Прерывания – это специальный механизм, позволяющий остановить выполнение основной программы и переключить процессор на выполнение другой задачи по определенному внешнему или внутреннему событию. Фактически прерывания являются обыкновенными подпрограммами, которые в тот или иной момент времени микропроцессор может вызывать аппаратно. Такие подпрограммы принято называть обработчиками прерываний.
В большинстве случаев прерывания позволяют очень сильно разгрузить ЦПУ от той работы, которую самостоятельно могут выполнять отдельные его модули. Например, любой таймер-счетчик, отсчитав необходимое число тактов генератора, может сгенерировать прерывание и вызвать подпрограмму, в которой будет находиться код для отчета различных временных интервалов. Точно таким же образом при наступлении определенного события (отсылка или прием слова данных, изменение состояния на линии и мн. др.) способны оповещать процессор модули 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 cbi 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
Вложенные прерывания могут оказаться недопустимыми при малом размере стека.
Перейти к следующей части: Порты ввода-вывода
Комментарии (1) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация
sbi DDRD,PD2 ;функция INT0) и подключаем к ней внутренний резистор