В продолжение урока, рассмотрим динамическую индикацию. Если вы внимательно изучили статическую индикацию, то знаете, что сегментный индикатор это набор светодиодов. Для того, чтобы подключить индикатор, нужно 7 ножек микроконтроллера. Но, вдруг нам понадобилось использовать несколько индикаторов, например 2, 3, 4…
Тогда нам понадобится уже 14, 21, 28 ножек, а ножек итак мало… Тут нам на помощь приходит динамическая индикация. Основная задача динамической индикации — снизить количество используемых ножек микроконтроллера. Обратите внимание на схеме задействовано 9, а не 14 ножек. Ножки управления все подключены параллельно.
В общем смысле работает данная конструкция следующим образом: вначале выводится конфигурация первого числа на общую шину и включаем PB1. Первый индикатор загорается, с нужным числом. Затем его гасим, выводим конфигурацию второго числа на шину данных, зажигаем второй индикатор, выключаем.
Более детально. В первый момент времени все выключено PORTB=0x00; PORTD=0xFF; так как схема с общим «+», анодом. Далее на PORTD посылается конфигурация первого числа, например «0». Из статической индикации мы помним:
case 0: { PORTD=0xC0; break; } |
Но обратите внимание, «+» подключен к PORTB.1, т.е. чтобы зажечь сегмент нужно включить ножку PORTB.1=1;
Во второй момент времени, снова все выключаем, посылаем конфигурацию второго числа и включаем, на этот раз, второй индикатор. Далее повторяем.
При высоких частотах, человеческий глаз не способен разглядеть эти переключения, и кажется что индикатор горит постоянно. Рекомендуется не использовать частоты кратные 50Гц. В своем тестовом проекте я использовал 120Гц. Таймер настроен на частоту 1МГц. Код обрабатывается в прерывании таймера1. Прерывание вызывается 240 раз в секунду, потому что индикаторов два, поэтому 1000 000/240=4166 или 0x1046 пихаем в регистр сравнения. Протеус подружить с динамическим индикатором не удалось, зато на железе заработало сразу.
Обратите внимание!!! При подсоединении индикатора, на каждый сегмент рекомендуется вешать токоограничивающий резистор, а не один общий. Также, рекомендую включать общий провод индикатора через транзистор, иначе можно спалить ножку.
Для схемы с общим анодом
Для схемы с общим катодом
В качестве тестовой прошивки использовал таймер из предыдущего проекта.
Видео работы прошивки
Какова частота мерцания в данном проекте? Помогите пожалуйста посчитать и разобраться с таймерами, а то в уроке про таймеры совершенно не понятно что откуда берётся.
Обновлено
Большое спасибо 😛
Подскажите пожалуйста какие транзисторы лучше использовать в схеме (крайне желательно в корпусе TO92 или подобном) или какие параметры у них должны быть.
нужно грубо прикинуть ток, например у SA56-11G один сегмент потребляет максимум 25ма, всего сегментов 8, значит максимальный ток будет 200ма. При динамической индикации, ток конечно будет меньше, да и вряд ли все сегменты будут гореть одновременно, но лучше всегда брать с запасом, по току более 200ма, как вариант BC337-25.
Добавьте пожалуйста код для четырех семисегментников
Код практически не изменится, нужно добавить в прерывании условие включения 3 и 4 индикатора, аналогично 1 и 2. И пересчитать прерывание
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
PORTB=0x00;
if(i==0){n=n1;PORTB.0=1;i++;}
if(i==1){n=n2;PORTB.1=1;i++;}
if(i==2){n=n3;PORTB.2=1;i++;}
else{n=n4;PORTB.3=1;i=0;}
switch(n)
{
case 0:{PORTD=0b10001000;break;}
case 1:{PORTD=0b11101011;break;}
case 2:{PORTD=0b01001100;break;}
case 3:{PORTD=0b01001001;break;}
case 4:{PORTD=0b00101011;break;}
case 5:{PORTD=0b00011001;break;}
case 6:{PORTD=0b00011000;break;}
case 7:{PORTD=0b11001011;break;}
case 8:{PORTD=0b00001000;break;}
case 9:{PORTD=0b00001001;break;}
}
}
правильный ли это код для 4-ёх семисегментников? У меня не робит почему-то, горят только 2 разряда, а ещё 2 последних не откликаются и даже при то, что задано чтобы они показывали 0123, они показывают 22 тупо и всё… Помогите начинающему прогерру
в выборе свитч писал сам под свои индикаторы и на таймере всё работало, этот блок можно не проверять все цифирки правильные. Если надо, то схему могу прислать.
Попробуйте так:
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
PORTB=0×00;
switch(i)
{
case 0: n=n1;PORTB.0=1;i++; break;
case 1: n=n2;PORTB.1=1;i++; break;
case 2: n=n3;PORTB.2=1;i++; break;
case 3: n=n4;PORTB.3=1;i=0; break;
}
switch(n)
{
case 0:{PORTD=0b10001000;break;}
case 1:{PORTD=0b11101011;break;}
case 2:{PORTD=0b01001100;break;}
case 3:{PORTD=0b01001001;break;}
case 4:{PORTD=0b00101011;break;}
case 5:{PORTD=0b00011001;break;}
case 6:{PORTD=0b00011000;break;}
case 7:{PORTD=0b11001011;break;}
case 8:{PORTD=0b00001000;break;}
case 9:{PORTD=0b00001001;break;}
}
}
Всё равно не работает, лучше, но не работает… последние два разряда всё равно не горят…
тогда схему и прошивку целиком нужно смотреть, можете выложить на форуме, или на почту мне прислать
Роман, а у Вас 2й и 3й пины порта В объевлены, как выходы? Т.е. DDRB = 00001111, или DDRB = 0x0F, что-то такое есть? 🙂
Ether, спасибо, попался я на простом 😛 😛 😛
Нужна ещё помощь. На 4-ёх индикаторах мерцает на таких вот настройках таймера:// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 8,192 ms
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x01;
OCR1AL=0x04;
OCR1BH=0x00;
OCR1BL=0x00;
Подскажите настройки чтобы пошустрее мигало(незаметно т.е.)
В генераторе кода поменяйте Mode: Normal top=0xFFFF на Mode: CTC top=OCR1A,
здравствуйте,подскажите пожалуйста…
у меня такой вопрос — как вывести информацию на LCD и 7seg …
точнее сказать так: хочу чтоб в схеме были два индикатора — один lcd другой 7seg,но чтоб информация выводилась (я делаю спидометр)скорость на 7seg ,а одометр и всякая другая информация на lcd(т.е. одометр)….
я запутался и что то вообще не могу разобраться помогите с трудностями пожалуйста….
здравствуйте,подскажите пожалуйста…
у меня такой вопрос — как вывести информацию на LCD и 7seg …
точнее сказать так: хочу чтоб в схеме были два индикатора — один lcd другой 7seg,но чтоб информация выводилась (я делаю спидометр)скорость на 7seg ,а одометр и всякая другая информация на lcd(т.е. одометр)….
я запутался и что то вообще не могу разобраться помогите с трудностями пожалуйста….буду длягодарен если скинете исходный код по этому делу…
какие проблемы, 3 урок вывод на LCD, урок 6.1 вывод на семисегментник статической индикацией. там и исходники и объяснение.
Спасибо разобрался,там я сам напутал в переменных…спасибо за ответ…
Добрый день,у меня такой вопрос как подключить и7seg индикатор к AVR через регистр сдвига и как им управлять…помогите разобрать…
про это будет статья в ближайшее время
спасибо за ответ,жду с нетерпением,уж сильно нужно так как ног порой маловато бывает…
Здравствуйте. Хочу собрать частотомер с динамической индикацией. Подскажите пожалуйста, как полученный результат разложить на разряды, чтобы потом его поочередно вывести на семисегментные индикаторы? Хотя бы просто подскажите в каком направлении двигаться… Заранее спасибо
i[0]= freq/1000; //тысячи
i[1]= freq/100; //сотни
i[2]= freq/10; //десятки
i[3]= freq%10; //единицы
Подскажите, если в коде прерывания написать #asm(«sei») другие виды прерываний могут сработать в любой момент независимо прерывание завершилось или нет. Необходимо что бы одно прерывание не приоритетное не мешало другому более приоритетному.
Другие виды прерываний не сработают если они не настроены, если прерывания мешают друг другу, можно при входе в не приоритетное прерывание отключать остальные #asm(«cli»)
Подскажите, как разбить float на разряды(13,85 например)?
Int разбиваю кодом ниже, а на float ругается.
chislo = 5931; // это int
....
number1=chislo%10; // 1ый разряд
number2=(chislo%100)/10; // 2ой разряд
number3=(chislo%1000)/100; // 3ий разряд
number4=(chislo%10000)/1000; // 4ий разряд
Спасибо!
num1 = result/10; //десятки
num2 = result%10; //единицы
num3 = ((float)result — (char)result)*10; //дробная часть, будет с небольшой погрешностью
а не подскажете. какие резисторы лучше всего использовать в данной схеме?
зависит от тока сегмента и питающего напряжения, если питание 5в и ток сегмента 20ма, то резистор нужен 5/0.02=250 ом, т.е 300 ом будет нормально
Здравствуйте
Подскажите как посчитать переменную скажем за 5 секунд,и вывести среднее значение в другую переменную.
Нужно создать задержку при которой выводилось на экран среденее значение а не бегали цифры хаотично.
Спасибо
Делаете прерывание раз в секунду, в нем считываете значение, каждое пятое прерывание обновляете значение на индикаторах.
наверное не так написал,как подсчитать переменную за 5 секунд,и вывести среднее значение х+х+х+х+х/5
думаю я вас понял правильно, так что см. пред. ответ
а как написать этот код,или где посмотреть пример
таймеры вам в помощь http://avr-start.ru/?p=414
у меня получается выводить иформацию раз в 5 секунд,а нужно средее значение полученное за 5 секунд
.будьте добры пример кода
спс
….interrupt ….. // по прерыванию раз в секунду
{
if(sek < 5) { i[sek] = result; sek++; } else { mid = (i[0]+i[1]+i[2]+i[3]+i[4])/5; sek = 0; } }
Доброго времени суток.
Все получилось, все работает… НО !
У меня задача немного интересней: считать данные с АЦП. Взял ваш урок для примера по АЦП, но не смог вписаться в код…. Почти сутки просидел…
Где вставить строку запроса с АЦП, чтоб потом она автоматом отработало..
num=((5.00*adc_data[0])/1024.00);