Предыдущий <<  GIMSK $3B ($5B), GIFR  $3A ($5A)   >>Следующий

 Эти два регистра предназначены для управления внешними прерываниями. Внешнее прерывание программы вызывается фронтом, спадом или уровнем на выводе INTx МК в том случае, если установлен общий флаг разрешения прерывания I в SREG и соответствующий флаг INTx в регистре GIMSK.

Если ваша программа работает с прерываниями, то регистр GIFR вам, в общем-то, и не нужен. В нем устанавливается в "1" флаг INTFx в том случае, если прерывание запрещено, а ситуация возникновения прерывания имеется. Программа может опрашивать эти флаги и предпринимать какие-либо действия.

Следует только помнить, что флаги в регистре GIFR автоматически сбрасываются при обработке прерывания, если же прерывания запрещены - то сбросить их программно можно, записывая в соответствующий бит "1" (нелогично? но именно так и есть)


Если вы знаете, что такое прерывания - далее можете не читать. А я попробую простым языком изложить суть прерываний. На мой взгляд, это очень важная тема, без понимания механизма прерываний построить эффективную realtime программу для МК просто невозможно.

Допустим, нужно создать на МК устройство, которое должно выполнять какое-нибудь достаточно сложное вычисление (занимающее, например, 0,1 секунды) и в то же время переключать один из своих pin-ов с частотой 1 кГц. Как это сделать?

Ну, время считать будет таймер - это естественно. Настроили таймер так, чтобы он через 1 мс выставлял  флажок переполнения. А дальше? Вставлять в программу через 10 команд проверку этого флага? Это уже не программа будет, а сыр с дырками. Да к тому же 10 команд можно написать таких, что выполняться они будут и в течение секунды. Как быть?

А вот тут-то и надо использовать прерывание. Таймер у нас настроен на переполнение через 1 мс, так разрешим прерывание переполнения. Кроме этого. должен быть установлен флаг общего разрешения прерываний. Что же произойдет при переполнении таймера?

Закончив выполнение текущей команды, МК сохранит значение счетчика команд в стеке, после чего выполнение передастся на соответствующий вектор прерывания, а проще - конкретный адрес, закрепленный за прерыванием. См. таблицу векторов для МК 8535

Таблица векторов построена так, чтобы по соответствующему адресу можно было поставить одну команду - RJMP обработчик. Следовательно, завершив (прервав!) выполнение текущей программы, МК передает управление на процедуру обработки прерывания. Требования к ней следующие:

Процедура обработки прерывания должна заканчиваться командой RETI - возврат из прерывания. По этой команде МК восстановит из стека счетчик команд, сохраненный там после возникновения прерывания, то есть вернется к выполнению основной программы.

В начале процедуры обработки прерывания нужно сохранить в стеке SREG и изменяемые регистры. Так, если в процедуре обработки мы изменяем R16, то она должна начинаться с команд:

push R16
in R16, SREG
push R16

и заканчиваться командами:

pop R16
out SREG,R16
pop R16
RETI

Адрес
вектора
Описание вектора прерывания
$000 Старт программы после сброса, включения питания или сброса по сторожевому таймеру
$001 Внешнее прерывание 0 (pin INT0)
$002 Внешнее прерывание 1 (pin INT1)
$003 Таймер 2 - сравнение
$004 Таймер 2 - переполнение
$005 Таймер 1 - захват
$006 Таймер 1 - сравнение A
$007 Таймер 1 - сравнение B
$008 Таймер 1 - переполнение
$009 Таймер 0 - переполнение
$00A Прерывание SPI - цикл обмена завершен
$00B Прерыванние USART - принят байт
$00C Прерыванние USART - регистр данных пуст
$00D Прерыванние USART - передача закончена
$00E АЦП - преобразование завершено
$00F EEPROM - готово
$010 Аналоговый компаратор

Таблица векторов для МК AT90s8535

В этом случае основная программа просто ничего не заметит, и требуемое действие будет выполнено именно тогда, когда возник запрос, независимо от того что делала в это время основная программа. 

ВНИМАНИЕ! Несохранение чего-либо, что изменяется в процедуре обработки прерывания и используется в основной программе, приведет к неверной ее работе или вообще ее краху. Представьте себе ситуацию, когда в основной программе выполняется, допустим, вычитание числа 10 из регистра R3. R3 - это регистр "младший", эти регистры не работают с непосредственным операндом, то есть нельзя написать

subi R3, 10

В этом случае нужно написать

ldi R16, 10
sub R3, R16

Ничего тут не поделаешь - так уж устроен AVR. У него много тонкостей, на которых по неопытности можно понабивать шишек, смотри тут подробнее. Но мы отвлеклись. Представьте себе , что прерывание возникает между этими двумя командами (на то оно и прерывание, чтобы возникать когда угодно!) и в процедуре обработки прерывания мы изменим содержимое региcтра R16. Думаю, ясно, что результат работы программы после этого непредсказуем.

В заключение надо упомянуть, что время обработки прерывания не должно быть больше, чем период  его возникновения, иначе основная программа просто не будет выполняться.


Если вы живете в подмосковье, бурение скважин чеховский район - самый удобный для вас вариант. ·· Натуральный камень. Плитка и камни для бани и сауны из натурального камня. Жадеит.

nml 11-Jul-2009