Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
УП МПУ-13.doc
Скачиваний:
13
Добавлен:
01.04.2025
Размер:
6 Мб
Скачать
☆

Часть 4. Прерывания (л8)

4.1. Механизм прерываний в avr и его программирование

Прерывания в МК серии AVR

Таблица прерываний (см. Табл. 1) начинается с нулевой ячейки памяти программ (.cseg) и имеет шаг в одну или две ячейки. Размер шага определяется объемом памяти программ – если объем не превышает 212 = 4096 байт, то для перехода к любой ячейке памяти достаточно команды rjmp a12, она занимает в памяти одну ячейку; при большем объеме ПП требуется команда jmp a16 размером в две ячейки.

Размер таблицы равен числу источников прерываний плюс один и зависит от модели МК. Однотипные источники прерываний в разных моделях МК одного семейства нередко имеют разные вектора. Для удобства программиста в системах программирования для каждой модели МК поставляются файлы описания символьных констант (например, 2323def.inc для ассемблера в среде AVR-Studio или 90s2323.h для языка C в среде CodeVision), включающие символьные имена векторов, их написание несет смысловую нагрузку.

В первой ячейке (адрес 0) располагается первая команда, выполняемая после рестарта МК. Как правило, это команда перехода к этапу инициализации для обхода таблицы прерывания. Если в вашей программе предусмотрено общее разрешение прерываний, то по адресам векторов располагаются либо команды перехода к началу соответствующей ISR (rjmp/jmp VECTOR_N_SUBROUTINE), либо команда выхода из прерывания [reti].

Таблица 1.

ATtiny15L

ATmega128

Вект.

Адрес ПП

Источник

Описание

Вект.

Адрес ПП

Источник

Описание

1

0

RESET

External Reset, Power-on Reset,

Brown-out Reset, and Watchdog Reset

1

0

RESET

External Pin, Power-on Reset, Brown-out Reset,

Watchdog Reset, and JTAG AVR Reset

2

1

I/O Pins

External Interrupt Request 0

2

2

INT0

External Interrupt Request 0

3

2

Tim1,CompA

Pin Change Interrupt

3

4

INT1

External Interrupt Request 1

4

3

Tim1,Ovf

Timer/Cnt.1 Compare Match A

4

6

INT2

External Interrupt Request 2

…

…

…

…

…

…

…

…

9

4

ADC

ADC Conversion Complete

35

0x44

SPM READY

Store Program Memory Ready

Флаг глобального прерывания находится в регистре состояния процессора SREG.7, имеет символическое имя I [Interrupt], для общего разрешения прерываний используется команда sei, для запрещения - cli.

На этапе инициализации, как правило, устанавливаются биты регистров масок прерывания [*MSK], для излишней надежности сбрасываются биты запросов прерывания [*FR]. Последней командой перед входом в основной цикл выполняется общее разрешение прерываний.

Впрочем, это не мешает в процессе выполнения основного цикла и подпрограмм обслуживания прерывания менять состояние масок и общего разрешения. Последнее [cli] актуально для некоторых специфических процедур программирования [atomic], в которых определенное состояние триггеров аппаратных узлов удерживается на ограниченном числе машинных циклов.

Процедура предоставления прерывания МК серии AVR детально состоит из следующих этапов.

1) Этап аппаратного предоставления прерывания: в конце текущей команды при наличии запроса (флага) прерывания, индивидуальном (маска) и общем (I бит в SREG) разрешении прерываний процессор сохраняет в стеке адрес следующей команды прерываемой (фоновой) программы (4 машинных цикла), сбрасывает флаг прерывания, загружает в счетчик команд значение вектора прерывания и сбрасывает бит I регистра SREG и, тем самым, запрещает обслуживание вложенных прерываний. Время выполнения этого этапа зависит от длительности прерываемой команды и длительности перехода на начало ISR и составляет для МК серии AVR 5...6 машинных циклов.

2) Команда перехода из таблицы векторов к первому оператору ISR – на ассемблере программист по адресу прерывания (вектору) размещает команду перехода к тексту подпрограммы (2…3 м.ц.), на языке С/С++ эта команда не видна, она порождается строкой вызова функции прерывания.

3) Этап сохранения контекста – на ассемблере при необходимости программируется разработчиком – состоит в сохранении значений SREG и тех РОН, которые приходится "делить" между ISR и фоновой программой/программами. Если файл РОН недостаточен для разграничения между подпрограммами и основной программой, следует сохранять значения контекста в стеке [push] в определенном порядке. На языке С/С++ транслятор сам определяет необходимость и порядок сохранения контекста.

4) Этап выполнения собственно ISR, т. е. запланированных разработчиком действий.

5) Этап восстановления контекста – на ассемблере в обратном порядке из стека восстанавливаются значения РОН и SREG, на С/С++ обо всем заботится транслятор.

6) Этап выхода из прерывания выполняется с помощью команды RETI [RETurn Interrupt] – из стека восстанавливается значение счетчика команд (4…5 машинных цикла), возобновляется выполнение прерванной программы, причем, первая команда обязательно выполняется (I = 0), после чего устанавливается бит I общего разрешения прерывания и может начаться обслуживание следующего прерывания.

Таким образом, минимальная задержка между установкой флага запроса прерывания и первой командой обработки прерывания составляет 7…9 м. ц. Минимальное время, на которое задерживается выполнение фоновой программы, составляет 13…15 м. ц. (если отсутствует сохранение/восстановление контекста и «содержательная» часть ISR состоит из 2 м. ц.).

Прерывания не были предусмотрены при разработке языка С, поэтому реализация зависит от транслятора.

В IAR-C и CodeVision-AVR подпрограмма обслуживания прерывания оформляется как функция со специальным модификатором interrupt, за которым в квадратных скобках следует вектор прерывания, а затем уже имя функции без входных (void) и выходных (void) параметров:

#pragma vector = VECTOR // IAR-C, line 1

__interrupt void name_functiont(void) { /* тело функции */ } // IAR-C, line 2

interrupt [VECTOR] void name_function(void) {/*тело функции*/}

//CodeVision-AVR

interrupt [TIM0_OVF] void timer0_ovf_isr(void) { //CodeVision-AVR

TCNT0 = -156;//Период 200 Гц = 8MHz/256/78

flag200Hz=1;

} // ********************************

В GCC применяется более короткая запись [здесь ISR – Interrupt SubRoutine]:

ISR[VECTOR] { /* тело функции */ }

Транслятор размещает по адресу вектора прерывания команду перехода к телу функции, а в нем – команды сохранения контекста, далее – команды, полученные в результате трансляции тела ППОП, далее – команды восстановления контекста и, наконец, команду RETI.

Для передачи параметров в/из ППОП существует только механизм глобальных переменных, для запоминания значений между вызовами – статические переменные.

Для минимизации времени выполнения прерывания надо стремиться писать короткие программы обслуживания с минимальным использованием локальных и глобальных переменных, особенно при большом количестве одновременно разрешенных прерываний или их относительно высокой частоте повторения.