В этой части разберем простой пример использования внешнего прерывания INT0 и INT1.
Если посмотрим на прошлую программу, то видно, что микроконтроллер практические все свои ресурсы тратит на отслеживание срабатывания порта PD0. Таким образом наша программа не может быть расширена, так как нужно будет все время возращаться к проверке порта ввода. Чтобы от этого избавиться, нужно задействовать внутренний модуль внешнего прерывания INTx.
Первым делом необходимо в технической документации МК посмотреть адрес вектора прерывания «External Interrupt Request 0».
В программе адрес INT0 нужно прописать сразу же после метки Reset. Так как наша программа будет обрабатываться в цикле аппаратного прерывания, то цикл «main» остается пустым. Важно помнить, что при использовании прерываний, цикл main должен присутствовать в программе. Не зависимо от того будет ли там что-то написано или нет.
Так как вывод прерывания INT0 припадает на порт PD2, то нужно перенести кнопку с PD0 на PD2 и произвести настройку порта на ввод.
Чтобы разрешить использование прерывания INT0, необходимо внести данные в регистр GIMSK, согласно таблице ниже.
Следующим шагом будет настройка условий прерывания. Параметры записываются в регистр MCUCR.
Как видно из таблицы, с помощью битов ISCxx можно настроить условие прерывания по переднему фронту, по заднему и по изменению логического состояния пина.
Перенесем нашу прошлую программу в прерывание INT0 и проверим ее работу в Proteus.
.device Attiny2313 ; указываем тип устройства
.include “tn2313def.inc” ; подключаем файл директив МК ATtiny2313
.def temp = r16 ; задаем имя нашему регистру общего назначения
.org 0x0000 ; начало программы с 0 адреса
rjmp reset
.org 0x001 ;адрес нашего прерывания
rjmp INT_0
reset:
ldi temp,ramend ; грузим значение ramend в регистр temp
out $3d, temp ;
ser temp ; настраиваем все выводы порта В на выход
out DDRB, temp ;
ldi temp,0b00000100;настрйока PD2 на вход
out PORTD,temp
ldi temp,(1< out GIMSK,temp ldi temp,(1< out MCUCR,temp sei ldi r22,1 out PORTB,r22 main: rjmp main INT_0: rcall delay rol r22 out PORTB,r22 reti delay: clr r20 clr r21 d_1: inc r20 cpi r20,200 brne d_1 d_2: inc r21 cpi r21,50 brne d_1 ret Как видим программа сильно упростилась. Сейчас нет необходимости отслеживать состояние выходного сигнала, тем самым мы экономим производительность время микроконтроллера. В данном примере настроили прерывание по заднему фронту сигнала с порта PD2. Задержка delay предотвращает дребезг контакта и ложное выполнение программы. На рисунке ниже видно срабатывание кнопки (канал А) и включение светодиода на порте B. Апааратное прерывание настроено на задний фронт сигнала, поэтому выполнение программы началось только после отпускания кнопки. Перед тем как на PВ2 установилась логическая единица, была выполнена задержка длительностью 100мс. Такого интервала вполне достаточно для предотвращения дребезга контакта. С помощью этого прерывания можно делать подсчет импульсов или подключить важные аварийные кнопки, которые будут незамедлительно обрабатываться. При этом основная часть программы может быть выделена на решение других задач. Чтобы применить прерывание INT1 нужно внести дополнительные настройки в регистры GIMSK и MCUCR. ldi temp,(1< out GIMSK,temp ldi temp,(1< out MCUCR,temp Таким образом, мы разрешили использование двух меток прерываний. Если в МК имеется вектор INT2 то по такому же образу можно добавить следующую метку.