|  |  | |||||||||||||||
| 
 Динамическая индикация 
    Автор: Владимир Итак, девочки и мальчики, сегодня дядя Сережа расскажет о том, как соорудить динамическую индикацию в домашних условиях, че это ваще такое, и зачем оно нам. Не вдаваясь в нудные предисловия скажем так: Динамическая индикация – это метод отображения целостной картины через быстрое последовательное отображение отдельных элементов этой картины. Причем, «целостность» восприятия получается благодаря инерционности человеческого зрения. На этом принципе, как вы догадываетесь, построено кино и телевидение. Не слишком занудно? Поконкретнее. Скажем, нам нужно организовать вывод какого-то числа на 7-сегментные индикаторы. Ну, например, мы делаем часы, или термометр, или еще чего-нибудь. Давайте посчитаем, сколько понадобится проводов, чтобы подключить индикаторы. Кстати, индикаторы выглядят примерно вот так:  Уделим пару слов увиденному. Перед нами – самый обычный светодиодный 7-сегментный индикатор. Вопрос: почему 7-сегментный, когда сегментов на самом деле – восемь? Ответ: потому что 8-й сегмент – это точка, которая не входит в изображение цифры и вообще, является необязательной. Бывают индикаторы и без точек. Для нумерации сегментов используются латинские буквы от a до h . У всех всех всех 7-сегментных индикаторов в нашем бренном мире, сегменты нумеруются в том порядке, как это показано на рисунке, и никак иначе. Теперь смотрим на схемы. Во-первых, почему их две? Да потому что индикаторы бывают разные. Бывают – с общим катодом (ОК), бывают – с общим анодом (ОА). Среди буржуйских более распространены, как ни странно, индикаторы с ОА. Но встречаются и с ОК. Так что – нужно быть осторожным, чтоб не спутать. Хотя, нам-то все равно. Нашими индикаторами будет управлять контроллер. А его можно запрограммировать как на работу с ОК так и с ОА. Тут сложностей нет. У каждого индикатора – 9 ножек. С 1 по 8 – выводы сегментов, 9-я – общий. Допустим, мы хотим отображать 4-разрядное число. Надо 4 индикатора. Арифметика маленького Пети: 8*4 = 32. То есть, нам потребуется 32 провода (не считая общие) Неслабо? Ничуть. Тем более, учитывая, что у большинства контроллеров количество каналов ввода/вывода как раз равно 32. Как-то меня не очень греет перспектива угрохать все выводы контроллера на индикацию. А вас? Ведь надо ж еще куда-то подключить кнопочки, ручечки, датчички и пр. пр. пр. а мало ли чего? Кстати, у любимого нами AT 90 s 2313 всего 15 каналов ввода/вывода. Как здесь прикажете быть? Вот тут нам и поможет динамическая индикация. Делаем очень просто: подключаем все индикаторы параллельно. Точнее, сажаем выводы сегментов на общую шину. А общие провода оставляем раздельно. Смотрим небольшой поясняющий мультик:  Че мы делаем? Мы последовательно подаем напряжение на адресные входы индикаторов, и одновременно выдаем в шину данных 7-сегментный код, соответствующий индикатору, активному в данный момент. Все. Прекращаю кормить Вас баснями. Сейчас мы пишем прогу. В этой проге мы выведем на 4-разрядный индикатор число 1234. Вот тут то нам и понадобится узнанное в предыдущей главе об оперативной памяти. Итак, я хочу, чтобы значения цифр, выводимых на индикацию, лежали в ячейках памяти. Поскольку у индикатора 4 разряда – значит цифр тоже будет 4, и соответственно, столько же ячеек памяти. Дабы не заморачиваться, мы объединяем все четыре ячейки в переменную Digit . Итак, пишем: .include "d:avravrasmappnotes2313def.inc" .def Temp1=R16 .def Temp2=R17 .def Temp3=R18 .def Temp4=R19 .def Temp=R20 .dseg Digit: .byte 4 Написали.  Поскольку у нас на порт B уже повешены светодиоды – наверно не будет большим криминалом повесить туда еще и сегменты индикаторов. Порт D пока что пустует – ну дык значит посадим туда общие провода. Рисуем схему:  Схему прошивки, как и договаривались, не показываем, но подразумеваем ее наличие. В данной схеме используется два сдвоенных индикатора C562. Эти индикаторы – с общим катодом (об этом говорит буква C в названии). Будем иметь это ввиду при написании программы. Вы можете поставить совершенно любые индикаторы, какие будут под рукой. Можно, например, поставить один счетверенный, или четыре одинарных. Также, можно ставить индикаторы с общим анодом – в программе только придется дописать пару строчек – совершенно ничего сложного… Резисторы в шине данных взяты меньшего номинала, чем были. Зачем? Чтоб ярче светили светодиоды. Поскольку индикация динамическая, то каждый индикатор работает только 1/4 общего времени работы схемы. Глаз это воспринимает как пропорциональное уменьшение яркости свечения (т.е. – тоже в 4 раза.). Чтобы как-то компенсировать этот недостаток, на светодиоды подается завышенный ток (больше максимально допустимого). В статическом режиме этот ток может причинить светодиодам вред. Однако в динамическом режиме, кратковременные воздействия тока не столь фатальны. Ну вот, вроде все. Теперь пишем программулину дальше. 
