Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Программа счетчика с использованием прерываний
Здесь мы должны будем развернуться "по полной программе", т. е. включить в состав программы таблицу прерываний, написать секцию инициализации (RESET) и т. п. Таблицу прерываний мы включим полностью, т. к. для модели 2313 она невелика, а в дальнейшем, если потребуется, такой текст программы гораздо легче дорабатывать (с этой же целью я сохранил в тексте описания даже неиспользуемых прерываний). Учтите только, что старая программа (листинг 5.11) без использования прерываний, в принципе, годится почти для любой модели МК AVR без переделок (кроме самых младших моделей Tiny, где отсутствует порт D). А вот программа», приведенная далее, пригодна только для 2313 Classic (или ATtiny2313 в режиме Classic)— уже для собственно ATtiny2313 ее без переделок применить не получится, из-за того хотя бы, что число прерываний в последней заметно больше.

С учетом всего сказанного, код программы приведен в листинге 5.13.
/Программа счета нажатий в двоичном коде .device AT90S2313 .include "2313def.inc" /частота 4 МГц
.def temp = rl6 /рабочая переменная .def Count_time = rl7 /счетчик задержки .def Counter = rl8 /счетчик нажатий
.def Flag = rl9 /регистр флагов: если бит 0 установлен,
/то обнаружили нажатие и переходим к обнаружению отпускания
;========== прерывания ============
rjmp RESET /Reset Handle
rjmp INTO /External InterruptO Vector Address reti /External Interruptl Vector Address reti
/Timerl capture Interrupt Vector Address reti /Timerl compare Interrupt Vector Address reti
/Timerl Overflow Interrupt Vector Address rjmp TIMO /TimerO Overflow Interrupt Vector
Address reti /UART Receive Complete Interrupt Vector Address, reti /UART Data Register
Empty Interrupt Vector Address reti /UART Transmit Complete Interrupt Vector Address reti /Analog Comparator Interrupt Vector Address
/========== программа ============
INTO: /внешнее прерывание по кнопке
/первым делом запрещаем прерывания от кнопки
clr temp
out GIMSK,temp

/на всякий случай очищаем регистр флагов прерываний ldi temp,$FF
out GIFR,temp /GIFR очищается записью единиц
sbrs Flag,0 /проверяем бит 0 нашего регистра флагов
rjmp Pushjpin /если 0, то было нажатие
cbr Flag,1 /иначе было отпускание, очищаем бит О
inc Counter /кн. была отпущена, увеличиваем счетчик
out PORTB,Counter /выводим счетчик в порт В
ldi Count_time,50 /интервал 0,2 с
rjmp ent_int/Ha выход
Push_pin: ;было нажатие
sbr Flag, 1 устанавливаем бит О
ldi Count_time,128 /интервал 0,5 с ent_int:
ldi temp,ObOOOOOOll; запуск TimerO входная частота 1:64 out TCCR0,temp reti ;конец обработки прерывания кнопки
TIM0: /обработчик прерывания TimerO
dec Count_time ;в каждом прерывании уменьшаем на 1
breq end_timer /если ноль, то на конец отсчета
reti /иначе выход из прерывания end_timer:
clr temp /останавливаем таймер
out TCCR0,temp
sbrc Flag,0 '/проверяем бит 0 нашего регистра флагов' rjmp Push_tim /если 1, то было нажатие
ldi temp,(1< out MCUCR,temp
rjmp end_tim /на выход Push_tim: /если было нажатие
ldi temp,(1< ldi temp,(1< RESET: /начальная инициализация
ldi temp,low(RAMEND) /загрузка указателя стека out SPL,temp
ldi temp,ObOOOOOlOO /для второго разряда порта D
out PORTD,temp /подтягивающий резистор на всякий случай
ldi temp, 0Ы1111111 /порт В все контакты на выход
out DDRB,temp
clr Counter /очищаем счетчик clr Flag /очищаем наш флаг
ldi temp, (1«ТО1Е0) /разр. прерывания TimerO out TIMSK,temp
ldi temp, (1«ISC01) /устанавливаем прер. INTO по спаду out MCUCR,temp
ldi temp, (1«INT0) /разрешаем прерывание INTO
out GIMSK,temp
sei /разрешаем прерывания
Gcykle: /основной пустой цикл rjmp Gcykle

Здесь нужно пояснить момент, связанный с использованием флага (регистр Flag). У нас одни и те же прерывания служат для разных вещей: в прерывании от кнопки мы должны иногда реагировать на фронт импульса, иногда на спад, в зависимости от этого формировать разные задержки и в прерывании таймера устанавливать нужную реакцию для кнопки к следующему разу. Собственно разных состояний системы у нас два: исходное, когда по кнопке МК должен реагировать на спад, и состояние нажатия, когда МК затем должен реагировать на фронт.
Чтобы эти состояния разделить, я и использую флаг— нулевой бит специально заведенного для этой цели регистра Flag. Вообще говоря, специально отводить целый регистр для этой цели необязательно: в "официальном" регистре флагов SREG есть предназначенный как раз для подобных вещей бит т (см. табл. 6.1). Но дело в том, что здесь мы обходимся всего двумя состояниями, а нередко их бывает значительно больше, потому одного бита может быть недостаточно. В целях унификации я и здесь задействовал отдельный специальный регистр Flag, который нам еще не раз потребуется.

Думаю, что читатель еще далеко не во всем разобрался, и в применении некоторых команд многое ему непонятно. В последующих главах мы рассмотрим многие вопросы подробнее, а сейчас остановимся на весьма существенном для программирования современных МК AVR моменте, связанном с установкой конфигурационных ячеек.



     
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru