Поиск по сайту: |
|
По базе: |
|
Главная страница > Применение > Микроконтроллеров > AVR |
|
|||||||||
Рекомендация по применению AVR242;**** Рекомендация по применению AVR242 ************************ ;* ;* Наимен.: Устройство дин. управления светодиодами и опроса клавиатуры 4х4 ;* Версия: 1.0 ;* последнее обновление: 98.07.24 ;* Микроконтроллер: Любой AVR-микроконтроллер ;* ;* Поддержка через E-mail:avr@atmel.com ;* ;* Описание: ;* Данное приложение выполняет функции промышленного таймера или часов реального ;* времени с 24 часовым форматом счета времени с двойным назначением линий ;* ввода-вывода. Ввод организован через матричную клавиатуру 4х4, вывод данных ;* осуществляется на 4 разрядный цифровой светодиодный индикатор и два ;* дискретных светодиода, имитирующих вкл./выкл. нагрузки. Вместо данных ;* светодиодов можно применить согласовывающие элементы для управления внешней ;* нагрузкой. Нажатие на клавиши подтверждается звуковым сигналом, генерируемого ;* пьезокерамическим излучателем. В состав входит основная программа, ;* которая позволяет с помощью клавиатуры установить реальное время и времена ;* вкл./выкл. нагрузок, выполняет функции счета реального времени, сканирования ;* клавиатуры. Пример написан для микроконтроллера AT90S1200 для демонстрации ;* возможности преодоления ограничений ввода-вывода. Но можно применить любой ;* AVR-микроконтроллер, для чего необходимо откорректировать вектора, ;* ЭСППЗУ и указатель стека. ;* В схеме тактирования предполагается использование кварца 4.096 МГц ;* (4 МГц кварц создаст погрешность -0.16%, если в таймер перезагружать код 178, ;* а не 176,как в этом примере, следовательно, в программу необходимо внести ;* небольшие изменения. Таблица преобразования, записанная в ЭСППЗУ, хранит ;* семисегментные коды для индикатора, в т.ч. со специальными символами ;* для установки текущего времени и времен включения/выключения, а также коды ;* клавиш. Если ЭСППЗУ запланировано использовать в других целях, то таблицы ;* можно перенести в память программ, но с учетом использования более мощного ;* микроконтроллера. ;*************************************************************************** ;***** Регистры используемые в пределах всей программы ;******Глобальные переменные, используемые процедурами .def loset =r1 ;содержит минуты после установки .def hiset =r2 ;содержит часы после установки .def ld1minon =r3 ;время включения нагрузки 1 (минуты) .def ld1hron =r4 ;время включения нагрузки 1 (часы) .def ld1minoff =r5 ;время выключения нагрузки 1 (минуты) .def ld1hroff =r6 ;время выключения нагрузки 1 (часы) .def ld2minon =r7 ;время включения нагрузки 2 (минуты) .def ld2hron =r8 ;время включения нагрузки 2 (часы) .def ld2minoff =r9 ;время выключения нагрузки 2 (минуты) .def ld2hroff =r10 ;время выключения нагрузки 2 (часы) .def temp =r16 ;универсальный временный регистр .def second =r17 ;счетчик секунд часов реального времени (ЧРВ) .def minute =r18 ;счетчик минут ЧРВ .def hour =r19 ;счетчик часов ЧРВ .def mask =r20 ;маска мигания разрядов .def blink =r21 ;Счетчик скорости мигания двоеточия .def bounce =r22 ;Счетчик антидребезга клавитатуры .def flash =r23 ;счетчик задержки зажигания .def lobyte =r24 ;хранение разрядов минут для функции display .def hibyte =r25 ; хранение разрядов часов для функции display .def key =r26 ;Кол нажатой клавиши после опроса клавиатуры ;***'key' значения возвращаемые 'keyscan'*************************** ;Код 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ;Кнопка 1 2 3 4 F 5 6 E 7 8 9 D A 0 B C Нет нажатия ;Функция 1 2 3 LD1ON 4 5 6 LD1OFF 7 8 9 LD2ON SET 0 CLEAR LD2OFF .def tock =r27 ;5 мс импульс .def flags =r28 ; флаги команд клавиатуры ;7 6 5 4 3 2 1 0 ;5мс keyok ld2off ld2on ld1off ld1on ld2 ld1 ; tick 0 = вкл., 1 = выкл. .equ ms5 =7 ; 5мс интервалы для задания времени индикации одного разряда .equ keyok =6 ; устанавливается после подавления дребезга кнопки .equ ld2off =5 ;устанавливаются при нажатии кнопок задания времен .equ ld2on =4 ; включения или выключения нагрузок 1 и 2 .equ ld1off =3 ; .equ ld1on =2 .equ ld2 =1 ; разрешение управления нагрузками 2 и 1. Устанавливаются .equ ld1 =0 ; автоматически после задания соответствующих времен включения ;***T-флаг регистра статуса используется как флаг установки времени .equ clear =0 ;флаг изменения состояния ЧРВ (например, секунд) ;Линии порта B .equ col1 =0 ;Сегмент a индикатора/столбец 1 клавиатуры .equ col2 =1 ;Сегмент b индикатора/столбец 2 клавиатуры .equ col3 =2 ;Сегмент c индикатора/столбец 3 клавиатуры .equ col4 =3 ;Сегмент d индикатора/столбец 4 клавиатуры .equ row1 =4 ;Сегмент e индикатора/строка 1 клавиатуры .equ row2 =5 ;Сегмент f индикатора/строка 2 клавиатуры .equ row3 =6 ;Сегмент g индикатора/строка 3 клавиатуры .equ row4 =7 ;Сегмент : индикатора/строка 4 клавиатуры ;Линии порта D .equ A1 =0 ; Выходы управления общими анодами индикатора (активный низкий) .equ A2 =1 ; .equ A3 =2 ; .equ A4 =3 ; .equ LOAD1 =4 ;Выход нагрузки 1 (активный низкий) .equ LOAD2 =5 ;Выход нагрузки 2 (активный низкий) .equ PZ =6 ;Выход пьезокерамического излучателя (активный низкий) .include "1200def.inc" ;***** Регистры, используемые в процедуре обработки прерывания .def timer =r31 ;временный регистр для перезагрузки таймера .def status =r0 ; регистр для запоминания регистра статуса ;*****Таблица преобразования в семисегментный код ********************** .eseg ;Сегмент данных в ЭСППЗУ .org 0 table1: .db 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 ;Отобр.0 1 2 3 4 5 6 7 8 9 .db 0x86,0x8E,0xA3,0xAB,0XFF,0XFF ;Отобр. E f o n пробел спец. символы ;****Таблица преобразования нажатой клавиши в удобный для пользователя код *** ;key1 2 3 F 4 5 6 E 7 8 9 D A 0 B C table2: .db 1, 2, 3,15, 4, 5, 6,14, 7, 8, 9, 13, 10, 0, 11, 12 ;Значение 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ;****Код программы *************************************************** .cseg ; Сегмент кода программы .org 0 rjmp reset ;обработка сброса nop ;не исп. прерывание rjmp tick ;переполнение таймера (5 мс) nop ;неиспользуемое прерывание аналогового компаратора ;*** Сброс ************************************************** ;*** инициализация порта, таймера и прерывания reset: ser temp ; out DDRB,temp ;настройка порта В на вывод out DDRD,temp ;настройка порта D на вывод out PORTB,temp ;все столбцы =1 / выключение сегментных светодиодов out PORTD,temp ;выключение светодиодов и нагрузок ldi temp,0x04 ;установка коэффициента предделения таймера 256 out TCCR0,temp ldi timer,176 ;настройка периода переполнения на 5мс out TCNT0,timer ;(256 - n)*256*0.2441 мкс ldi temp,0x02 ;разрешение прерывания таймера out TIMSK,temp clr flags ;очистка флагов управления clr tock ;очистка 5мс счетчика clr bounce ;очистка счетчика дребезга клавиши clr flash clr blink sei ;разрешение глобальных прерываний ;** Предупреждающее мигание символами EEEE на индикаторах** ;****Ожидает нажатия кнопки SET на клавиатуре timesetting: ldi hibyte,0xaa ; запись символов "EEEE" ldi lobyte,0xaa ;для отображения ser mask ;и установка мигания индикатора notyet: rcall display ;индикация и опрос клавиатуры brtc notyet ;ожидание нажатия клавиши SET rcall setrtc ; установка времени mov hour,hiset ; и обновление часов mov minute,loset ;и минут clt ;очистка Т-флага ;***** Основной цикл сервисных функций *************************** do: clr mask ;начало выполнения функций cpi blink,100 ;если прошло 0.5с, brne nohalf clr blink com flash ;то инверсия мигания nohalf: cpi second,60 ; прошла 1 минута? brne nochange ;нет clr second ;да, очистка секунд и inc minute ;увеличение минут mov temp,minute andi temp,0x0f ;маскирование ст. разр. минут cpi temp,10 ; прошло 10 минут? brne nochange ;нет andi minute,0xf0 ; очистка мл. разряда минут ldi temp,0x10 add minute,temp ;инкремент ст. разряда минут cpi minute,0x60 ; прошло 60 минут? brne nochange ; нет clr minute ; да, очистка минут и inc hour ;увеличение часов mov temp,hour andi temp,0x0f ;маскирование ст. разряда часов cpi temp,10 ;прошло 10 часов? brne nochange ;нет andi hour,0xf0 ;да, инкремент ldi temp,0x10 add hour,temp ;ст. разряда часов nochange: cpi hour,0x24 ;прошло 24 часа? brne sameday ;нет, clr hour ;да, очистка переменных времени clr minute ;для начала отсчета времени нового дня clr second sameday: ;Обновление времени mov lobyte,minute mov hibyte,hour rcall display ;отображение времени за 20 мс brtc case1 ;переход, если нет нажатия кнопки SET rcall setrtc ;переустановка времени mov hour,hiset ;обновление часов mov minute,loset ; и минут clt ;очистка флага Т case1:sbrc flags,ld1 ;нагрузка 1 включена? rjmp chkload1 ;да, проверка на необходимость выключения нагрузки 1 case2:sbrc flags,ld2 ;нагрузка 2 включена? rjmp chkload2 ; да, проверка на необходимость выключения нагрузки 2 case3: sbrc flags,ld1on ;время включения нагрузки 1 установлено? rjmp setld1on ;нет, установка времени включения case4: sbrc flags,ld1off ;время выключения нагрузки 1 установлено? rjmp setld1off ;нет, установка времени выключения case5: sbrc flags,ld2on ;время включения нагрузки 2 установлено? rjmp setld2on ;нет, установка времени включения case6: sbrc flags,ld2off ;время выключения нагрузки 2 установлено? rjmp setld2off ;нет, установка времени выключения case7: rjmp do ;переход на начало основного цикла ;* Обработка событий по достиж.времен вкл./выкл. нагрузок и нажатиях клавиатуры* chkload1: cp hour,ld1hroff; время выключения достигнуто? brne onload1 cp minute,ld1minoff brne onload1 sbi PORTD,LOAD1; да, выключить нагрузку 1 onload1: cp hour,ld1hron; время включения нагрузки 1 достигнуто? brne case2 cp minute,ld1minon brne case2 cbi PORTD,LOAD1; да, включить нагрузку 1 rjmp case2;переход на действия при включенной нагрузке chkload2: cp hour,ld2hroff;время выключения нагр.2 достигнуто? brne onload2 cp minute,ld2minoff brne onload2 sbi PORTD,LOAD2;да, выключить нагрузку 2 onload2: cp hour,ld2hron;время включения нагрузки 2 достигнуто? brne case3 cp minute,ld2minon brne case3 cbi PORTD,LOAD2;да, включить нагрузку 2 rjmp case3;переход на действия с включенной нагрузкой setld1on: sbr flags,0x01;установка флага активизации функции управл. нагрузкой 1 rcall setrtc; установка нового времени включения mov ld1hron,hiset ;и запоминание mov ld1minon,loset cbr flags,0x04; очистка флага ld1on rjmp case4 setld1off: rcall setrtc ;установка времени выключения mov ld1hroff,hiset ;и запоминание mov ld1minoff,loset cbr flags,0x08 ;очистка флага ld1off rjmp case5 setld2on: sbr flags,0x02;установка флага активизации функции управл. нагрузкой 2 rcall setrtc; установить новое время mov ld2hron,hiset; и сохранение mov ld2minon,loset cbr flags,0x10; очистка флага ld2on rjmp case6 setld2off: rcall setrtc; установка нового времени включения mov ld2hroff,hiset; и сохранение mov ld2minoff,loset cbr flags,0x20; очистка флага ld2off rjmp case7 ;****Процедура динамического управления индикацией и сканирования клавиатуры**** display: ser temp ;выключение индикатора out PORTB,temp ;**** сканирование клавиатуры и установка флагов нажатия клавиш*************** keyscan: cbr flags,0x40 ;сброс флага нажатия клавиши ldi key,0x10 ;установка значения нет нажатой клавиши ser temp ; установка высоких уровней на порте клавиатуры out PORTB,temp ; in temp,PORTD ;выключение индикатора без влияния на состояние нагрузки ori temp,0x0f ;на время out PORTD,temp ;сканирования клавитатуры ldi temp,0x0f ;установка столбцов на выход и out DDRB,temp ;строк на вход с подтягивающими резисторами ldi temp,0xf0 ;и возбуждение столбцов out PORTB,temp ;мл. тетрада готова для опроса ldi temp,20 ;короткое время установления tagain1: dec temp brne tagain1 sbis PINB,ROW1 ;поиск нажатия в строке ldi key,0 ;и установка указателя строки sbis PINB,ROW2 ldi key,4 sbis PINB,ROW3 ldi key,8 sbis PINB,ROW4 ldi key,12 ldi temp,0xF0 ;изменение настроек порта В out DDRB,temp ;для поиска нажатия в столбце ldi temp,0x0F ;разрешение подтягивающих резисторов и out PORTB,temp ;запись нулей в строки ldi temp,20 ;короткое время установления tagain2: dec temp brne tagain2 ;задержка для установки новых настроек порта clr temp sbis PINB,COL1 ;найти нажатие в столбце ldi temp,0 ;и установить указатель столбца sbis PINB,COL2 ldi temp,1 sbis PINB,COL3 ldi temp,2 sbis PINB,COL4 ldi temp,3 add key,temp ;объединить указатели строк и столбцов cpi key,0x10 ;если нет нажатия breq nokey ;выход из процедуры, иначе ldi temp,0x10 add key,temp ;изменение к табл. 2 out EEAR,key ;загрузка адреса ЭСППЗУ (0 - 15) sbi EECR,EERE ;разрешение чтения ЭСППЗУ in key,EEDR ;чтение дешифрированного значения действительной клавиши convert: cpi key,10 ;это клавиша SET? brne notset ;нет, проверка следующей кнопки set ;да, установка флага Т в регистре статуса notset: cpi key,11 ;это кнопка CLEAR? brne notclear ;нет, проверка следующей кнопки sbi PORTD,LOAD1 ;да, выключение всех нагрузок sbi PORTD,LOAD2 cbr flags,0x03 ;сброс флагов включения нагрузок notclear: cpi key,15 ;это кнопка LD1ON? brne notld1on ;нет, проверка следующей кнопки sbr flags,0x04 ;да, установка флага LD1ON notld1on: cpi key,14 ;это клавиша LD1OFF? brne notld1off ;нет, проверка следующей клавиши sbr flags,0x08 ;да, установка флага LD1OFF notld1off: cpi key,13 ;это кнопка LD2ON? brne notld2on ;нет, проверка след. кнопки sbr flags,0x10 ;да, установка флага LD2ON notld2on: cpi key,12 ;это кнопка LD2OFF? brne notld2off ;нет, проверка следующей кнопки sbr flags,0x20 ;да, установка флага LD2OFF notld2off: ;***Звуковая сигнализация нажатия клавиш *********************** ;***генерирует 4кГц тон для пьезо-излучателя в течение 5мс ***** tactile: cbr flags,0x80 cbi PORTD,PZ ;включить излучатель на короткое время ldi temp,125 ; на короткое время t1again: dec temp brne t1again sbi PORTD,PZ ;включить излучатель ldi temp,125 ; на короткое время t2again: dec temp brne t2again sbrs flags,ms5 ;повтор в течение 5мс rjmp tactile notok: cpi bounce,40 brlo nokey sbr flags,0x40 ;установка флага окончания дребезга nokey: ser temp out DDRB,temp ;переинициализация порта В на вывод out PORTB,temp ;и выключение сегментов ;*** Процедура динамического управления индикацией **************** cbi PORTD,A1 ;включить разряд 1 mov temp,lobyte ;загрузить мл. разряд минут digit1: cbr flags,0x80 ;очистка 5мс флага хода часов andi temp,0x0f ;маскирование ст. тетрады out EEAR,temp ;установка адреса ЭСППЗУ (0 - 15) sbi EECR,EERE ;разрешение чтения из ЭСППЗУ in temp,EEDR ;считывание семисегментного кода sbrs flash,clear ;мигание каждые 0.5с or temp,mask ;наложить маску мигания на разряд out PORTB,temp ;запись в сегментные разряды и удержание 5 мс led1: sbrs flags,ms5 ;5 мс прошло? rjmp led1 ;нет, ждем пока пройдет sbi PORTD,A1 ;выключить разряд 1 ser temp ;очистка дисплея out PORTB,temp cbi PORTD,A2; mov temp,lobyte ;загрузка старшего разряда минут swap temp digit2: cbr flags,0x80 ;очистка 5 мс флага andi temp,0x0f ;маскирование старшей тетрады out EEAR,temp ;загрузка адреса ЭСППЗУ (0 - 15) sbi EECR,EERE ;разрешение чтения ЭСППЗУ in temp,EEDR ;считывание семисегментного кода sbrs flash,clear ;мигание каждые 0.5с or temp,mask ;наложить маску мигания на разряд out PORTB,temp ; запись в сегментные разряды и удержание 5 мс led2: sbrs flags,ms5 ; 5 мс прошло? rjmp led2 ;нет, ждем пока пройдет sbi PORTD,A2 ; ser temp ;очистка индикатора out PORTB,temp cbi PORTD,A3 ; mov temp,hibyte ; загрузка мл. разряда часов digit3: cbr flags,0x80 ;очистка 5 мс флага andi temp,0x0f ;маскирование ст. тетрады разряда out EEAR,temp ;загрузка адреса ЭСППЗУ (0 - 15) sbi EECR,EERE ;разрешение чтения ЭСППЗУ in temp,EEDR ;считывание семисегментного кода sbrs second,clear ; andi temp,0x7f ; добавить индикацию секунд : sbrs flash,clear ;мигание каждые 0.5с or temp,mask ;наложение маски мигания out PORTB,temp ; запись в сегментные разряды и удержание 5 мс led3: sbrs flags,ms5 ;5 мс прошло? rjmp led3 ;не, ожидаем пока пройдет sbi PORTD,A3 ser temp ;очистка индикатора out PORTB,temp cbi PORTD,A4; mov temp,hibyte ; загрузка старшего разряда часов swap temp andi temp,0x0f ;ст. разряд часов равен 0? brne digit4 ldi temp,0xff ;да, выключить разряд digit4: cbr flags,0x80 ;очистка 5 мс флага andi temp,0x0f ;маскирование старшей тетрады out EEAR,temp ;загрузка адреса в ЭСППЗУ (0 - 15) sbi EECR,EERE ;разрешение чтения из ЭСППЗУ in temp,EEDR ;считывание семисегментного кода sbrs flash,clear ;мигание каждые 0.5с or temp,mask ;наложение маски мигания out PORTB,temp ; запись в сегментные разряды и удержание 5 мс led4: sbrs flags,ms5 ;5 мс прошло? rjmp led4 ;нет, ждем опять sbi PORTD,A4 ser temp ;очистка индикатора out PORTB,temp tst mask ;мигание завершено? breq outled ;да, выход cpi blink,50 ;время мигания прошло? brlo outled ;нет, выход clr blink ;да, очистка счетчика скорости мигания com flash ;и инверсия байта зажигания outled: ret ;****Функция установки часов реального времени/времен включения-выключения в ;часах и минутах под управлением клавиатуры ;****возвращает минуты в 'loset' часы в 'hiset' setrtc: ser mask ;установка мигания индикатора ldi hibyte,0xdf ;запись кода 'n' в старший разряд часов ser lobyte ;и выключение мл. разрядов минут и часов hihrus: clr bounce bounce1: rcall display ;Индикация и опрос клавиатуры sbrs flags,keyok rjmp bounce1 cbr flags,0x40 ;очистка флага keyok cpi key,0x03 ; Старший разряд часов > 2 ? brsh hihrus ; если да, что считываем кнопки снова hihrok: ; если нет, то корректный вход swap key ;перемещение значения старшего разряда часов в старшую тетраду mov hiset,key ; и запись в регистр установки часов ldi hibyte,0x0d ; запись 'n' в мл. разряд часов add hibyte,hiset ;добавляем к hihour код 'n' lohrus: clr bounce bounce2: rcall display ; Индикация и опрос клавиатуры sbrs flags,keyok ;клавиша нажата? rjmp bounce2 ; нет – повтор снова cbr flags,0x40 ;да – очистка флага keyok mov temp,hibyte ;Проверка общего значения часов andi temp,0xf0 ;на непревышение 24 add temp,key cpi temp,0x24 ;часы >24? brsh lohrus ;да – чтение кнопки снова add hiset,key ;нет – объединить ст. и мл. разряды часов lohrok: mov hibyte,hiset ;отображение установленных часов ldi lobyte,0xdf ;записать код 'n' в старший разряд минут himinus: clr bounce bounce3: rcall display ; индикация и опрос клавиатуры sbrs flags,keyok rjmp bounce3 cbr flags,0x40 ;очистка флага keyok cpi key,6 ; ст. разряд минут >5 ? brsh himinus ;нет – чтение клавиатуры снова lominok: swap key ;перемещение ст. разр. мин. в старшую тетраду mov loset,key ; и сохранение минут ldi lobyte,0x0d ; записать 'n' в мл. разряд минут add lobyte,loset ;и объединить этот код с ст.разрядом минут lominus: clr bounce bounce4: rcall display ; индикация и опрос клавиатуры sbrs flags,keyok rjmp bounce4 cbr flags,0x40 ;очистка флага keyok cpi key,10 ;клавиша >9 ? brsh lominus ; нет- снова чтение кнопок add loset,key ;да – сложить ст. и мл. разряды минут clr mask ;сброс мигания разрядов ret ;и выход с установками времени ;****Процедура обработки прерывания по переполнению таймера************** ;*Вызывается каждые 5мс для обновления флага хода часов, счетчиков мигания и антидребезга tick: in status,SREG ;сохранение регистра статуса при входе inc tock ;+ 1 счетчика 5мс периодов 'tock' inc blink ; + 1 счетчика частоты мигания inc bounce ; + 1 счетчика задержки на дребезг контактов sbr flags,0x80 ;установка флага хода часов (5 мс) cpi tock,200 ;прошла 1 секунда? breq onesec ;да, прибавляем 1 секунду nop ;балансировка времени прерывания rjmp nosecond ;нет, секунда еще не прошла onesec: inc second ;прибавление 1 к секундам clr tock ;очистка 5мс счетчика nosecond: ldi timer,176 ;перезагрузка таймера out TCNT0,timer out SREG,status ;восстановление регистра статуса reti ;возврат к основному процессу Главная - Микросхемы - DOC - ЖКИ - Источники питания - Электромеханика - Интерфейсы - Программы - Применения - Статьи |
|
Впервые? | Реклама на сайте | О проекте | Карта портала тел. редакции: +7 (995) 900 6254. e-mail:info@eust.ru ©1998-2023 Рынок Микроэлектроники |
|