Прерывания

Прерывания

Прерывания – это специальный механизм, позволяющий остановить выполнение основной программы и переключить процессор на выполнение другой задачи по определенному внешнему или внутреннему событию. Фактически прерывания являются обыкновенными подпрограммами, которые в тот или иной момент времени микропроцессор может вызывать аппаратно. Такие подпрограммы принято называть обработчиками прерываний.

В большинстве случаев прерывания позволяют очень сильно разгрузить ЦПУ от той работы, которую самостоятельно могут выполнять отдельные его модули. Например, любой таймер-счетчик, отсчитав необходимое число тактов генератора, может сгенерировать прерывание и вызвать подпрограмму, в которой будет находиться код для отчета различных временных интервалов. Точно таким же образом при наступлении определенного события (отсылка или прием слова данных, изменение состояния на линии и мн. др.) способны оповещать процессор модули USART, SPI, TWI, ADC и т.д. Различные модели AVR могут содержать от 4 до 56 таких источников прерываний.

Табл.5. Таблица векторов прерываний:

Номер Адрес в памяти программ Бит разрешение прерывания Флаг прерывания Описание события
1 0x0001 INT0 из GICR INTF0 из GIFR Внешнее прерывание 0
2 0x0002 INT1 из GICR INTF1 из GIFR Внешнее прерывание 1
3 0x0003 OCIE2 из TIMSK OCF2 из TIFR Cовпадение TCNT2 и OCR2
4 0x0004 TOIE2 из TIMSK TOV2 из TIFR Переполнение TCNT2
5 0x0005 TICIE1 из TIMSK ICF1 из TIFR Захват в ICP1
6 0x0006 OCIE1A из TIMSK OCF1A из TIFR Совпадение TCNT1 и OCR1A
7 0x0007 OCIE1B из TIMSK OCF1B из TIFR Совпадение TCNT1 и OCR1B
8 0x0008 TOIE1 из TIMSK TOV1 из TIFR Переполнение TCNT1
9 0x0009 TOIE2 из TIMSK TOV2 из TIFR Переполнение TCNT0
10 0x000A SPIE из SPCR SPIF из SPSR Прерывание от модуля SPI
11 0x000B RXCIE из UCSRB RXC из UCSRA Получение байта по USART
12 0x000C UDRIE из UCSRB UDRE из UCSRA Опустошение UDR в USART
13 0x000D TXCIE из UCSRB TXC из UCSRA Передача байта по USART
14 0x000E ADIE из ADCSRA ADIF из ADCSRA Прерывание от АЦП
15 0x000F EERIE из EECR EEMWE из EECR Завершение записи в EEPROM
16 0x0010 ACIE из ACSR ACI из ACSR Прерывание от компаратора
17 0x0011 TWIE из TWCR TWINT из TWCR Прерывание от модуля TWI
18 0x0012 SPMIE из SPMCR SPMIE из SPMEN Завершение выполнения spm

За каждым обработчиком прерывания жестко закреплен определенный адрес (вектор прерывания) в начале памяти программ. Положения векторов прерываний для ATmega8 сведены табл.5. Обычно по адресу  вектора прерывания находится инструкция перехода, которая передает управление подпрограмме обработчика:

.cseg .org 0 ;начало с нулевого адреса памяти программ rjmp initial ;переход на начало основной программы rjmp service_INT0 ;переход на метку service_INT0 rjmp service_INT1 ;переход на метку service_INT1 . rjmp service_TWI ;переход на метку service_TWI rjmp service_SPMR ;переход на метку service_SPMR

В моделях AVR с объемом FLASH ≤8 кбайт, для векторов отводится по 1 слову памяти программ, как раз для инструкций rjmp. Во всех остальных микроконтроллерах каждый вектор прерывания занимает уже 2 слова, а в качестве инструкции перехода используются jmp.

