![](https://vsor.by/wp-content/uploads/2020/04/0-заставка.jpg)
Прерывание (внешнее или внутреннее) — это событие прерывающее выполнение программы для выполнения другого кода ( кода обслуживающего это прерывание).
Этот код называется обработчиком прерывания. Код обработчика прерывания расположен в памяти программ после меток .Чтобы сработало определенное прерывание- его надо разрешить. К примеру , в микроконтроллере AT90S2313 предусмотрены 11 прерываний (вектора прерываний) :
Допустим надо активизировать прерывание Timer1_comp1.
Тогда необходимо по адресу $004 памяти программ поставить ссылку (метку) на подпрограмму — обработчик этого прерывания.
При срабатывании прерывания (Timer1_comp1) происходит переход на адрес $004. По этому адресу стоит безусловный прыжок на метку , где после метки написан код обслуживания этого прерывания .
Все прерывания воздействуют на определённые биты в регистрах: регистре состояния, регистрах разрешения прерываний (т.е чтобы начать выполнять определенное прерывание необходимо иметь разрешение на обслуживание этого прерывания) .
Для дачи разрешения в регистре состояния и регистре разрешения определенные биты должны быть в определенном состоянии.
Подпрограмма обработки прерывания начнет выполняться ,если флаг прерывания в регистре разрешения установлен и в регистре состояния прерывание глобально разрешено : флаг (I)=1 в SREG. Флаг глобального разрешения (I) в регистре состояния (SREG) устанавливается в 1 при выполнении команды выхода из прерывания – RETI. Если бит I=0 , то все прерывания запрещены.
Схема :
Пример использования прерывания INT0 в приведенной схеме :
По умолчанию, прерывание INT0 устанавливается по низкому уровню (ISC01=0 и ISC00=0). Но, чтобы INT0 выполнить нужно инициализировать(разрешить это прерывание). В приведенной схеме ожидается сигнал на ножке микроконтроллера 6 (INT0). Поэтому (согласно архитектуре микроконтроллера) надо произвести предварительные настройки регистров GIMSK и MCUCR.
Предварительные настройки :
Если в регистре GIMSK 6 бит (INT0)=1.,то разрешается прерывание формой сигнала определяемой в регистре MCUCR (биты ISC).
Так как при нажатии кнопки на ножке 6 сигнал меняется с +5В до 0 , то будет прерывание по спаду ( ISC01=1,ISC00=0).
Бит 6 ( INT0) — запрос внешнего прерывания разрешен, когда этот бит установлен. Пусть событие (нажатие кнопки) на 6 ножке произошло . Произойдет скачок с адреса $001 на метку INT_0 (начнет выполняться процедура обработки прерывания INT0).
$001 rjmp INT_0 ; метка начала подпрограммы обработки прерывания на входе INT0.
Еще важно помнить ,что регистр состояния (SREG) бит 7 тоже нужно готовить для выполнения прерывание INT0 . При возникновении прерывания INT0 6 бит станет нулем и все другие прерывания получат запрет. Это состояние будет, пока не будет обслужено INT0 и не произойдет выход из обработчика командой reti. Также по окончании прерывания INT0 сбрасывается и бит 6 GIMSK в 0. Команда RETI устанавливает флаг разрешения преры-ваний I в 1 и разрешит все прерывания..
Если нужно запомнить состояние SREG , то это делается так: перед выполнением подпрограммы, программный счетчик (PC) записывает текущий адрес в стек , а 8 -ми разрядный указатель стека (SP) уменьшается на 2.
То есть обязательно, в инициализационной части программы , надо указать компилятору про стек и расположить его в оперативной памяти данных (8 -ми разрядной SRAM). Стек хранит адреса возврата .
Если вывод INT0 используется для работы с внешним источником прерывания, то соответствующий бит в регистре направле¬ния данных порта D (регистра DDRD), должен быть сброшен в 0, чтобы вывод INT0 работал как вход .
Практика:
.device AT90S2313
.include «2313def.inc» ;( объявленный inc-файл)
.def temp = r16 ; регистру r16 присвоил имя переменной- temp
.def кlav = r17 ;регистру r17 присвоил имя переменной кlav
.def Reg0=18
.def Reg1=19
.def Reg2=20
rjmp Reset; переход на метку Reset (имя метки может быть произвольным)
rjmp INT_0; переход на метку INT_0
rjmp INT_1;
rjmp Timer1_capt1; переход на метку Timer1_capt1
rjmp Timer1_comp1;
rjmp Timer1_OVF1;
rjmp Timer0_OVF0;
rjmp UART_RX;
rjmp UART_UDRE;
rjmp UART_TX;
rjmp ANA_COMP;
;Метка Reset — это начало выполнения программы. Инициализация.
Reset:
ldi temp,low(RAMEND) ; стек –специальная область памяти. Указ компилятору, где расположить ;программный стек(в конце SRAM ,что обозначается константой RAMEND, объявленной в соответствующем inc-файле).
out SPL,temp ;
ldi temp,high(RAMEND)
out SPH,temp ; загрузка указателя стека в регистр .
;Контроллер должен сохранять состояние программного счетчика, чтобы знать, куда вернуться.
ldi temp, 1<<ACD; 1 в позиции AСD (зачем расходовать питание)
out ACSR, temp ;выкл. аналог. компаратор
ldi temp,0b00000100 ;для второго разряда порта D
out PORTD,temp ;подтягивающий резистор, на выход.
clr Flag ;очищаем r17.
ldi temp,(1<<ISC01); 1 позиции ISC01
out MCUCR,temp ; установка прерывания по форме напряжения.
ldi temp,(1<<INT0); 1<<INT0 значит,что число 1, сдвинуто и находится в позиции INT0.
out GIMSK, temp ;разреш. прерыв. от кнопки
sei ;разреш. глобальное прерывание
; настройки начальные завершены.
; на ножке 6 (INT0), отслеживаем нажатие;
INT_0:
clr temp ;
out GIMSK,temp ;
ldi temp,$FF
out GIFR,temp ;
sbrs klav,0 ;
rjmp kon_pin ;
cbr klav,1 ;
kon_pin:
sbr кlav,1 ;устанавливаем бит .
(код защиты от дребезга)
(сформировать задержку)
reti ;конец обработки прерывания от кнопки, выход из прерывания.
;Один из вариантов защиты от дребезга при нажатии на клавишу.
Delay: ; задержка от дребезга при нажатии кнопки.
dec Reg0;
brne Delay ; проверка условия равенства нулю. Переход ,если не =0.
dec Reg1
brne Delay
dec Reg2
brne Delay ; пока во всех переменных Reg0, Reg1, Reg2 не будут нули будет задержка.
ret
Некоторые команды:
dec — декрементировать,reti— выход из подпрограммы (обработчика прерывания),sbr-(установить биты),sbrs-(бит установлен-пропустить),clr-(очистить),sei-(флаг глобального прерывания установить) ,rjmp – безусловный переход.ldi-(загрузить значение) ,out-(записать из регистра в порт) , brne— перейти если не равно, cbr-(очистить биты в регистре),ret(возврат из подпрограммы)
Отдельные директивы:
def— определение символьных имен переменных, понятных пользователю, из смысла действий логики (алгоритма).
defice-указывает ассемблеру на применяемую модель (в выше приведенной программе — это AT90S2313)и перечень команд , которые способна выполнить эта модель микроконтроллера.
inciude-подключить файл с определениями констант и адресов для контроллера AT90S2313. Сам файл должен находится в текущем каталоге.Inc-файлы указывают ассемблеру на истинные адреса регистров в микроконтроллере.