Внешние прерывания МК AVR

Просмотров: 79766Комментарии: 4
Электроника. СхемотехникаAVR.Начинающим

Что же такое прерывание? Прерывание это событие, при котором происходит приостановка основной программы и переход на выполнение подпрограммы прерывания. Чтобы узнать какие же есть прерывания в МК, откроем даташит микроконтроллера и нажмем на вкладку Interrupts и там в самом начале увидим таблицу векторов прерываний. Для МК mega8 она выглядит вот так.
В каждом векторе прерывания находится команда перехода с адресом начала подпрограммы прерывания. Любая программа начинается с Reset, в котором находится команда перехода к блоку инициализации. А дальше, каждое прерывание настроено на какое-то событие и при срабатывании этого события программа переходит к обработчику этого прерывания. Видно, что каждому прерыванию соответствует свой вектор прерывания. Чем выше адрес прерывания, тем ниже приоритет прерывания. Т.е. в очереди прерываний, прерывания с большим приоритетом будут выполняться раньше. Если началась обработка какого-нибудь прерывания, никакое другое не может быть вызвано, даже с большим приоритетом. Иначе получался бы рекурсивный вызов обработчиков прерываний и сложнее было бы отследить работу программы. При вызове обработчика любого прерывания бит глобального разрешения прерываний I регистра SREG (status register - регистр состояния) сбрасывается в "0"и только по завершении обработки прерывания снова устанавливается в "1" и разрешает начать обработку следующего прерывания в очереди. Чтобы установить ручками этот бит существует функция sei(), а чтобы сбросить - cli(). При запуске программы этот бит всегда сброшен и чтобы прерывания срабатывали его нужно установить (вызвать sei()).
Итак, в этой статье нас будут интересовать только внешние прерывания, т.е. те прерывания, которые возникают при изменении состояния определенных входом МК. Из таблицы векторов прерываний видно, что у МК ATmega8 таких прерываний 2 - INT0 и INT1 и их приоритет выше других прерываний. Жмем в даташите External Interrupts и обнаруживаем интересную вещь. Для настройки этих прерываний нужно воспользоваться регистрами MCUCR (MCU Control Register - регистр управления) и GICR (General Interrupt Control Register - общий регистр управления прерываниями). Рассмотрим их подробней.

MCUCR
  • Бит 1, 0 - ISC01, ISC00: Настройка условия срабатывания прерывания INT0 (таблица 1).
  • Бит 3, 2 - ISC11, ISC10: Настройка условия срабатывания прерывания INT1 (таблица 2)
Биты 4-7 относятся к управлению питанием и здесь рассматривать их не будем.

GICR
  • Бит 7 - INT1: Разрешает внешнее прерывание 1 ("1" - разрешено, "0" - запрещено)
  • Бит 6 - INT0: Разрешает внешнее прерывание 0 ("1" - разрешено, "0" - запрещено)
Также любое прерывание имеет свой флаг прерывания. Этот флаг устанавливается в "1" в момент, когда должно произойти прерывание, даже если прерывания глобально запрещены и соответствующая программа обработки прерывания не вызывается. Можно, например, внутри какого-нибудь обработчика прерывания по этому флагу проверять было ли какое-либо прерывание или нет. Флаги внешних прерываний являются 7-м и 6-м битом регистра GIFR. Флаги прерываний сбрасываются записью в них "1".

GIFR
  • Бит 7 - INTF1: Флаг внешнего прерывания 1.
  • Бит 6 - INTF0: Флаг внешнего прерывания 0.
Вот собственно и все, что нужно знать чтобы настроить внешние прерывания. Рассмотрим на примере, что нужно записать в регистры MCUCR и GICR, чтобы настроить внешние прерывания. Мы хотим настроить вызов обработчика прерывания INT1 при установлении "1" на входе INT1 (т.е. по переднему фронту импульса). Согласно таблице 2 нужно установить в "1" биты ISC11 и ISC10 регистра MCUCR, а по таблице 1 бит INT1 регистра GICR. Таким образом, MCUCR = 0b00001100 и GICR = 0b10000000.
Настроим внешние прерывания в WinAVR. Чтобы вызвать обработчик конкретного прерывания в WinAVR нужно воспользоваться макросом ISR и указать ему в качестве параметра вектор нужного прерывания. Откроем файл микроконтроллера mega8 - в папке с WinAVR по адресу \avr\include\avr\iom8.h и в  нем найдем определения векторов прерывания. Внешнему прерыванию INT1 соответствует вектор INT1_vect. В блоке инициализации устанавливаем регистры MCUCR и GICR, после этого вызываем функцию sei(). Да, еще нужно подключить файл interrupt.h. В примере добавил переменную, которую будем инкрементировать при срабатывании внешнего прерывания - такой себе счетчик. Все это будет выглядеть вот так:

#include <iom8.h>
#include <avr/io.h>
#include <avr/interrupt.h>
//определяем биты регистров
#define ISC10 2
#define ISC11 3
#define INT1 7
unsigned char int1 = 0;
ISR(INT1_vect)
{
//обработка прерывания
        int1++;
}
//функция инициализация внешнего прерывания
void INTinit()
{
MCUCR = (1<<ISC10) | (1<<ISC11);//0b00001100
GICR = (1<<INT1);//0b10000000
}
int main()
{
        INTinit();//вызываем функцию инициализации прерывания
        sei();//устанавливаем бит глобального разрешения прерываний
while(1);
}
На этом собственно и все по поводу внешних прерываний.

Комментариев: 4 RSS

1 Аноним 22-04-2011 19:45

Дмитрий здравствуйте, респектище за статью !!!!!!!!

Вот вы инициализировали только INT1

void INTinit()

{

MCUCR = (1

2 Артем 09-03-2012 23:04

//определяем биты регистров

#define ISC10 2

#define ISC11 3

#define INT1 7

Это лишнее, оно определено в соответствующем файле (для тини2313 - iotn2313.h) через io.h

3 Юрий 30-09-2012 21:24

А если обработчик выполняет вычисления и возвращает значение, какая должна быть запись?

4 ifar 05-11-2012 00:30

А если обработчик выполняет вычисления и возвращает значение, какая должна быть запись?

С основным телом программы обработчик общается через изменение глобальных переменных, которые следует объявлять как volatile:

unsigned char volatile int1 = 0;

Иначе, без объявления переменной как volatile, включенная оптимизация может удалить переменную как неиспользуемую явно в программе.

Оставьте комментарий!

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Вы можете войти под своим логином или зарегистрироваться на сайте.

(обязательно)