Управление прерываниями производится индивидуально. За разрешение каждого из них отвечают специальные разряды соответствующих РВВ, а о наступлении события микроконтроллер может судить по состоянию флагов прерывания (см. табл.5). Например, если прерывание по переполнению таймера-счетчика 2 разрешено (установлен бит TOIE2 из TIMSK), то при изменении содержимого счетного регистра TCNT2 c 0xFF на 0x00 в регистре TIFR аппаратно будет установлен флаг прерывания TOV2 и микроконтроллер вызовет подпрограмму по адресу 0x0004.

За общее управление прерываний у AVR отвечает флаг I из регистра SREG. При I=0 все прерывания, независимо от состояния битов разрешения, запрещены.

При вызове обработчика прерывания адрес текущей команды в основной программе копируется в стек, как и при обычном вызове подпрограммы. Но вместе с этим микроконтроллер аппаратно сбрасывает на нуль флаг I и флаг, который явился источником прерывания. Обработчик должен заканчиваться командой возврата из прерывания reti. После ее выполнения адрес возврата восстанавливается в PC и при этом одновременно устанавливается флаг I.

Ниже рассмотрен пример использования обработчика внешнего прерывания INT0.

.include “m8def.inc” ;подключение стандартного заголовочного файла .cseg ;начало секции кода с нулевого адреса .org 0 rjmp main ;вектор сброса rjmp service_INT0 ;вектор внешнего прерывания 0 . main: ldi R16,low(RAMEND) ;инициализируем указатель стека out SPL,R16 ldi R16,high(RAMEND) out SPH,R16 sbi PORTD,PD2 ;настраиваем на ввод линию 2 порта D (альтернативная sbi DDRD,PD2 ;функция INT0) и подключаем к ней внутренний резистор ldi R16,1«ISC01 ;задаем условием прерывания изменения out MCUCR,R16 ;состояния вывода INT0 с лог.1 на лог.0 ldi R16,1«INT0 ;разрешаем прерывание INT0 out GICR,R16 sei ;разрешаем прерывания глобально (I=1) . service_INT0: push R16 ;сохраняем в стеке R16 in R16,SREG push R16 ;сохраняем в стеке SREG . pop R16 ;восстанавливаем из стека SREG out SREG,R16 pop R16 ;восстанавливаем из стека R16 reti

Инструкция перехода, размещенная по нулевому адресу (вектор сброса у всех моделей AVR), передает управление на начало основной программы main, где и происходит инициализация микроконтроллера. В качестве условия возникновения прерывания выбрано изменение состояния вывода INT0 с уровня лог.1 на лог.0 (момент нажатия кнопки). При возникновении указанного события произойдет вызов подпрограммы по адресу 0x0001 (вектор прерывания INT0) и, далее, обработчика service_INT0. В обработчике нужно сохранить содержимое SREG и, если это необходимо, остальных регистров, которые используются в контексте основной программы.

Возможна такая ситуация, что в процессе работы одновременно возникнут сразу несколько запросов на прерывания (одновременно будут установлены несколько флагов прерывания). В этом случае первым будет вызван тот обработчик, чей адрес в таблице векторов прерывания находится выше. Например, при возникновении запросов от АЦП (адрес 0x000E) и компаратора (адрес 0x0010), первым будет обработан запрос от АЦП. Таким образом, каждое прерывание у AVR имеет свой собственный неизменный приоритет, который зависит от его местоположением в таблице векторов.

Здесь возможны две проблемы. Во-первых, обработка отдельных прерываний может быть достаточно длительной процедурой и другие запросы окажутся отложенными на недопустимо большой срок. А во-вторых, прерывание с низким приоритетом может иметь намного большее значение для данного устройства. В обоих случаях можно выйти из положения, если допустить в программе вложенные прерывания. Для этого после сохранения контекста в обработчике прерывания нужно вручную установить флаг I командой sei:

service_INT0: push R16 ;сохраняем в стеке R16 in R16,SREG push R16 ;сохраняем в стеке SREG sei ;разрешаем прерывания во время обработчика . pop R16 ;восстанавливаем из стека SREG out SREG,R16 pop R16 ;восстанавливаем из стека R16 reti

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


Категория: Микроконтроллеры
Метки:

Написать коментарий

*
= 5 + 0

Добавить изображение

Последние статьи