Первым делом о том что такое прерывание.
Прерывание (interrupt) - это своеобразная функция, которая будет выполнена при поступлении сигнала на какой нибудь вход контроллера.
При работе в AVR Studio прерывания создаются при помощи макросов ISR()
, SIGNAL()
и INTERRUPT()
. Они помечают некоторую функцию как обработчик прерывания. Их различие в том, что INTERRUPT()
и ISR()
определяют функцию обработчик для случая, когда разрешено общее прерывание (обработчик может быть прерван), а SIGNAL()
для случая когда общее прерывание запрещено.
На этом покончим с теорией и перейдём к практике (хотя теории ещё будет ниже).
Соберём в ISIS такую схему:
Как вы уже наверное догадались мы напишем прерывание (которое генерируется кнопкой) которое будет зажигать и тушить диод.
Итак, откройте студию и создайте стандартный проект.
Для использования прерываний включим заголовочный файл:
#include
Условимся, что прерывание (физически) не будет включать выключать питание на ноге контроллера (как это делается я уже рассматривал), а всего лишь будет изменять флаг. При определённых значениях которого и будет включаться и выключаться диод.
Зададим этот флаг глобально:
Int num = 1;
Теперь объявим прерывание:
ISR(SIG_INTERRUPT1){ if (num == 1) num = 0; else num = 1; }
Как видите в скобках макроса указан так называемый вектор прерывания. Этот вектор указывает компилятору для какого входа будет сгенерировано прерывание. Для INT1 - это SIG_INTERRUPT1. Для АЦП (ADC) например это - SIG_ADC. (весь перечень отлично описан в книге "Шпак Ю.А. Программирование на языке Си для AVR и PIC микроконтроллеров".)
Теперь перейдём к функции main нашей "программы".
Нам необходимо разрешить прерывания в целом и для INT1 в частности:
Sei(); // в целом
GIMSK |= (1< Когда это сделано нужно настроить поведение прерывания. Оно может быть сгенерировано по разному. Думаю как перевести это вы и так поймёте. MCUCR = (0< Теперь установим весь порт С как выход: DDRC = 0xff; // порт С - выход
Ну а это уже должно быть понятно: While (1){
if (num == 1)
PORTC |= 1; // включаем первый выход С
else
PORTC &= ~1; // выключаем первый выход С
_delay_ms(100); // ждём 100мс
}
Ждать не обязательно. Тем более что это уменьшает быстродействие. Но мне так хочется.
#define F_CPU 8000000UL // 8MHz
#include Компилируем hex и собираем схему в Proteus. Наслаждаемся работой прерывания при изменении положения кнопки. Для чего нужны внешние прерывания
Прерывание — это событие по которому прерывается исполнение основного кода программы (например функции main) и управление передаётся функции обработчику прерывания. Соответственно внешние прерывания — это некие внешние события прерывающие исполнение основного кода программы. Внешние прерывания позволяют получить быструю, гарантированную реакцию на внешние события. По этому наиболее частое применение внешних прерываний это реализация счетчиков импульсов, измерение частоты или длительности импульсов, программная реализация uart, one-wire, i2с, spi, а так-же обработка сигналов от внешних периферийных устройств. Для того что бы микроконтроллер узнал о внешних событиях используются дискретные входы INT0 INT1 и т.д. Дискретные означает что они работают с логическими уровнями: 0 и 1. Внешние прерывания можно разделить на два типа: Срабатывание внешнего прерывания может быть настроено на низкий или высокий логический уровень. Например, если прерывание настроено на низкий логический уровень, то оно возникает когда на входе INT напряжение равно нулю. Если же прерывание настроено на высокий уровень, то оно возникает когда на входе логическая 1. Прерывание по переднему фронту или, как иногда говорят, нарастанию сигнала, возникает когда происходит изменение уровня сигнала на входе INT с 0 на 1. Прерывание по заднему фронту (спаду сигнала), возникает при изменении уровня сигнала на входе INT с 1 на 0. Внешние прерывания в avr atmega8
настраиваются при помощи бит ISCxx
регистра MCUCR
. Зависимость условия срабатывания внешнего прерывания INT0 от бит ISC0x регистра MCUCR в avr atmega8
Для внешнего прерывания INT1
, настройка производиться так же, только используются биты ISC11
ISC10
. Пример
настройки внешнего прерывания для avr atmega8:
//сбрасываем все биты ISCxx
MCUCR &= ~((1< Для того что бы внешние прерывания заработали их надо разрешить, установив в 1 соответствующие биты в регистре GICR
. Бит INT0
отвечает за разрешение/запрещение внешнего прерывания INT0
, а бит INT1
, соответственно за внешне прерывание INT1
. Так же необходимо что бы был выставлен флаг глобального разрешения прерываний. Пример кода разрешающего внешнее прерывание INT0 для avr atmega8:
//разрешаем внешнее прерывание INT0
GICR |= (1< В качестве примера приведу программу счетчика импульсов. Программа подсчитывает количество импульсов на входе INT0, и раз в секунду выводит результат подсчета в uart. #include В состав AVR микроконтроллеров входит большое число периферийных устройств (ADC, Timer/Counters, EXTI, Analog Comparator, EEPROM, USART, SPI, I2C и т.д.), каждое из которых может выполнять определенные действия над данными/сигналами и пр. информацией. Эти устройства встроены в микроконтроллер для повышения эффективности приложения и снижения затрат при разработке всевозможных устройств на базе AVR микроконтроллеров.
Процессор общается/управляет периферийными устройствами посредством регистров ввода/вывода (I/O Registers), которые располагаются в памяти данных (Data Memory), что позволяет использовать их как обычные переменные. У каждого устройства имеются свои регистры ввода/вывода.
Все регистры ввода/вывода (I/O Registers) можно поделить на три группы: регистры данных, регистры управления и регистры состояния.
При помощи регистров управления (Control Registers) реализуется настройка устройства для работы в том или ином режиме, с определенной частотой, точностью и т.д., а при помощи регистров данных (Data Registers) считывается результат работы данного устройства (аналого-цифровое преобразование, принятые данные, значение таймера/счетчика и т.д.). Казалось бы, ничего сложного здесь нет (вообще-то здесь и вправду ничего сложного нет:)), включил устройство, указал желаемый режим работы а потом только остается стричь купоны читать готовенькие данные и использовать их в вычислениях. Весь вопрос заключается в том "когда” читать эти самые данные (завершило устройство работу или все еще обрабатывает данные), ведь все периферийные устройства работают параллельно с ядром микроконтроллера, да еще и на разных частотах. Встает вопрос реализации общения и синхронизации между процессором и периферийным устройством.
Как вы уже наверное догадались, для реализации общения и синхронизации между устройством и процессором используются "регистры состояния” (Status Registers), в которых хранится текущее состояние работы того или иного устройства. Каждому состоянию, в котором может находиться устройство, соответствует "бит в регистре состояния” (флаг), текущее значение которого, "говорит” о текущем состоянии данного устройства или его отдельно взятой функции (работа завершена/не завершена, ошибка при обработке данных, регистр пуст и т.д.).
Механизм общения, между процессором и периферийным устройством, реализуется путем опрашивания флагов (flag polling), отвечающих за ту или иную функцию данного устройства. В зависимости от значения того или иного флага (состояние устройства), можно менять ход исполнения программы (ветвление). К примеру:
Проверка если определенный флаг установлен (произошло некое событие) :
if
(RegX &
(1
<<
Flag)
)
// если флаг в регистре RegX установлен
Ожидание завершения какого либо действия (событие) :
while(!(RegX & (1< Опрашивание флагов – занятие довольно ресурсоемкое, как в плане размера программы, так и в плане быстродействия программы. Поскольку общее число флагов в AVR микроконтроллерах довольно велико (преимущество), то реализация общения, между процессором и устройством, путем опроса флагов приводит к снижению КПД (быстродействие кода/размер кода) написанной вами программы, к тому же программа становится очень запутанной, что способствует появлению ошибок, которые трудно обнаружить даже при детальной отладке кода.
Для того чтобы повысить КПД программ для AVR микроконтроллеров, а также облегчить процесс создания и отладки данных программ, разработчики снабдили все периферийные устройства "источниками прерываний” (Interrupt sources
), у некоторых устройств может быть несколько источников прерывания.
При помощи источников прерываний реализуется механизм синхронизации
, между процессором и периферийным устройством, то есть процессор начнет прием данных, опрос флагов и др. действия над периферийным устройством только тогда, когда устройство будет к этому готово (сообщит о завершении обработке данных, ошибке при обработке данных, регистр пуст, и т.д.), путем генерации "запроса на обработку прерывания” (Interrupt request
), в зависимости от значения некоторого флага (состояние устройства / функции / события).
В литературе, очень часто, всю цепочку событий, начиная от "запроса на обработку прерывания” (IRQ) и до "процедуры обработки прерывания” (ISR), сокращенно называют – прерывание (Interrupt
).
Что такое прерывание?
Прерывание (Interrupt) – сигнал, сообщающий процессору о наступлении какого-либо события. При этом выполнение текущей последовательности команд приостанавливается и управление передаётся процедуре обработки прерывания, соответствующая данному событию, после чего исполнение кода продолжается ровно с того места где он был прерван (возвращение управления). (Wiki)
Процедура обработки прерывания
(Interrupt Service Routine) – это ни что иное как функция/подпрограмма, которую следует выполнить при возникновении определенного события. Будем использовать именно слово "процедура”, для того чтобы подчеркнуть ее отличие от всех остальных функций.
Главное отличие процедуры от простых функций состоит в том что вместо обычного "возврата из функции” (ассемблерная команда RET), следует использовать "возврат из прерывания” (ассемблерная команда RETI) – "RETurn from Interrupt
".
Свойства AVR прерываний:
Прерывание Reset, в отличие от всех остальных, нельзя запретить. Такие прерывания еще называют Non-maskable interrupts.
Таблица векторов прерываний, кроме вектора Reset, может быть перемещена в начало Boot раздела Flash памяти, установив бит IVSEL в регистре GICR. Вектор сброса также может быть перемещен в начало Boot раздела Flash памяти, путем программирования фьюз бита – BOOTRST.
Рис.1 Таблица векторов прерываний ATmega16
Прототип процедуры обработки прерывания
Чтобы объявить некоторую функцию в качестве процедуры обработки того или иного прерывания, необходимо следовать определенным правилам прототипирования, чтобы компилятор/компоновщик смогли правильно определить и связать нужное вам прерывание с процедурой ее обработки.
Во первых процедура обработки прерывания не может ничего принимать в качестве аргумента (void), а также не может ничего возвращать (void). Это связано с тем что все прерывания в AVR асинхронные, поэтому не известно в каком месте будет прервано исполнение программы, у кого принимать и кому возвращать значение, а также для минимизации времени входа и выхода из прерывания.
void
isr(void
)
Во вторых, перед прототипом функции следует указать что она является процедурой обработки прерывания. Как вам известно, в языке Си исполняется только тот код что используется в функции main. Поскольку процедура обработки прерывания в функции main нигде не используется, то для того чтобы компилятор не "выкинул” ее за ненадобностью, перед прототипом процедуры следует указать что эта функция является процедурой обработки прерывания.
Прототип процедуры обработки прерывания в среде AVR Studio
#include ISR(XXX_vect)
В AVR Studio (AVR GCC), каждая процедура обработки прерывания начинается с макроопределения ISR, после чего, в круглых скобках следует конструкция:
XXX_vect
где "XXX” это имя вектора прерывания. Все имена векторов, для определенного AVR микроконтроллера, можно найти в "таблице векторов прерываний” даташита данного микроконтроллера или в его заголовочном файле. К примеру, "таблица векторов прерываний” для микроконтроллера ATmega16 приведена на рис.1, где в колонке Source, приведены все имена векторов прерываний. Также имена можно посмотреть в заголовочном файле данного микроконтроллера (C:\Program Files\Atmel\AVR Tools\AVR Toolchain\avr\include\avr\iom16.h), см. рис.2. Все что нам надо сделать, это найти в таблице имя нужного нам вектора и к нему прибавить суффикс "_vect". Рис.2 Заголовочный файл ATmega16 для AVR Studio Для примера, напишем процедуру обработки прерывания по приему байта через USART (USART, Rx Complete) : ISR(USART_RXC_vect)
Кстати: перед тем как использовать любое прерывание в AVR Studio, следует включить в проект заголовочные файлы io.h и interrupt.h:
#include Более подробно об обработчиках прерываний в AVR Studio (AVR GCC) можно почитать в разделе Introduction to avr-libc’s interrupt handling.
Прототип процедуры обработки прерывания в среде ImageCraft
#pragma interrupt_handler В среде ImageCraft, прототип процедуры обработки прерывания выглядит следующим образом:
void
<
handler_name>
(void
)
где #pragma interrupt_handler где Рис.3 Заголовочный файл ATmega16 для ImageCraft IDE К примеру процедура обработки прерывания по приему байта через USART (USART, Rx Complete) в среде ImageCraft, будет выглядит так: #pragma interrupt_handler usart_rxc_isr: iv_USART_RXC
Более подробно о процедурах обработки прерывания в ImageCraft IDE можно найти в меню Help->Programming the AVR->Interrupt Handlers среды разработки. Иногда, если несколько обработчиков прерывания должны делать одно и то же, то для экономии памяти программ, можно направить несколько векторов прерывания на одну и ту же процедуру обработки прерывания.
В среде AVR Studio это выглядит так: ISR(INT0_vect)
Сначала идет процедура обработки прерывания для определенного вектора, в данном случае INT0. Все остальные процедуры могут ссылаться на любой обработчик прерывания при помощи конструкции: ISR(YYY_vect,
ISR_ALIASOF(XXX_vect)
)
;
где YYY это имя вектора прерывания который ссылается на ранее объявленный обработчик прерывания для вектора XXX. В среде ImageCraft это выглядит так: #pragma interrupt_handler #pragma interrupt_handler где векторы XXX и YYY ссылаются на один и тот же обработчик прерывания Как работает прерывание в AVR микроконтроллерах?
1. Предположим произошел "запрос на обработку прерывания
” (IRQ). Кстати: если одновременно произойдут несколько запросов на обработку прерывания, то первым будет обработано прерывание с самым высоким приоритетом, все остальные запросы будут обработаны по завершению высокоприоритетного прерывания.
2. Проверка.
Если бит активации данного прерывания установлен (Interrupt enable bit), а также I-бит (бит всеобщего разрешения прерываний) регистра состояния процессора (SREG) установлен, то процессор начинает подготовку процедуры обработки прерывания, при этом бит всеобщего разрешения прерываний (I-бит регистра SREG) сбрасывается, запрещая таким образом все остальные прерывания. Это происходит для того чтобы никакое другое событие не смогло прервать обработку текущего прерывания. Кстати: если в процедуре обработки прерывания установить I-бит в состояние лог. единицы, то любое активированное прерывание может в свою очередь прервать обработку текущего прерывания. Такие прерывания называются вложенные (Nested interrupts).
3. Подготовка
. Процессор завершает выполнение текущей ассемблерной команды, после чего помещает адрес следующей команды в стек (PC->STACK). Далее процессор проверяет какой источник прерывания подал "запрос на обработку прерывания” (IRQ), после чего воспользовавшись вектором данного источника (ссылка) из таблицы векторов (который железно закреплен за каждым источником прерывания), переходит в процедуру обработки прерывания (инструкция JMP). На все, про все процессор тратит минимум 4 такта! (в зависимости от момента появления запроса и длительность исполнения текущей инструкции). Это очень хорошее время реакции на IRQ, по сравнению с микроконтроллерами других производителей. Кстати: если IRQ произойдет, когда микроконтроллер находится в спящем режиме (sleep mode), время реакции на IRQ увеличивается еще на четыре такта, плюс время заложенное в фьюз битах SUT1 и SUT0 (Start-Up Time).
Системы
прерываний - важная часть любой управляющей
системы. От ее работы
во многом зависит то, насколько эффективно
микропроцессорная система выполняет
свои функции. Общая структура системы
пре рываний МК-51 представлена на рис.
14.3. Микроконтроллеры
семейства МК-51 обеспечивают поддержку
пяти источников прерываний: * двух внешних
прерываний, поступающих по входам INT0
и INT1 (линии порта Р3:Р3.2 и
Р3.3 соответственно); * двух
прерываний от таймеров/счетчиков Т/С0
и Т/С1; *
прерываниеотпоследовательногопорта. Запросы на
прерывание фиксируются в регистрах
специальных функций микроконтроллера:
флаги IE0, IE1,
TF0, TF1
запросов на прерывание от INT0,
INT1, T/C0
и T/C1
содержатся в регистре управления TCON
(табл. 14.4), а флаги RI и TI
запросов на прерывание от последовательного
порта - в регистре SCON
управления последовательным портом. Таблица 14.4.
Формат регистра TCON 0 IT0 Настройка
вида прерывания INT0 1 IE0 Флаг
запроса прерывания INT0 2 IT1 Настройка
вида прерывания INT1 3 IE1 Флаг
запроса прерывания INT1 4 TR0 Включение
в работу таймера/счетчика 0 5 TF0 Флаг
переполнения (запрос прерывания)таймера/счетчика
0 6 TR1 Включение
в работу таймера/счетчика 1 7 TF1 Флаг
переполнения (запрос прерывания)таймера/счетчика
1 Флаги TF0 и TF1 устанавливаются
аппаратно при переполнении соответствующего
таймера/счетчика (точнее, при
переходе T/Cx из состояния "все
единицы" в состояние "все нули"). Флаги IE0 и
IE1 устанавливаются аппаратно от внешних
прерываний IT0 и IT1 соответственно. Внешний
запрос может вызвать установку флага
либо при низком уровне сигнала на
соответствующем входе, либо при
переключении этого сигнала с высокого
уровня на низкий (с частотой, не превышающей
половины частоты внешней синхронизации
МК). Настройка
на тип запроса осуществляется программной
установкой бит IT0 и IT1 в регистре управления
TCON. Установка ITx = 0 настраивает систему
прерывания на запрос по низкому уровню
сигнала, ITx = 1 - запрос на прерывание по
спаду сигнала. Флаги TI и RI
устанавливаются аппаратно схемой
последовательного интерфейса после
окончания передачи или после окончания
приема соответственно. Все указанные
флаги запросов на прерывание программно
доступны для установки и сброса.
Программная установка флага запроса
на прерывание приводит к такой же реакции
микроконтроллера, что и аппаратная
установка того же самого флага. Флаги TF0
и TF1 сбрасываются аппаратно
при передаче управления программе
обработки соответствующего прерывания. Сброс флагов
IEx выполняется аппаратно
при обслуживании прерывания только в
том случае, если прерывание было настроено
на восприятие спада сигнала INTx.
Если прерывание было настроено на
восприятие уровня сигнала запроса, то
сброс флага IEx должна
выполнять программа обслуживания
прерывания, воздействуя на источник
прерывания для снятия им запроса. Флаги TI
и RI сбрасываются только
программным путем. Каждый вид
прерывания индивидуально разрешается
или запрещается установкой или сбросом
соответствующих разрядов регистра
разрешения прерывания IE.
Этот регистр содержит также и бит общего
запрещения всех прерываний. ФорматрегистраIE
приведен в табл. 14.5. Таблица
14.5. Назначение разрядов регистра IE
Позиция
в регистре
Мнемоника
бита
Функция
Запрет
прерывания от всех источников Не
используется Не
используется Запрет
прерывания от последовательного
порта
Запрет
прерывания от таймера/счетчика T/C1 Запрет
прерывания от внешнего источника INT1 Запрет
прерывания от таймера/счетчика T/C0 Запрет
прерывания от внешнего источника INT0 Каждому виду
прерывания может быть программно
присвоен один из двух возможных
приоритетов: 0 - низший или 1 - высший. Настройка
приоритетов осуществляется установкой
или сбросом соответствующего бита
регистра приоритетов прерываний IP.
Формат этого регистра приведен в табл.
14.6. При одновременном
поступлении запросов прерывания от
источников, имеющих различные приоритеты,
сначала обрабатывается запрос от более
приоритетного источника. В случае
одновременного поступления нескольких
запросов на прерывания с одинаковым
приоритетом порядок их обработки
определяется аппаратными
средствами микроконтроллера и не
может быть изменен программно. Этот
порядок соответствует последовательности
опроса флагов запросов прерываний,
имеющей следующий вид: IT0
-> TF0 -> IT1 -> TF1 -> (RI, TI) Таблица 14.6.
Назначение разрядов регистра IP Позиция в
регистре Мнемоника бита Функция 7 - Не
используется 6 - Не
используется 5 - Не
используется 4 PS Приоритет
прерыванияот последовательного порта 3 PT1 Приоритет
прерывания от таймера/счетчика T/C1 2 PX1 Приоритет
прерыванияот внешнего источника INT1 1 PT0 Приоритет
прерывания от таймера/счетчика T/C0 0 PX0 Приоритет
прерыванияот внешнего источника INT0 Аппаратно
реализуемый вызов обработчика
прерываний состоит из следующих
действий: * сохранение
значения программного счетчика в стеке; Точки входа
вобработчик прерывания для каждого
источника прерываний аппаратно
зафиксированы. Их значения приведены
в табл. 14.7. Таблица
14.7. Адреса точек входа в обработчики
прерываний
Источник
прерывания
Адреса
точек входа в обработчики прерываний
Внешнее
прерывания(ITO
) Таймер-счетчик(TFO) Внешнее
прерывания(IT1) Таймер-счетчик(TF1) Последовательный
порт(R1 или T1) По указанному
адресу должна размещаться первая
команда обработчика прерывания. Как
правило, такой командой является
команда безусловного перехода в
то место программы, где фактически
располагается обработчик. При переходе
на подпрограмму обработки прерывания
автоматически независимо от состояния
регистра IE запрещаются все прерывания,
которые имеют уровень приоритета, равный
уровню приоритета обслуживаемого
прерывания, - то есть вложенные прерывания
с равным уровнем приоритета запрещены.
Таким образом, низкоприоритетное
прерывание (имеющее "0" в соответствующем
разряде регистра IP) может прерываться
высокоприоритетным (имеющим "1" в
соответствующем разряде регистра IP),
но не низкоприоритетным. Обслуживание
высокоприоритетного прерывания не
может быть прервано другим источником. Возврат из
обработчика прерываний осуществляется
с помощью команды RETI, которая
восстанавливает из стека значение
программного счетчика PC, сохраненного
там в момент вызова обработчика
прерывания, и логику приоритетов
прерываний. Прерывание
(interrupt) – событие, требующие немедленной реакции со стороны процессора. Реакция состоит в том, что процессор прерывает обработку текущей программы (прерываемой программы
) и переходит к выполнению некоторой другой программы (прерывающей программы
), специально предназначенной для данного события. По завершении этой программы процессор возвращается к выполнению прерванной программы. Каждое событие, требующее прерывания, сопровождается сигналом прерывания
, оповещающим об этом вычислительную машину, и называемым запросом прерывания
. Состояние программы
представляет собой совокупность состояний всех запоминающих элементов в соответствующий момент времени (например, после выполнения последней команды). При возникновении прерывания микроконтроллер сохраняет в стеке содержимое счетчика команд и загружает в него адрес соответствующего вектора прерывания. Последней командой подпрограммы обработки прерывания должна быть команда, которая осуществляет возврат в основную программу и восстановление предварительно сохраненного счетчика команд. Во время выполнения обработчика прерывания некоторая информация может подвергнуться изменению. Поэтому при переходе к обработчику прерывания необходимо сохранить элементы, подвергающиеся изменению. Набор таких элементов представляет собой вектор состояния программы
. При этом другая информация о состоянии ячеек памяти не существенна или может быть восстановлена программным путем. Вектор начального состояния
содержит всю необходимую информацию для начального запуска программы. Во многих случаях вектор начального состояния содержит только один элемент – начальный адрес запускаемой программы. Вектор прерывания
является вектором начального состояния прерывающей программы (обработчика) и содержит всю необходимую информацию для перехода к обработчику, в том числе его начальный адрес. Каждому типу прерываний соответствует свой вектор прерывания, который инициализирует выполнение соответствующего обработчика. Обычно векторы прерывания хранятся в специально выделенных фиксированных ячейках памяти с короткими адресами, представляющих собой таблицу векторов прерываний
. Для перехода к соответствующей прерывающей программе процессор должен располагать вектором прерывания и адресом этого вектора. По этому адресу, как правило, находится команда безусловного перехода к подпрограмме обработки прерывания. Как правило, управление запоминанием и возвратом возложено на обработчик прерывания. В этом случае обработчик состоит из трех частей – подготовительной (пролог
) и заключительной (эпилог
), обеспечивающих переключение программ, и собственно прерывающей программы, выполняющей затребованные запросом операции. Время реакции определяется как временной интервал от момента поступления запроса прерывания до начала выполнения прерывающей программы. При наличии нескольких источников запросов должен быть установлен определенный порядок обслуживания поступающих запросов, называемый приоритетными соотношениями
или дисциплиной обслуживания
. Совокупность всех возможных типов прерывания процессора представляет собой систему прерывания
микроконтроллера. Дисциплина обслуживания определяет, какой из нескольких запросов, поступивших одновременно, подлежит обработке в первую очередь, и имеет ли право данный запрос прерывать тот или иной обработчик прерывания. Если запрос прерывания окажется не обслуженным к моменту прихода нового запроса от того же источника (того же приоритета), то возникает насыщение системы прерываний
. При этом часть запросов прерывания будет утрачена, что для нормальной работы микроконтроллера недопустимо. Характеристиками системы прерывания
являются: Маскирование прерываний
используется для сообщения микроконтроллеру о необходимости реагировать на каждый тип прерывания или игнорировать его. Маска
прерывания представляет двоичный код, разряды которого поставлены в соответствие источникам запроса прерываний. Единичный бит в двоичном коде сообщает микроконтроллеру о необходимости обработки прерываний такого типа. Нулевой бит напротив не позволяет микроконтроллеру переходить к обработке прерываний указанного типа.
Скачиваем datasheet (ссылка есть при создании проекта) и находим в разделе прерывания (interrupt) такую таблицу:
Установим состояние генерации прерывания при каждом "логическом изменении на INT1".
Программа целиком: Принцип работы внешних прерываний в AVR
0 — это отсутствие напряжения на входе
1 — наличие на входе напряжения, которое равно напряжению питания микроконтроллера.Внешние прерывания по уровню
При работе с прерываниями по уровню надо помнить, что пока на входе INT соответствующий уровень, прерывание будет возникать постоянно. Т.е. если возникло прерывание, например по низкому уровню и программа его обработала, но если при выходе из обработчика прерывания на входе остается низкий уровень, то прерывание сработает еще раз, и опять будет вызван обработчик прерывания, и так будет продолжаться до тех пор пока на входе не появится высокий уровень. Что бы этого не происходило нужно в обработчике запрещать данный вид прерываний, или перенастраивать его на другой уровень.Внешние прерывание по фронту
Так же возможно настроить прерывание что бы оно реагировало на любое изменение на входе INT т.е. оно будет возникать и по переднему и по заднему фронту. Настройка внешних прерываний в AVR
//сбрасываем все биты ISCxx
MCUCR &
amp;=
~( (1
&
lt;&
lt;
ISC11)
|
(1
&
lt;&
lt;
ISC10)
|
(1
&
lt;&
lt;
ISC01)
|
(1
&
lt;&
lt;
ISC00)
)
MCUCR |=
(1
&
lt;&
lt;
ISC01)
|
(1
&
lt;&
lt;
ISC00)
;
Разрешение внешних прерываний в avr atmega
Пример использования внешних прерываний в AVR atmega
#include
{
// делай что-то
}
{
}
{
// Тело обработчика прерывания
}
#include
void
<
handler_name>
(void
)
{
// Тело обработчика прерывания
}
void
usart_rxc_isr(void
)
{
// Тело обработчика прерывания
}
{
// Do something
}
ISR(INT1_vect,
ISR_ALIASOF(INT0_vect)
)
;
void
<
handler_name>
(void
)
{
// Тело обработчика прерывания
}
#pragma interrupt_handler
void
<
handler_name>
(void
)
{
// Тело обработчика прерывания
}
t p
– время реакции системы на прерывание;
t з
– время запоминания состояния прерываемой программы;
t ппр
– время собственно прерывающей программы;
t в
– время восстановления состояния прерванной программы
В случае если во время обработки прерывания поступает запрос на прерывание с более высоким уровнем приоритета, управление передается обработчику прерывания более высокого приоритета, при этом работа обработчика прерывания с более низким уровнем приоритета приостанавливается. Возникает вложенность прерываний
. Максимальное число программ, которые могут приостанавливать друг друга называется глубиной прерываний
.
Как правило, кроме маскирования прерываний, существует также бит глобального разрешения прерываний, нулевое значение которого отключает все обработчики прерываний (кроме аппаратного сброса и перехода к началу исполняемой программы).
Кроме двоичного кода маски прерываний существует также двоичный код флагов прерываний
, который позволяет обработчику прерываний установить источник возникновения прерывания в случае если источников с указанным запросом в микроконтроллере несколько.