суббота, 2 февраля 2013 г.

очередь прерываний mega8

Что же такое прерывание? Прерывание это событие, при котором происходит приостановка основной программы и переход на выполнение подпрограммы прерывания. Чтобы узнать какие же есть прерывания в МК, откроем даташит микроконтроллера и нажмем на вкладку 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 7unsigned char int1 = 0;ISR(INT1_vect){//обработка прерывания        int1++;}//функция инициализация внешнего прерыванияvoid INTinit(){MCUCR = (1<<ISC10) | (1<<ISC11);//0b00001100GICR = (1<<INT1);//0b10000000}int main(){        INTinit();//вызываем функцию инициализации прерывания        sei();//устанавливаем бит глобального разрешения прерыванийwhile(1);}На этом собственно и все по поводу внешних прерываний.

19фев/2011Внешние прерывания МК AVRАвтор: Рубрика: -> Просмотров: 26024

Новинки электронных устройств. Готовые устройства на микроконтроллерах

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

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