В данном примере рассмотрим динамическую индикацию и узнаем что это за зверь такой. Основной принцип действия динамической индикации заключается в том что вывод значения осуществляется последовательно. Сначала на однин сегмент а затем на другой. Человеческий глаз не в силу уловить эти колебания, так как зрение человека инертно. Динамическая индикация применяется в том случае когда мы нам нужно отобразить более двух чисел. Если бы мы применяли статическую индикацию то нам нужно было использовать дополнительные порты микроконтроллера, количество которых ограничено.
В данном примере мы подключим два семисегментных индикатора с общим анодом. Есть также семисегментные индикаторы с общим катодом - принцип работы их идентичен с той лишь разницей что нужно правильно соблюдать полярность. Мы будем последовательно выводить значения числа, которое увеличивается в памяти микроконтроллера с 0 до 99 с определенным периодом. Для вывода двухзначного числа нам необходимо сначала разложить его на разряды т.е. узнать сколько у нас десятков и сколько единиц а только потом производить отображение.
В семисегментом индикаторе семь сегментов, для того чтобы зажечь один сегмент нужно на его вход подать логический "ноль" . Каждый сегмент имеет свое обозначение. Обозночаются они латинскими буквами "a,b,c,d,e,f,g". Обозначение начинается с верхнего и далее по часовой стрелки. Оставшийся сегмент "g" это центральный светодиод. Для защиты микроконтроллера от превышения допустимого тока на выводах порта установлены сопротивления, ограничивающие протекающие через них ток и в тоже время обеспечивающие нормальное свечение сегмента индикатора.
Для того чтобы отобразить определенную цифру, нужна определенная последоветельность байтов, которая одновременно подяется на порт микроконтролллера. Для этого мы в программе объявили массив записав в него определенное значение, для наглядности это значение мы представили в бинарном виде "0x0000000". К примеру это значение зажет все сегменты, каждый бит отвечет за свой сегмент.
#include <avr/io.h> #include <avr/delay.h> #include <avr/interrupt.h> char numarray[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; unsigned char num=0; unsigned char raz1,raz2; int seg=0; ISR (TIMER0_OVF_vect){ switch(seg) { case 0: PORTD=~numarray[raz1]; break; case 1: PORTD=~numarray[raz2]; break; } PORTB =(1<<seg); seg++; if(seg>2) seg=0; TCNT0=190; } int main(void) { DDRD=0xff; DDRB=0xff; PORTB=0x00; //Настраиваем таймер TCCR0 |=(0<<CS02)|(1<<CS01)|(1<<CS00); TIMSK |=(1<<TOIE0); //------------------------ asm("sei"); while(1) { if (num>99) num=0; _delay_ms(600); num=num+1; raz1=num/10; raz2=num-10*raz1; } }
В главном методе сначала настраиваем таймер TIMER0 . Прерывание по переполнению происходит в случае переполнении счетного регистра TCNT0.;В векторепрерывания значение счетного регистра выставлено в 190. Это для сделано для того чтобы получить определенную частоту прерывания. Это значение подобрано опытном путем. Вы можете сами "поиграться" с этим значением. Если его выставить в ноль то видно как будет моргать цифры на индикаторе, это говорит о том что наше зрение уловило эти колебания и значение TCNT0 нужно ;увеличить.
Схему приводить не буду, тут и так все понятно. Порт D подключен к сегментам индикатора. Нулевой и первый пин порта B подключаем к анодам индикаторов.