Прерывание по фронту и по уровню
Внешнее прерывание можно настроить на событие — перепад сигнала — или на состояние — низкий уровень. От этого зависит, сколько раз сработает обработчик, что будет с коротким импульсом и как микроконтроллер проснётся из глубокого сна. Разбираем на AVR и STM32.
Обновлено Редакция GAW
Внешнее прерывание запускается одним из двух способов.
Прерывание по фронту (edge-triggered) срабатывает на перепад сигнала: переход из нуля в единицу (фронт), из единицы в ноль (спад) или любой из них. Один перепад — один запрос, сколько бы ни длился новый уровень.
Прерывание по уровню (level-triggered) срабатывает, пока на входе держится заданный уровень, обычно низкий. Если уровень не снят, запрос повторяется сразу после выхода из обработчика.
AVR: регистр EICRA
У ATmega328P прерывания INT0 и INT1 настраиваются битами ISC в регистре EICRA:
| ISCx1:ISCx0 | Событие |
|---|---|
| 00 | низкий уровень |
| 01 | любое изменение |
| 10 | спад |
| 11 | фронт |
Microchip уточняет детали: при выборе фронта гарантированно ловятся импульсы длиннее одного такта, а низкий уровень должен держаться до конца выполняемой инструкции. Прерывания по уровню и по изменению вывода обнаруживаются асинхронно и могут будить микроконтроллер из Power-down, когда такты остановлены. У ATmega328P асинхронно ловится и фронт на INT0/INT1, но у более старых кристаллов это не так: в даташите ATmega8 распознавание фронтов на INT0 и INT1 требует тактового сигнала ввода-вывода, и из Power-down их будит только низкий уровень. Поэтому для пробуждения проверяйте даташит конкретного кристалла. Пример настройки — в уроке о таймерах и прерываниях.
STM32: только фронты
Контроллер EXTI в STM32F4 RM0090 описывает как набор детекторов фронтов: каждая линия реагирует на фронт, спад или оба. Прерывания по уровню у EXTI нет; запрос фиксируется в регистре EXTI_PR, и программа сбрасывает его записью единицы.
Что выбрать
- Сигнал готовности датчика с коротким импульсом — по фронту. Если датчик держит уровень до чтения (режим удержания у MPU-6050, см. сигнал готовности данных), подходят оба варианта, но по уровню надо обязательно сбросить источник в обработчике.
- Общая линия с открытым стоком от нескольких источников — по уровню: пока хоть один источник держит запрос, прерывание не потеряется. По фронту второй запрос, пришедший во время первого, не даст нового перепада.
- Кнопки — по фронту, но с подавлением дребезга, иначе один нажим даст серию прерываний.
Частые вопросы
Чем прерывание по уровню опаснее прерывания по фронту?
Тем, что оно повторяется. Пока на выводе INT0 ATmega328P держится низкий уровень, прерывание срабатывает снова и снова, сразу после выхода из обработчика. Если источник не снимает сигнал, программа застревает в обработчике. Поэтому в обработчике либо снимают причину — читают регистр датчика, — либо запрещают прерывание до следующего события.
Почему прерывание по фронту пропускает короткие импульсы?
Потому что вывод опрашивается тактовым сигналом. Microchip для ATmega328P гарантирует прерывание по фронту только для импульсов длиннее одного периода такта. Импульс короче может быть не замечен. Если источник выдаёт очень короткие импульсы, их удлиняют или используют вход, который фиксирует событие асинхронно.
Как разбудить AVR из Power-down внешним сигналом?
Надёжнее всего — прерыванием по низкому уровню на INT0 или INT1 или прерыванием по изменению вывода, если оно есть у кристалла: они обнаруживаются асинхронно, без тактов. Фронт на INT0/INT1 будит ATmega328P, но не старые кристаллы вроде ATmega8, где для фронтов нужен такт ввода-вывода. Уровень при этом должен держаться, пока микроконтроллер не закончит пробуждение: иначе, предупреждает Microchip, он проснётся, но прерывание не будет сгенерировано.
Источники
- Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet, DS40002061B (2020) — разд. 13: внешние прерывания INT0 и INT1 запускаются спадом, фронтом или низким уровнем (регистр EICRA); при настройке на уровень прерывание срабатывает, пока вывод удерживается в нуле; прерывания по низкому уровню и по фронту INT обнаруживаются асинхронно и будят из сна глубже Idle; разд. 13.2.1: значение на выводе опрашивается перед обнаружением фронтов, при выборе фронта или изменения импульсы длиннее одного такта гарантированно дают прерывание, короче — нет; при выборе низкого уровня он должен держаться до конца выполняемой инструкции; табл. 13-1: ISC11:ISC10 = 00 низкий уровень, 01 любое изменение, 10 спад, 11 фронт; разд. 10.5: при пробуждении из Power-down прерыванием по уровню уровень должен держаться до конца пробуждения, иначе микроконтроллер проснётся, но прерывания не будет
- Atmel. ATmega8(L) Datasheet (Rev. 2486AA–AVR–02/2013) — External Interrupts: прерывания INT0 и INT1 — по спаду, фронту или низкому уровню (регистр MCUCR); распознавание фронтов на INT0 и INT1 требует тактового сигнала ввода-вывода, а низкий уровень обнаруживается асинхронно и может будить микроконтроллер из режимов сна глубже Idle; такт ввода-вывода остановлен во всех режимах сна, кроме Idle; при пробуждении из Power-down уровень нужно удерживать некоторое время
- STMicroelectronics. RM0090 Reference manual: STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439, Rev 21 (June 2024) — разд. 12.2: контроллер EXTI состоит из до 23 детекторов фронтов; каждая линия настраивается как прерывание или событие по фронту, спаду или обоим (EXTI_RTSR, EXTI_FTSR); регистр EXTI_PR хранит запросы; разд. 12.3.6: бит ожидания сбрасывается записью 1
Нашли ошибку?
Смотрите также
- ПрерываниеЗапрос периферии, вектор и обработчик прерывания
- EXTI — внешние прерывания STM32Линии, которые превращают фронт на выводе в прерывание или событие
- Прерывание по изменению вывода (PCINT)Прерывание AVR при любом изменении уровня на выводе
- Дребезг контактовСерия переключений вместо одного при нажатии кнопки
- Сигнал готовности данных (DRDY)Выход или флаг, сообщающий, что новый результат измерения можно читать
- Таймеры и прерыванияCTC на Timer0 и Timer1, ISR, sei, volatile, ATOMIC_BLOCK
- Прерывания STM32Векторы и IRQn, приоритеты и HAL, EXTI и общие векторы, флаги, события, примеры