Лекция №8 СИСТЕМА ПРЕРЫВАНИЙ МК СЕРИИ AVR Внутри МК или в связанной с ним внешней среде могут возникать разнообразные события, которые требуют немедленной реакции на свое появление, т.е. временной приостановки процесса обработки основной программы («прерывания») и выполнения другой программы (процедуры), предназначенной для обслуживания возникшего события. Соответственно такие события называются прерывающими событиями. Реакция контроллера на внешнее событие должна завершаться возвратом к основной программе (рис.14.1). Рис.8.1. Совокупность аппаратных и программных средств микроконтроллеров, предназначенных для организации и обслуживания прерываний, образует систему прерываний. Все микроконтроллеры семейства AVR имеют многоуровневую векторную систему приоритетных прерываний. Всего в различных моделях АVR существует от 6-8 (младшие Tiny) до нескольких десятков источников прерываний (например, в ATmega128 их 34, в ATmega2560 их 57 и т.д.). Общие замечания. Возможность аппаратно прерывать выполнение основной программы - важнейшая функция современных микроконтроллеров. Не будет преувеличением утверждать, что основное занятие почти любого современного вычислительного устройства - ожидание и обработка в бесконечном цикле неких событий. Это могут быть сигналы от других устройств, сообщающие о готовности к обмену информацией, сигналы определяющие момент начала расчета управляющего кода, сигналы инициализирующие аварийные ситуации и т.д. Место и причина возникновения указанных событий могут быть достаточно разнообразными, однако эти события обладают одним общим свойством - момент их возникновения заранее неизвестен для программы. В связи с этим, в вычислительной системе необходимо предусмотреть средства обнаружения этих событий с тем, чтобы по факту их обнаружения предпринять некоторые действия по их обслуживанию. 1 Обнаружить прерывающее событие на практике возможно либо в результате периодического опрашивания процедурой пользователя информационных входов (программный способ), либо аппаратного формирования признаков наступления события, требующего своего обслуживания (аппаратный способ). Программный способ, имеет два существенных недостатка: снижение производительности вычислительной системы (некоторая часть программы будет отведена под перебор признаков возникновения событий); наличие задержки между моментом возникновения события и моментом его обнаружения (в ряде случаев, например в системах реального времени, принципиально недопустимая). Исключение указанных недостатков возможно лишь в случае аппаратного обнаружения заданных прерывающих событий, что реализуется посредством системы обслуживания прерывающих событий (кратко - "система прерываний"). Разновидности прерываний В общем случае прерывающие события могут иметь как программную, так и аппаратную природу: к программным причинам возникновения прерывающих событий относятся: попытка выполнения несуществующих команд (т.е. таких, чей КОП отсутствует в системе команд данного МК) или выполнение команд с недопустимыми данными (например, в случае деления на ноль); к аппаратным причинам возникновения прерывающих событий относятся: готовность периферийных модулей (например, окончание преобразования в АЦП, переполнение таймера, прием посылки по последовательному порту и т. п.), активизация сигналов, поступающих на МК извне от объекта управления (например, двоичный сигнал от датчика срабатывания исполнительного механизма) и т.д. Особенностью системы прерываний МК является то, что в МК, все прерывания аппаратные, которые в свою очередь делятся на внутренние и внешние. Внутреннее прерывание это событие, которое возникает в МК и прерывает выполнение основной программы. Внутренних прерываний в МК семейства АVR довольно много и в совокупности они служат для организации взаимодействия устройств с ядром системы. Внутренние прерывания могут возникать от таймеров, аналогового компаратора, последовательного порта и т. п. Внешние прерывания инициируются сигналами, которые формируются на соответствующих выводах МК, устройствами, являющимися внешними по 2 отношению к МК. Эти выводы обозначаются INT0 – INT7. Функции ввода сигналов прерывания являются альтернативными функциями портов МК. Пример размещения сигналов на выводах ATmega128 приведен на рис. Рис.8.2. Как следует из приведенного рис.8.2., функции вводов сигналов прерываний выполняют порты РЕ4-РЕ7 и PD0-PD3. Внешние прерывания могут возникать, независимо друг от друга. Уникальный случай представляет собой ATtiny28 (специально предназначенный для пультов управления), в котором имеется внешнее прерывание, возникающее при появлении сигнала низкого уровня на любом из контактов порта В, что позволяет обслуживать многокнопочную клавиатуру. Во всех остальных случаях внешнее прерывание - событие, которое наступает при наличии сигнала на одном из входов, специально предназначенных для этого (например, INT7 – INT0). Выделяют три вида событий, вызывающих внешнее прерывание: это может быть низкий уровень напряжения, а также положительный или отрицательный фронт на соответствующем выводе. Таким образом, система прерываний может работать в одном из четырех возможных режимов: - режим прерывания по уровню (статический, асинхронный режим); - режим прерывания по фронту (нарастанию); - режим прерывания по срезу сигнала (спаду); - режим прерывания по фронту и срезу сигнала. 3 Последние три режима относятся к динамическим режимам и в свою очередь могут быть асинхронными и синхронными. Кроме того, все имеющиеся прерывания можно разделить на два типа. Прерывания первого типа генерируются при наступлении некоторого события, в результате которого устанавливается флаг прерывания. Затем, если прерывание разрешено, в счетчик команд загружается адрес вектора соответствующего прерывания. При этом флаг прерывания аппаратно сбрасывается. Он также может быть сброшен программно, путем записи логической 1 в разряд регистра, соответствующий флагу. Прерывания второго типа не имеют флагов прерываний и генерируются в течение всего времени, пока присутствуют условия, необходимые для генерации прерывания. Соответственно, если условия, вызывающие прерывание, исчезнут до разрешения прерывания, генерации прерывания не произойдет. ТАБЛИЦА ВЕКТОРОВ ПРЕРЫВАНИЙ. В векторной системе прерываний каждому прерыванию поставлен в соответствие некоторый адрес (абсолютный или относительный), по которому должна располагаться команда безусловной передачи управления процедуре обслуживания данного прерывания. Совокупность адресов, задействованных системой прерываний, называют таблицей прерываний. Под таблицу прерываний по умолчанию отводят младшие адреса памяти программ начиная с адреса $0001 (модели ATmega8x и ATmega8515x) и $0002 (для остальных моделей). Каждому прерыванию соответствует адрес в этой таблице, который загружается в счетчик команд при возникновении прерывания. Положение вектора в таблице также определяет и приоритет соответствующего прерывания: чем меньше адрес, тем выше приоритет прерывания. Размер вектора прерывания зависит от объема памяти программ микроконтроллера и составляет 1 слово для моделей ATmega8x и ATmega8515x и 2 слова для остальных моделей. Соответственно для перехода к подпрограммам обработки прерываний в моделях микроконтроллеров ATmega8x и ATmega8515x используются команды RJMP, а в остальных моделях - команды JMP. Это обусловлено тем, что команда RJMP занимает 1 слово (2 байта) памяти программ и способна адресовать 8Кбайт. А команда JMP занимает 2 слова (4 байта) и способна адресовать 8Мбайт памяти программ (4 Мслова памяти). 4 Практически во всех микроконтроллерах семейства Mega, за исключением моделей ATmega161x и ATmega163x, положение таблицы векторов прерываний может быть изменено. Таблица может располагаться не только в начале памяти программ, а также и в начале области загрузчика. Причем перемещение таблицы может быть осуществлено непосредственно в ходе выполнения программы. Управление размещением таблицы прерываний осуществляется двумя младшими разрядами регистров MCUCR (модели ATmega64x и АТmega128x) и GICR (остальные модели): IVSEL (1-й разряд) и IVCE (0-й разряд). Состояние флага IVSEL определяет положение таблицы в памяти программ. Если флаг сброшен в «0», таблица векторов прерываний располагается в начале памяти программ, если флаг установлен в «1» - в начале области загрузчика. Конкретное значение начального адреса области загрузчика зависит от установок конфигурационных ячеек BOOTSZ1 и BOOTSZ0 (кроме моделей ATmega161x). Разряд IVCE предназначен для разрешения изменения флага IVSEL. Конфигурационная ячейка BOOTRST определяет расположение вектора сброса Reset. Если эта ячейка запрограммирована (BOOTRST=0), то вектор сброса расположен в начале области загрузчика. Если ячейка BOOTRST не запрограммирована (BOOTRST=1) вектор сброса расположен в начале памяти программ. Для изменения положения таблицы векторов прерываний необходимо установить разряд IVCE в «1» и затем в течение следующих четырех машинных циклов занести требуемое значение в разряд IVSEL. При этом разряд IVCE сбрасывается в «0». В противном случае разряд IVCE будет сброшен аппаратно по истечении четырех машинных циклов, запрещая дальнейшее изменение флага IVSEL. На время выполнения описанной последовательности прерывания автоматически запрещаются и разрешаются только после сброса флага IVCE. Состояние флага I регистра SREG при этом не меняется. Размер таблицы зависит от модели микроконтроллера. Для моделей ATmega64x и ATmega128x таблица векторов прерываний содержит 34 вектора, для модели ATmega8515x – 16. Распределение адресов таблицы векторов прерываний для МК ATmega128 приведено в таблице 8.1. При размещении векторов прерываний в области загрузчика к значениям, указанным в таблице, следует прибавить значение начального адреса области загрузчика. Указанная таблица прерываний, устанавливающая связь прерывающего события с адресом вектора прерывания, может быть получена из файла “m128def.inc”, в котором вводятся все описания, принятые для МК. Область описания адрес, задействованных системой прерываний (таблицы прерываний) для ATmega128 приведен в листинге _8.1. 5 Таблица 8.1. Номер вектора Адрес вектора 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 $0000 $0002 $0004 $0006 $0008 $000A $000C $000E $0010 $0012 $0014 $0016 $0018 $001A $001С $001E $0020 $0022 $0024 $0026 $0028 $002A $002C $002E $0030 $0032 $0034 $0036 $0038 $003A $003C $003E $0040 $0042 $0044 Источник RESET INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 TIMER2 COMP TIMER2 OVF TIMER1 CAPT TIMER1 COMPA TIMER1 COMPB TIMER1 OVF TIMER0 COMP TIMER0 OVF SPI, STC USART0, RX USART0, UDRE USART0, TX ADC ЕЕ READY ANALOG COMP TIMER1 COMPC TIMER3 CAPT TIMER3 COMPA TIMER3 COMPB TIMER3 COMPC TIMER3 OVF USART1, RX USART1, UDRE USART1,TX TWI SPM READY Описание Сброс от любого внешнего источника Внешнее прерывание 0 Внешнее прерывание 1 Внешнее прерывание 2 Внешнее прерывание 3 Внешнее прерывание 4 Внешнее прерывание 5 Внешнее прерывание 6 Внешнее прерывание 7 Совпадение таймера/счетчика 2 Переполнение таймера/счетчика 2 Захват таймера/счетчика 1 Совпадение «A» таймера/счетчика 1 Совпадение «B» таймера/счетчика 1 Переполнение таймера/счетчика 1 Совпадение таймера/счетчика 0 Переполнение таймера/счетчика 0 Передача по SPI завершена USART0, прием завершен Регистр данных USART0 пуст USART0, передача завершена Преобразование АЦП завершено Готовность EEPROM Прерывание от аналогового компаратора Совпадение «C» таймера/счетчика 1 Захват таймера/счетчика 3 Совпадение «A» таймера/счетчика 3 Совпадение «B» таймера/счетчика 3 Совпадение «C» таймера/счетчика 3 Переполнение таймера/счетчика 3 USART1, прием завершен Регистр данных USART1 пуст USART1, передача завершена Прерывание от модуля TWI Готовность SPM 6 Листинг 8.1. .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ INT0addr = 0x0002 INT1addr = 0x0004 INT2addr = 0x0006 INT3addr = 0x0008 INT4addr = 0x000a INT5addr = 0x000c INT6addr = 0x000e INT7addr = 0x0010 OC2addr = 0x0012 OVF2addr = 0x0014 ICP1addr = 0x0016 OC1Aaddr = 0x0018 OC1Baddr = 0x001a OVF1addr = 0x001c OC0addr = 0x001e OVF0addr = 0x0020 SPIaddr = 0x0022 URXC0addr = 0x0024 UDRE0addr = 0x0026 UTXC0addr = 0x0028 ADCCaddr = 0x002a ERDYaddr = 0x002c ACIaddr = 0x002e OC1Caddr = 0x0030 ICP3addr = 0x0032 OC3Aaddr = 0x0034 OC3Baddr = 0x0036 OC3Caddr = 0x0038 OVF3addr = 0x003a URXC1addr = 0x003c UDRE1addr = 0x003e UTXC1addr = 0x0040 TWIaddr = 0x0042 SPMRaddr = 0x0044 INT_VECTORS_SIZE ; External Interrupt Request 0 ; External Interrupt Request 1 ; External Interrupt Request 2 ; External Interrupt Request 3 ; External Interrupt Request 4 ; External Interrupt Request 5 ; External Interrupt Request 6 ; External Interrupt Request 7 ; Timer/Counter2 Compare Match ; Timer/Counter2 Overflow ; Timer/Counter1 Capture Event ; Timer/Counter1 Compare Match A ; Timer/Counter Compare Match B ; Timer/Counter1 Overflow ; Timer/Counter0 Compare Match ; Timer/Counter0 Overflow ; SPI Serial Transfer Complete ; USART0, Rx Complete ; USART0 Data Register Empty ; USART0, Tx Complete ; ADC Conversion Complete ; EEPROM Ready ; Analog Comparator ; Timer/Counter1 Compare Match C ; Timer/Counter3 Capture Event ; Timer/Counter3 Compare Match A ; Timer/Counter3 Compare Match B ; Timer/Counter3 Compare Match C ; Timer/Counter3 Overflow ; USART1, Rx Complete ; USART1, Data Register Empty ; USART1, Tx Complete ; 2-wire Serial Interface ; Store Program Memory Read = 70 ; size in words По умолчанию вектор сброса и таблица векторов прерываний расположены в начале памяти программ. Это объясняется тем, что в стандартном варианте конфигурационная ячейка BOOTRST не запрограммирована, а флаг IVSEL=0. На примере микроконтроллера ATmega128 рассмотрим вариант организации таблицы векторов прерываний для случая расположения таблицы векторов прерываний в начале программы (листинг 8.2). 7 Листинг 8.2. Адрес Метка .CSEG .org $0000 $0002 $0004 ... $0044 $0046 $0047 $0048 $0049 $004A RESET: Код Описание 0x0000 jmp RESET jmp EXT_INT0 jmp EXT_INT1 ... jmp SPM_RDY ;Обработчик сброса ;Обработчик IRQ0 ;Обработчик IRQ1 ldi r16,high(RAMEND) out SPH,r16 ldi r16, low(RAMEND) out SPL,r16 sei ;Начало основной программы ;Инициализация стека ; ; ;Разрешение прерываний ;Обработчик готовности SPM В приведенном листинге фрагмента программы рассмотрен редкий случай, когда в основной программе используются все прерывания, то есть таблица прерываний содержит адресные ссылки на обработчики всех прерываний. В частом случае основная программа использует несколько прерываний и для организации их обработки достаточно описать таблицу прерываний таким образом, что бы она содержала ссылки только на обработчики используемых прерываний. Для этого необходимо воспользоваться директивой компилятора .org устанавливающей адрес памяти программ, по которому будет расположена команда. Таким образом, можно заполнить таблицу векторов прерываний, чтобы она содержала ссылки только на обработчики указанных прерываний. Все остальные ячейки памяти программ в области расположения таблицы прерываний будут заполнены кодом 0xFFFF. Фрагмент листинга программы, в котором представлен вариант организации таблицы векторов прерываний приведен ниже (листинг 3). Зарезервированные в фале описания слова INT0addr, OVF0addr, OC3Aaddr соответствуют адресам в таблице прерывания. Так INT0addr=0x0002, OVF0addr=0x0020, а OC3Aaddr=0x0034. Если прерывание не описано (нет ссылки на обработчик) то, как уже отмечалось, в соответствующей ему адресной ячейке памяти программ будет находиться команда с кодом 0xFFFF. Если данное прерывание разрешено и будет сгенерировано в процессы работы микроконтроллера, то в счетчик команд PC будет загружен адрес этого прерывания и ядро микроконтроллера попытается выполнить несуществующую команду с кодом 0xFFFF хранящуюся по данному адресу. 8 Листинг 8.3. .CSEG .org 0x0000 jmp Reset .org INT0addr jmp INT0addr_Routing .org OVF0addr jmp OVF0addr_Routing .org OC3Aaddr jmp OC3Aaddr_Routing ;Обработчик сброса ;Обработчик внешнего ;прерывания INT0 ;Обработчик прерывания ;по переполнению Т/С0 ;Обработчик прерывания ;по совпадению «A» Т/С3 .org int _vectors_size Reset: ldi r16,high(RAMEND) out SPH,r16 ldi r16, low(RAMEND) out SPL,r16 sei ... INT0addr: ... ;Тело обработчика прерывания INT0 ... RETI Флаги прерываний, маскирование прерываний Для надлежащего управления процессами обработки прерываний используются специальные биты, называемые флагами прерываний. Флаги прерываний в МК семейства AVR образуют иерархию. Во главе этой структуры стоит бит I регистра флагов SREG, который разрешает (если установлен в лог.1 ) или запрещает (если установлен в лог.0) аппаратные прерывания вообще. Формат регистра SREG и его адрес показан на рис.8.3. $3F($5F) SREG 7 6 5 4 3 2 1 0 I T H S V N Z С Рис.8.3. Как правило, непосредственно с этим битом (как и вообще с регистром SREG) программисту дело можно не иметь: для общего разрешения (запрещения) прерываний предусмотрены специальные команды sei (разрешить) и cli (запретить), устанавливающие этот бит в нужное состояние. Отметим, что по умолчанию бит I регистра флагов SREG сброшен, т. е. прерывания при запуске МК запрещены. Для того чтобы их разрешить, необходимо в процедуре начальной инициализации, выполняющейся по сбросу МК, разместить команду sei. 9 Кроме общего флага прерываний, для каждого конкретного прерывания имеется свой разрешающий/запрещающий бит, расположенный в соответствующем регистре (например, для таймеров это регистры TIMSK или ETIMSK, для внешних прерываний - GIMSK, или EIMSK, и т. п.) – так называемых регистрах масок прерываний. При использовании прерываний эти биты необходимо устанавливать в состояние логической единицы, в противном случае автоматического вызова прерываний не произойдет. И наконец, каждое событие, которое требует запуска процедуры обслуживания прерывания, при наличии разрешения (установки соответствующего бита в регистрах масок), устанавливает флаг (бит) прерывания в регистрах флагов прерываний: для внешних прерываний - GIFR (EIFR); для внутренних прерываний, например от таймеров/счетчиков - TIFR (ETIFR). Отметим, что эти регистры при инициализации МК рекомендуется очищать, что делается записью единиц: Листинг 8.4. in temp, GIFR out GIFR,temp ;сбросить флаги внешних прерываний таймеров Обработка прерываний Прерывание прекращает нормальный ход программы для выполнения приоритетной задачи, определяемой внутренним или внешним событием микроконтроллера. При возникновении прерывания микроконтроллер сохраняет в стеке содержимое счетчика команд PC и загружает в него адрес соответствующего вектора прерывания. По этому адресу, как правило, находится команда безусловного перехода к подпрограмме обработки прерывания. Последней командой подпрограммы обработки прерывания должна быть команда RETI, которая обеспечивает возврат в основную программу и восстановление предварительно сохраненного счетчика команд. Суть обработки прерывания сводится к следующим действиям: обнаружение факта прерывающего события; установление необходимости реакции на него (т.к. не все из потенциально возможных прерывающих событий необходимы для реализации данной целевой функции МК, например, может не потребоваться обработка запроса прерывания от АЦП, работа с которым осуществляется путем выдержки паузы в ТПРЕОБР); выполнение арбитража событий (в случае возникновения нового прерывающего события, в момент обслуживания предыдущего 10 прерывающего события, в зависимости от степени важности этих событий следует либо продолжить начатое обслуживание, либо прервать его, переключившись на обслуживание нового); выполнение переключения программного контекста (сохранение состояния прерываемой программы и переключение на программу обслуживания, адрес которой заранее однозначно сопоставлен типу прерывающего события (так называемый "вектор прерывания" или "точка входа в обработчик"); выполнение восстановления программного контекста (восстановление состояния прерванной программы и обратное переключение на нее). Общая схема обработки аппаратных прерываний следующая. При возникновении любого прерывания флаг I регистра SREG аппаратно сбрасывается, тем самым запрещая обработку других прерываний. При нормальном течении событий он автоматически устанавливается опять, когда обработка прерывания заканчивается (по команде reti). После сброса флага I контроллер определяет, запрос на обработку какого именно прерывания произошел, - это делается по флагу конкретного прерывания, который также автоматически устанавливается при возникновении прерывания (например, для таймеров эти флаги находятся в регистрах TIFR или ETIFR, для внешних прерываний - в регистре GIFR или EIFR и т. п.). После определения типа прерывания контроллер автоматически вычисляет адрес соответствующего вектора прерывания. Перед тем как перейти по вектору прерывания, МК сбрасывает флаг прерывания и автоматически сохраняет содержимое счетчика команд в стеке. Отметим, что аппаратный стек имеется лишь в некоторых младших моделях Tiny, во всех остальных моделях для успешного вызова прерываний в процедуру инициализации контроллера необходимо включать следующие строки (обычно их ставят сразу после метки, на которую осуществляется переход по вектору сброса RESET): Листинг 8.5. ... RESET: ldi out ldi out temp,low(RAМEND) ;загрузка указателя стека SPL,temp temp,high(RAМEND) ;загрузка указателя стека SPH,temp …………………… sei ;другие установки ;разрешаем прерывания 11 Для моделей, имеющих аппаратный стек (АTtiny28), эти строки включать в программу не нужно, но для них следует учитывать ограничение: т.к. аппаратный стек имеет три уровня, то вызов более чем трех вложенных подпрограмм (в том числе прерываний) попросту "обрушит" про грамму, которая уже не сможет "вспомнить", куда нужно вернуться в конечном итоге. Вместе с входом в подпрограмму обработки прерывания аппаратно сбрасывается также и соответствующий флаг, вызвавший прерывание. Некоторые флаги прерываний могут быть сброшены самим пользователем посредством установки соответствующего флага в лог. 1. Заканчиваться процедура-обработчик должна командой выхода из прерывания reti. По этой команде восстанавливается содержимое счетчика команд и устанавливается опять общий флаг разрешения прерываний. Если во время обработки прерывания произошли еще какие-то прерывания, то их флаги окажутся установленными, и процедуры их обработки начнут выполняться незамедлительно (точнее, после выполнения одной команды основной программы), в том порядке, в каком они расположены в таблице векторов прерываний. При такой системе "потерять" прерывание можно только при большой загрузке МК, когда события следуют чаще, чем успевают обрабатываться. Отметим, что иногда обработка прерываний может мешать выполнению каких-то длинных процедур, которые нельзя прерывать (например, не допускается возникновение прерывания во время записи в EEPROM). В этом случае прерывания всегда можно временно запретить командой cli (отметим, что при вызове таких длительных процедур изнутри обработчика прерывания проблема снимается, если, конечно, не разрешены вложенные прерывания). Кроме того, в любой программе почти всегда имеются глобальные "рабочие" переменные (в наших программах такую переменную мы будем обозначать, как temp), использование которых следует отслеживать, т. к. они могут быть "испорчены", если между операциями с этими переменными "вклинится" прерывание, в котором они также задействованы. В этом случае можно временно сохранять содержимое переменной в стеке командой push и затем восстанавливать командой рор. Не следует также забывать, что содержимое регистра флагов SREG при переходе к обработке прерывания не сохраняется. SREG, кроме флага разрешения прерываний, содержит другие флаги, задействованные, например, в арифметических операциях, командах сравнения и др. Поэтому если прерывание "вклинится", например, между командой сравнения и командой перехода в зависимости от его результата, то при наличии в обработчике команд, модифицирующих SREG, выполнение этой последовательности команд может оказаться некорректным. При опасности такого развития событий регистр SREG также следует сохранять в стеке. 12 Микроконтроллеры семейства Mega поддерживают очередь прерываний, которая работает следующим образом: если условия генерации одного или более прерываний возникают в то время, когда флаг общего разрешения прерываний сброшен (все прерывания запрещены), соответствующие флаги устанавливаются в «1» и остаются в этом состоянии до установки флага общего разрешения прерываний. После разрешения прерываний выполняется их обработка в порядке приоритета. Время ответа на прерывание Время реагирования, прошедшее от наступления прерывания вплоть до выполнения соответствующей подпрограммы, для всех видов прерываний составляет минимум четыре цикла такта системной синхронизации. В течение этих четырех тактов два байта адреса возврата будут сохранены в стеке, указатель стека будет декрементирован на 2, а также будет выполнен переход по адресу соответствующей подпрограммы. Если прерывание наступает во время выполнения команды, состоящей из нескольких циклов, то в любом случае выполнение этой команды будет закончено, а затем будет обработано прерывание. Еще два такта занимает переход по команде rjmp (или три для команды jmp) к процедуре обработчику. Возврат из подпрограммы обработки прерывания выполняется (как и при возврате из обычной подпрограммы) также за четыре тактовых цикла. В течение этих четырех тактов системной синхронизации два байта адреса возврата будут перенесены из стека в счетчик команд, и указатель стека будет инкрементирован на 2. Возврат из подпрограммы обработки прерывания реализован, как правило, с помощью команды reti. Эта команда не только приводит к возврату в место прерывания программы, но также устанавливает разряд I в регистре состояния для того, чтобы снова разрешить прерывания. Если после возврата из подпрограммы обработки прерывания обнаружится прерывание, находящееся в режиме ожидания, то до его обработки будет выполнена как минимум одна команда основной программы. ОБЗОР РЕГИСТРОВ, ИСПОЛЬЗУЕМЫХ ДЛЯ УПРАВЛЕНИЯ ВНЕШНИМИ ПРЕРЫВАНИЯМИ Внешние прерывания вызываются сигналами на выводах INT0 и INT1 (в МК базовых серий), либо на выводах INT7:1 для МК семейства mega. Будет ли прерывание вызвано, определяется состоянием регистров, используемых для управления процедурами обработки прерываний. Самым главным регистром, используемым для управления прерываниями, является регистр SREG бит I которого разрешает или запрещает все прерывания. Формат регистра SREG представлен выше. Каждое внешнее прерывание может быть индивидуально разрешено или запрещено при помощи регистров масок внешних прерываний: GIMSK ( EIMSK). 13 При каких условиях будет вызвано прерывание на входах INТx (уровнем лог. 0 или нарастающим/ниспадающим фронтом сигнала) определяется с помощью разрядов ISCx1:0, которые входят в регистры MCUCR (или EICRA и EICRB). Для установки ISC01:0 и ISC11:0 для INT0 и INT1 используется регистр управления MCUCR. Для установки ISCх1:0 (х=0÷7) для INTх (х=0÷7) используются регистры управления EICRA и EICRB . Если внешнее или аппаратное прерывание было разрешено по уровню сигнала, то прерывания будут вызываться до тех пор, пока на соответствующем входе INTx находится сигнал низкого уровня. Признаки возникновения события, вызывающего прерывание (флаги) хранятся в регистрах флагов GIFR и EIFR. Если внешние прерывания разрешены разрядом разрешения INTx (x=0 или 1) в регистре GIMSK, то они вызываются даже в том случае, когда выводы INT0/ INT1 сконфигурированы как выход. Это предоставляет пользователю возможность использовать программные прерывания. Для управления процедурами обслуживания прерываний от внутренних аппаратных источников МК также используют набор специальных регистров. Так например, для управления прерываниями от событий, формируемых таймерами/счетчиками, используются регистры TIMSK (ЕTIMSK), ТIFR (ЕТIFR). Регистры масок внешних прерываний GIMSK Разрешения на внешние прерывания вырабатываются через регистр GIMSK (General Interrupt Mask Register), который находится по адресу $3В ($5В) в области ввода/вывода. После поступления сигнала сброса он инициализируется значением $00. В микроконтроллерах АT90S8515, АT90S4414 и АT90S23 13 используются только разряды 6 и 7 регистра GIMSK. Они доступны как на чтение, так и на запись. Разряды 0-5 зарезервированы компанией Atmel для дальнейшего расширения и доступны только для чтения (всегда содержат лог. 0). Разряд $38 ($58) 7 6 INT1 INT0 5 4 3 2 1 0 - - - - - - GIMSK Рис.8.5. Если разряд INT1 установлен в лог. 1, то внешнее прерывание 1 будет разрешено до тех пор, пока будет установлен разряд общего разрешения прерываний в регистре состояния. Будет ли прерывание вызываться по фронту сигнала или же по уровню лог. 0 на выводе INT1, определяют разряды ISC11 и ISC10 в регистре 14 MCUCR. Адрес вызова внешнего прерывания 1 для соответствующего микроконтроллера семейства АVR может быть взят из таблицы векторов прерываний ($004). Если разряд INT0 установлен в лог. 1, то будет разрешено внешнее прерывание 0 до тех пор, пока в регистре состояния будет установлен разряд общего разрешения прерываний. Будет ли прерывание вызываться по фронту сигнала или же по уровню лог.0 на выводе INT0, определяют разряды ISC0l и ISC00 в регистре MCUCR. Адрес внешнего прерывания 0 - $002. Регистр маски внешних прерываний EIMSK В моделях ATmega64x и ATmega128x для разрешения/запрещения внешних прерываний предназначен регистр EIMSK (External Interrupt Mask — регистр маски внешних прерываний). Каждый разряд INTx регистра отвечает за разрешение/запрещение прерывания с номером, соответствующим номеру разряда. Если n-ый разряд регистра установлен в «1» и флаг I регистра SREG также установлен в «1», то прерывание с вывода INTx разрешено. Формат регистра имеет вид: $39($59) Разряд 7 6 5 4 3 2 1 0 EIMSK INT7 INT6 INT5 INT4 INT3 INT2 INT1 INT0 Рис.8.6. Биты 7-0 имеют то же назначение, что и рассмотренные биты регистра GIMSK. Регистры флагов внешних прерываний GIFR Состояние внешнего прерывания определяется по регистру GIFR (General Interrupt Flag Register - общий регистр флагов прерываний). В моделяхAT90S8515, AT90S4414 и AT90S2313 он находится по адресу $3А ($5А) в области ввода/вывода. После поступления сигнала сброса регистр GIFR инициализируется записью значения $00. В моделях АT90S8515, АT90S4414 и АT90S2313 используются только разряды б и 7 регистра GIFR, доступные для чтения и записи. Разряды 0-5 зарезервированы компанией Atmel и доступны только для чтения (всегда содержат лог. 0). Разряд $3A ($5A) 7 6 5 INTF1 INTF0 - 4 - 3 - 2 - 1 - 0 - GIFR Рис.8.7. Флаг INTFl (External Interrupt Flag 1 - флаг 1 внешних прерываний) устанавливается в лог. 1, если сигнал на выводе INT1 вызывает внешнее прерывание 1. 15 При входе в подпрограмму обработки прерывания разряд INTF1 переводится в исходное состояние аппаратно. Альтернативно, разряд INTF1 может быть сброшен в состояние лог. 0 путем записи лог. 1 в разряд 7 регистра GIFR. Аналогично для флага INTF0. Регистры флагов внешних прерываний EIFR Для индикации возникновения внешних прерываний в моделях ATmega64x и ATmega128x предназначен регистр EIFR (External Interrupt Flag Register — регистр флагов внешних прерываний). Регистр флагов внешних прерываний имеет формат. Разряд $38($58) 7 EIFR INTF7 6 5 INTF6 4 INTF5 3 INTF4 2 INTF3 1 INTF 0 INTF1 INTF0 Рис.8.7. При возникновении запроса на прерывание на выводе INTn соответствующий флаг INTFn (n-ый разряд регистра) устанавливается в «1». Флаг сбрасывается аппаратно при запуске подпрограммы обработки прерывания или программно, записью в него логической 1. Если генерация прерывания должна происходить по НИЗКОМУ уровню на выводе, соответствующий флаг сброшен постоянно. Установка режимов вызова внешних прерываний Условия генерации внешних прерываний (нарастающий/спадающий фронт сигнала или по низкий уровень сигнала на выводе INTx) определяются конфигурацией битов регистров управления внешними прерываниями EICRn (External Interrupt Control Registers) – EICRA(INT3:0) и EICRB(INT7:4). Если внешнее прерывание настроено на срабатывание по низкому уровню на входе, то прерывание будет генерироваться все время, пока на выводе INTx будет сигнал низкого уровня. В таблице 2 определены условия генерации внешних прерываний в зависимости от конфигурации битов регистров управления. Регистр А управления внешними прерываниями - EICRA EICRA – (External Interrupt Mask) Бит ($6A) Read/Write Начальная величина 7 ISC31 R/W 6 ISC30 R/W 5 ISC21 R/W 4 ISC20 R/W 3 ISC11 R/W 2 ISC10 R/W 1 ISC01 R/W 0 ISC00 R/W 0 0 0 0 0 0 0 0 Рис.8.8. 16 Регистр B управления внешними прерываниями - EICRB EICRB – (External Interrupt Mask) Бит $3A($5A) Read/Write Начальная величина 7 ISC71 R/W 6 ISC70 R/W 5 ISC61 R/W 4 ISC60 R/W 3 ISC51 R/W 2 ISC50 R/W 1 ISC41 R/W 0 ISC40 R/W 0 0 0 0 0 0 0 0 Рис.8.9. Обнаружение фронтов сигналов на выводах INT3:INT0 осуществляется асинхронно, при этом минимальная длительность импульса, гарантирующая генерацию прерывания, составляет 50нc. А на выводах INT7:INT4 обнаружение фронтов сигналов осуществляется синхронно, поэтому минимальная длительность импульса, гарантирующая генерацию прерывания, составляет 1 период тактового сигнала микроконтроллера. Если генерация прерывания должна происходить по низкому уровню, то он должен удерживаться на выводе до окончания выполнения текущей команды, в противном случае генерации прерывания не произойдет. Выбор режима вызова внешнего прерывания INTх определяется установкой соответствующих бит ISCx1:0 указанных выше регистров управления микроконтроллером (табл.8.2). Таблица 8.2 ISCx1 ISCx0 Описание Низкий уровень на входе INTx генерирует запрос на 0 0 прерывание Любое изменение логического уровня на входе INTx 0 1 генерирует запрос на прерывание Задний фронт входного сигнала INTx вызывает запрос на 1 0 прерывание Передний фронт входного сигнала INTx вызывает запрос на 1 1 прерывание Работа системы прерывания по переднему (заднему) фронту происходит следующим образом. Сначала схема обнаружения фронта фиксирует уровень сигнала на входе lNТ0. Затем она ожидает изменения этого уровня. Если уровень на входе изменится и этот измененный уровень продержится в течение одного периода тактового сигнала, то происходит вызов прерывания. Если изменение продержится меньше одного периода, вызов прерывания не гарантируется. Если выбран режим прерывания по уровню, то для того, чтобы вызвать прерывание, низкий уровень должен удерживаться на входе, пока не закончится процесс выполнения текущей команды. Вызов прерываний INТ7 – INT0 по низкому уровню осуществляется в асинхронном режиме. Это означает, что такое прерывание может быть использовано для пробуждения из любого спящего режима за исключением режима Idle. Синхросигнал системы ввода-вывода выключается во всех спящих режимах, кроме режима Idle. 17 Внимание. Если для пробуждения микроконтроллера используется прерывание по низкому уровню, то этот уровень должен удерживаться достаточно долго, чтобы микроконтроллер успел выйти из режима сна и начать обработку этого прерывания. Если низкий уровень исчезнет раньше, чем запустится микроконтроллер, то процедура обработки прерывания не будет запущена и прерывание останется невыполненным. Время запуска микроконтроллера определяется при помощи fusе-переключателей SUТ и CKSEL. Далее рассмотрим конкретный пример реализации программы способной обрабатывать внешнее прерывание INT0. Листинг данной программы приведен ниже. Листинг программы 8.6. .include "m128def.inc" .DSEG //Резервирование места для переменных в ОЗУ .CSEG .org 0x0000 jmp Reset .org INT0addr //Адрес вектора внешнего прерывания INT0 jmp INT0addr_Routing //В области памяти программ от 0х0000 до ... // INT_VECTORS_SIZE=0x0046 помещаются ссылки // на обработчики прерываний .org INT_VECTORS_SIZE Reset: ldi r16,high(RAMEND) //Инициализация стека out SPH,r16 ldi r16, low(RAMEND) out SPL,r16 //Условие генерации прерывания – нарастающий фронт сигнала // на выводе INT0 Clr r16 Sbi r16, INT0 out EIMSK , r16 //Разрешение прерывания INT0 ldi r16 , (1<<ISC01) | (1<<ISC00) out EICRA , r16 sei //Разрешение прерываний Loop: //Тело основного цикла rjmp Loop INT0addr_Routing: //Во всех прерываниях обязательно сохраняем контекст push r16 //Необходимо сохранить используемые в прерывании 18 // регистры in r16 , SREG push r16 ... //Тело процедуры обслуживания прерывания //Загружаем контекст pop r16 out SREG , r16 pop r16 RETI В начале программы подключается стандартный файл описания зарезервированных констант. Зарезервированные константы хранят под заранее определенными лингвистическими именами адреса и номера битов регистров ввода/вывода. Рассматриваемая программа реализована на микроконтроллере ATmega128. Необходимо организовать генерацию прерывания по нарастающему фронту сигнала на выводе INT0. Для этого необходимо организовать таблицу прерываний, где по адресу INT0addr поместить команду безусловного перехода к процедуре обработки прерывания. Для резервирования места для всей таблицы метку Reset можно поместить по адреса следующему за адресом последнего прерывания. Адрес последнего прерывания равняется 0х0044. А зарезервированная в файле описаний константа INT_VECTORS_SIZE=0х0046. После сброса в счетчик команд загружается адрес вектора сброса (0х0000). По этому адресу находиться команда безусловного перехода на метку Reset, с которой начинается тело основной программы. Она начинается с инициализации вершины стека. Важно чтобы глобальные прерывания были запрещены (флаг I по умолчанию сброшен) до установки вершины стека так как при возникновении прерывания значение счетчика команд сохраняется в стек. То есть разрешение глобальных прерываний командой sei должно происходить после инициализации стека. В общем случае вершина стека помещается в конец ОЗУ. Адрес последней ячейки ОЗУ определяется константой RAMEND. Причем это значение напрямую зависит от объема ОЗУ и для микроконтроллера ATmega128 с объемом ОЗУ 4Кбайт RAMEND=0x10FF (Так как в начале ОЗУ хранится регистровый файл и регистры ввода/вывода, то адресация начинается с 0х0100, тогда объем ОЗУ равняется RAMEND-0x00FF=0x1000(4096байт=4Кбайта)). Для разрешения/запрещения внешних прерываний предназначен регистр EIMSK. Разряд 0 регистра отвечает за разрешение/запрещение прерывания INT0. Если 0-ый разряд регистра установлен в «1» и флаг I регистра SREG также установлен в «1», то прерывание с вывода INT0 разрешено. Для установки нужного условия генерации внешнего прерывания (нарастающий фронт сигнала на выводе INT0) необходимо установит биты ISC00 и ISC01 регистра управления внешними прерываниями EICRA. 19 Вывод INT0 по умолчанию настроен на вывод, поэтому никаких изменений в настройке порта делать не нужно. После инициализации внешнего прерывания необходимо разрешить глобальные прерывания, установив флаг I командой sei. После этого при нарастающем фронте импульса на выводе INT0 будет сгенерированно прерывание. Микроконтроллер сохранит в стек содержимое счетчика команд PC и загрузит в него адрес INT0addr вектора прерывания INT0. По этому адресу находится команда безусловного перехода к подпрограмме обработки прерывания jmp INT0addr_Routing. Она выполняет заранее определенные функции. Последней командой подпрограммы обработки прерывания является команда RETI, которая обеспечивает возврат в основную программу. Она восстановление предварительно сохраненного счетчика команд и устанавливает флаг глобального разрешения прерываний I регистра SREG. 20 ПРИЛОЖЕНИЕ GIMSK (General Interrupt Mask Register) В микроконтроллерах АT90S8515, АT90S4414 и АT90S23 13 используются только разряды 6 и 7 регистра GIMSK. Они доступны как на чтение, так и на запись. Разряд $38 7 ($58) 6 INT1 INT0 5 4 3 2 1 0 - - - - - - GIMSK EIMSK (External Interrupt Mask) Разряд EIMSK $39($59) 7 6 5 4 3 2 1 0 INT7 INT6 INT5 INT4 INT3 INT2 INT1 INT0 Биты 7-0 имеют то же назначение, что и рассмотренные биты регистра GIMSK. GIFR (General Interrupt Flag Register) Состояние внешнего прерывания определяется по регистру GIFR. Разряд $3A ($5A) 7 6 5 INTF1 INTF0 - 4 3 - 2 - 1 - 0 - - GIFR EIFR (External Interrupt Flag Register) Для индикации возникновения внешних прерываний в моделях ATmega64x и ATmega128x 7 Разряд $38($58) EIFR INTF7 6 5 INTF6 4 INTF5 3 INTF4 2 INTF3 1 INTF 0 INTF1 INTF0 EICRA – (External Interrupt Mask) Бит ($6A) Read/Write Начальная величина 7 ISC31 R/W 6 ISC30 R/W 5 ISC21 R/W 4 ISC20 R/W 3 ISC11 R/W 2 ISC10 R/W 1 ISC01 R/W 0 ISC00 R/W 0 0 0 0 0 0 0 0 EICRB – (External Interrupt Mask) Бит $3A($5A) Read/Write Начальная величина 7 ISC71 R/W 6 ISC70 R/W 5 ISC61 R/W 4 ISC60 R/W 3 ISC51 R/W 2 ISC50 R/W 1 ISC41 R/W 0 ISC40 R/W 0 0 0 0 0 0 0 0 21 Листинг программы 8.6. .include "m128def.inc" .DSEG //Резервирование места для переменных в ОЗУ .CSEG .org 0x0000 jmp Reset .org INT0addr //Адрес вектора внешнего прерывания INT0 jmp INT0addr_Routing //В области памяти программ от 0х0000 до ... // INT_VECTORS_SIZE=0x0046 помещаются ссылки // на обработчики прерываний .org INT_VECTORS_SIZE Reset: ldi r16,high(RAMEND) //Инициализация стека out SPH,r16 ldi r16, low(RAMEND) out SPL,r16 //Условие генерации прерывания – нарастающий фронт сигнала // на выводе INT0 clr r16 sbi r16, INT0 out EIMSK , r16 //Разрешение прерывания INT0 ldi r16 , (1<<ISC01) | (1<<ISC00) out EICRA , r16 sei //Разрешение прерываний Loop: //Тело основного цикла rjmp Loop INT0addr_Routing: //Во всех прерываниях обязательно сохраняем контекст push r16 //Необходимо сохранить используемые в прерывании // регистры in r16 , SREG push r16 ... //Тело процедуры обслуживания прерывания //Загружаем контекст pop r16 out SREG , r16 pop r16 RETI 22 Таблица прерываний ATmega128 Номер вектора Адрес вектора 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 $0000 $0002 $0004 $0006 $0008 $000A $000C $000E $0010 $0012 $0014 $0016 $0018 $001A $001С $001E $0020 $0022 $0024 $0026 $0028 $002A $002C $002E $0030 $0032 $0034 $0036 $0038 $003A $003C $003E $0040 $0042 $0044 Источник RESET INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 TIMER2 COMP TIMER2 OVF TIMER1 CAPT TIMER1 COMPA TIMER1 COMPB TIMER1 OVF TIMER0 COMP TIMER0 OVF SPI, STC USART0, RX USART0, UDRE USART0, TX ADC ЕЕ READY ANALOG COMP TIMER1 COMPC TIMER3 CAPT TIMER3 COMPA TIMER3 COMPB TIMER3 COMPC TIMER3 OVF USART1, RX USART1, UDRE USART1,TX TWI SPM READY Описание Сброс от любого внешнего источника Внешнее прерывание 0 Внешнее прерывание 1 Внешнее прерывание 2 Внешнее прерывание 3 Внешнее прерывание 4 Внешнее прерывание 5 Внешнее прерывание 6 Внешнее прерывание 7 Совпадение таймера/счетчика 2 Переполнение таймера/счетчика 2 Захват таймера/счетчика 1 Совпадение «A» таймера/счетчика 1 Совпадение «B» таймера/счетчика 1 Переполнение таймера/счетчика 1 Совпадение таймера/счетчика 0 Переполнение таймера/счетчика 0 Передача по SPI завершена USART0, прием завершен Регистр данных USART0 пуст USART0, передача завершена Преобразование АЦП завершено Готовность EEPROM Прерывание от аналогового компаратора Совпадение «C» таймера/счетчика 1 Захват таймера/счетчика 3 Совпадение «A» таймера/счетчика 3 Совпадение «B» таймера/счетчика 3 Совпадение «C» таймера/счетчика 3 Переполнение таймера/счетчика 3 USART1, прием завершен Регистр данных USART1 пуст USART1, передача завершена Прерывание от модуля TWI Готовность SPM 23 Листинг 8.1. фрагмент файла "m128def.inc" .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ .equ INT0addr = 0x0002 INT1addr = 0x0004 INT2addr = 0x0006 INT3addr = 0x0008 INT4addr = 0x000a INT5addr = 0x000c INT6addr = 0x000e INT7addr = 0x0010 OC2addr = 0x0012 OVF2addr = 0x0014 ICP1addr = 0x0016 OC1Aaddr = 0x0018 OC1Baddr = 0x001a OVF1addr = 0x001c OC0addr = 0x001e OVF0addr = 0x0020 SPIaddr = 0x0022 URXC0addr = 0x0024 UDRE0addr = 0x0026 UTXC0addr = 0x0028 ADCCaddr = 0x002a ERDYaddr = 0x002c ACIaddr = 0x002e OC1Caddr = 0x0030 ICP3addr = 0x0032 OC3Aaddr = 0x0034 OC3Baddr = 0x0036 OC3Caddr = 0x0038 OVF3addr = 0x003a URXC1addr = 0x003c UDRE1addr = 0x003e UTXC1addr = 0x0040 TWIaddr = 0x0042 SPMRaddr = 0x0044 INT_VECTORS_SIZE ; External Interrupt Request 0 ; External Interrupt Request 1 ; External Interrupt Request 2 ; External Interrupt Request 3 ; External Interrupt Request 4 ; External Interrupt Request 5 ; External Interrupt Request 6 ; External Interrupt Request 7 ; Timer/Counter2 Compare Match ; Timer/Counter2 Overflow ; Timer/Counter1 Capture Event ; Timer/Counter1 Compare Match A ; Timer/Counter Compare Match B ; Timer/Counter1 Overflow ; Timer/Counter0 Compare Match ; Timer/Counter0 Overflow ; SPI Serial Transfer Complete ; USART0, Rx Complete ; USART0 Data Register Empty ; USART0, Tx Complete ; ADC Conversion Complete ; EEPROM Ready ; Analog Comparator ; Timer/Counter1 Compare Match C ; Timer/Counter3 Capture Event ; Timer/Counter3 Compare Match A ; Timer/Counter3 Compare Match B ; Timer/Counter3 Compare Match C ; Timer/Counter3 Overflow ; USART1, Rx Complete ; USART1, Data Register Empty ; USART1, Tx Complete ; 2-wire Serial Interface ; Store Program Memory Read = 70 ; size in words 24