.cseg
.org 0
              rjmp RESET    ; Reset Handler
              rjmp EXT_INT0 ; IRQ0 Handler
              rjmp EXT_INT1 ; IRQ1 Handler
              rjmp TIM_CAPT1 ; Timer1 Capture Handler
              rjmp TIM_COMP1 ; Timer1 Compare Handler
              rjmp TIM_OVF1 ; Timer1 Overflow Handler
              rjmp TIM_OVF0 ; Timer0 Overflow Handler
              rjmp UART_RXC ; UART RX Complete Handler
              rjmp UART_DRE ; UDR Empty Handler
              rjmp UART_TXC ; UART TX Complete Handler
              rjmp ANA_COMP ; Analog Comparator Handler
EXT_INT0  :	ret
EXT_INT1  :	ret
TIM_CAPT1 :	ret
TIM_OVF0  :	ret
TIM_OVF1  :   ret
UART_RXC  :   ret
UART_DRE  :   ret
UART_TXC  :   ret
ANA_COMP  :   ret
TIM_COMP1 :   ret
reset:        ldi Temp1,RamEnd	;инициализация стека
              out SPL,Temp1
              cli
              ldi Temp,0b11111111 ;настройка портов
              out ddrb,Temp
              ldi Temp,0b00001111
              out ddrd,Temp
              ldi Temp,4
              sts Digit  ,Temp      ;загрузка начальных сначений
              ldi Temp,3
              sts Digit+1,Temp
              ldi Temp,2
              sts Digit+2,Temp
              ldi Temp,1
              sts Digit+3,Temp
;*********************************************************
;MAIN
;*********************************************************
IndicCycle:   rcall Display        ;цикл индикации
              rjmp IndicCycle
;*********************************************************
Display:
;последовательный вывод на индикацию содержимого
;переменной Digit
              lds Temp1,Digit      ;загружаем 0-ю ячейку
              ldi Temp,0b00001110  ;активируем 0-й разряд
                                   ;индикации
              out PortD,Temp
              rcall Decoder        ;вызываем 7-сегм. декодер
              out PortB,Temp1      ;выводим значение в порт
              rcall Delay1         ;ждем
              lds Temp1,Digit+1    ;и .т.д
              ldi Temp,0b00001101
              out PortD,Temp
              rcall Decoder
              out PortB,Temp1
              rcall Delay1
              lds Temp1,Digit+2
              ldi Temp,0b00001011
              out PortD,Temp
              rcall Decoder
              out PortB,Temp1
              rcall Delay1
              lds Temp1,Digit+3
              ldi Temp,0b00000111
              out PortD,Temp
              rcall Decoder
              out PortB,Temp1
              rcall Delay1
              ret
;*********************************************************
Decoder:
;преобразование двоичного числа
;в код 7-сегментного индикатора
              ldi ZL,Low(DcMatrix*2)   ;инициализация массива
              ldi ZH,High(DcMatrix*2)
              ldi Temp2,0             ;прибавление переменной
              add ZL,Temp1            ;к 0-му адресу массива
              adc ZH,Temp2
              lpm                     ;загрузка значения
              mov Temp1,r0
              ret
DcMatrix:
;массив - таблица истинности декодера
              ;     hgfedcba   hgfedcba
              .db 0b00111111,0b00000110	;0,1
              .db 0b01011011,0b01001111	;2,3
              .db 0b01100110,0b01101101	;4,5
              .db 0b01111101,0b00000111	;6,7
              .db 0b01111111,0b01101111	;8,9
;*********************************************************
Delay1:
;цикл задержки
              push Temp1
              push Temp2
              ldi Temp1,0
              ldi Temp2,50
d11:          dec Temp1
              brne d11
              dec Temp2
              brne d11
              pop Temp2
              pop Temp1
              ret
Очень внимательно читаем программу. 
Сначала мы настраиваем прерывания, порты и стек. Это стандартно.  Вот так, в общих чертах, все просто и понятно.  Далее мы сделаем из этого дела секундомер. <<--Вспомним пройденное----Поехали дальше-->> 
 Эти статьи вам тоже могут пригодиться: |  | |||||||||||||||
|  |  | 


|  |  | |||
|  | ||||
|  |  | |||
 
			 
			 
			
			

