Порты ввода-вывода, прерывания и контроллер прерываний NVIC … ↩
mod. Четверг, 15 октября 2026 22:55 . См. 3
BeeFC · Урок S5 из 33 · Уровень «Старт»
Чем прерывание отличается от опроса, как настроить внешнее прерывание по фронту сигнала, как распределить приоритеты между обработчиками и как отфильтровать дребезг контактов кнопки. В конце урока задержка обработки прерывания измеряется логическим анализатором.
В этом уроке в BeeFC появляется обработчик линии готовности данных гироскопа. Сам гироскоп будет настроен в уроке P1, но прерывание от него уже проверяется в программной имитации.
Содержание
1. Цели урока
Продолжительность урока — три часа: один час теории и два часа практики. После урока слушатель:
- выбирает между опросом и прерыванием для конкретного сигнала;
- настраивает внешнее прерывание по фронту на любом выводе и задаёт его приоритет;
- безопасно передаёт данные из обработчика прерывания в основную программу;
- реализует фильтр дребезга контактов как конечный автомат и проверяет его модульными тестами;
- измеряет задержку обработки прерывания логическим анализатором.
2. Термины и сокращения
| Термин | Определение |
|---|---|
| прерывание | приостановка основной программы для выполнения обработчика по событию |
| обработчик прерывания | функция, которую ядро вызывает при возникновении события |
| контроллер вложенных векторных прерываний (NVIC) | блок ядра Cortex-M, который разрешает прерывания и выбирает порядок их обслуживания |
| контроллер внешних прерываний (EXTI) | блок STM32, который формирует прерывание по фронту сигнала на выводе |
| линия готовности данных (DRDY) | выход датчика, сообщающий о появлении нового измерения |
| дребезг контактов | многократное замыкание и размыкание механического контакта в момент переключения |
| конечный автомат | модель, в которой поведение определяется текущим состоянием и входным событием |
| критическая секция | участок кода, на время выполнения которого прерывания запрещены |
3. Опрос и прерывания
Программа может узнать о событии двумя способами. При опросе она периодически читает состояние вывода или флага. При прерывании ядро само приостанавливает текущий код и вызывает обработчик.
| Признак | Опрос | Прерывание |
|---|---|---|
| задержка реакции | до одного периода опроса | десятки наносекунд |
| нагрузка на процессор | постоянная, даже без событий | только при событии |
| поведение при дребезге | фильтруется естественным образом | каждое переключение вызывает обработчик |
| пример в BeeFC | кнопка, состояние батареи | линия готовности данных гироскопа, приём байта |
Ядро Cortex-M4 начинает выполнять обработчик через 12 тактов после события, то есть примерно через 71 нс на частоте 168 МГц. Такты ожидания флеш-памяти и выполняющиеся в этот момент обработчики с более высоким приоритетом увеличивают задержку.
↑ К оглавлению4. Контроллер внешних прерываний
Контроллер EXTI STM32F405 имеет шестнадцать линий для выводов: линия с номером n подключается к выводу с тем же номером в одном из портов. Линия EXTI4 может обслуживать PA4, PB4 или PC4, но только один из них. Выбор порта для линии задаётся в регистрах SYSCFG_EXTICR.
| Линии | Обработчик в таблице векторов |
|---|---|
| EXTI0–EXTI4 | отдельный обработчик для каждой линии |
| EXTI5–EXTI9 | общий обработчик EXTI9_5_IRQHandler |
| EXTI10–EXTI15 | общий обработчик EXTI15_10_IRQHandler |
Настройка прерывания по фронту
Файл hal/stm32f4/exti_stm32.c
Флаг запроса в регистре EXTI->PR сбрасывается записью единицы. Если его не сбросить, ядро вызовет обработчик снова сразу после выхода из него, и основная программа перестанет выполняться.
5. Приоритеты прерываний
В STM32F405 контроллер NVIC использует четыре бита приоритета, то есть шестнадцать уровней. Уровень 0 — самый высокий. Обработчик с более высоким приоритетом прерывает обработчик с более низким. Функция NVIC_SetPriority из CMSIS сама сдвигает значение в старшие биты регистра.
| Источник | Приоритет в BeeFC | Обоснование |
|---|---|---|
| линия готовности данных гироскопа | 1 | от неё зависит частота цикла управления |
| таймер выходов на двигатели | 2 | урок S8 |
| приём по последовательному порту | 5 | байт можно обработать в течение нескольких микросекунд |
| системный таймер SysTick | 15 | служебные задачи |

Общие данные обработчика и основной программы
Переменная, которую изменяет обработчик, объявляется с квалификатором volatile. Чтение и запись выровненного 32-битного значения на Cortex-M4 выполняются одной инструкцией и не могут быть прерваны. Для значений типа uint64_t и для структур это не так, и их чтение выполняется в критической секции.
Сохранение и восстановление регистра PRIMASK вместо безусловного разрешения прерываний позволяет вызывать такой код и там, где прерывания уже запрещены.
6. Дребезг контактов
При нажатии кнопки контакты замыкаются и размыкаются несколько раз в течение нескольких миллисекунд. Если повесить на кнопку внешнее прерывание, одно нажатие вызовет несколько обработчиков. Поэтому кнопка в BeeFC опрашивается задачей планировщика, а решение принимает конечный автомат.
Файл core/debounce.h
Файл core/debounce.c
Автомат меняет состояние только после того, как новое значение повторилось заданное число опросов подряд. При опросе с частотой 1 кГц и пороге в десять опросов изменение подтверждается через 10 мс.
Файл tests/unit/test_level1.c
7. Замер задержки прерывания
Задержка измеряется логическим анализатором с двумя каналами. Первый канал подключается к выводу кнопки, второй — к свободному выводу, который обработчик переключает первой же инструкцией. Время между фронтом на первом канале и фронтом на втором — задержка обработки прерывания вместе с временем записи в порт.
На том же снимке анализатора виден дребезг: после нажатия на первом канале появляется серия коротких импульсов, и каждый из них вызывает обработчик.
8. Практика
Задание S5.1. Фильтр дребезга
Продолжительность — 30 минут, выполняется на компьютере.
Реализовать модуль core/debounce и добавить тест на отпускание кнопки с дребезгом.
Критерий автоматической проверки: тесты test_debounce_* и скрытые тесты пройдены; скрытые тесты подают на вход записи дребезга реальных кнопок.
Задание S5.2. Счётчик прерываний от кнопки
Продолжительность — 40 минут.
Подключить кнопку между свободным выводом и общим проводом, включить подтягивающий резистор и настроить внешнее прерывание по спаду. Обработчик увеличивает счётчик. Выполнить двадцать нажатий и записать в отчёт docs/s5_report.md, сколько раз был вызван обработчик.
Задание S5.3. Замер задержки
Продолжительность — 30 минут, требуется логический анализатор.
Измерить задержку между фронтом на выводе кнопки и переключением отладочного вывода в обработчике. Приложить к отчёту снимок экрана анализатора и сравнить результат с расчётным значением.
Задание S5.4. Линия готовности данных гироскопа
Продолжительность — 20 минут.
Настроить прерывание по фронту на выводе линии готовности данных своей платы функцией gyro_drdy_exti_init. Обработчик сохраняет значение счётчика тактов DWT и увеличивает счётчик прерываний.
Критерий автоматической проверки: в модели Renode на вывод подаётся сто фронтов, после чего значение g_gyro_drdy_count равно 100.
9. Как это сделано в больших прошивках
| Прошивка | Версия | Файл в исходном коде |
|---|---|---|
| Betaflight | 2026.6.2 | src/main/drivers/exti.h, src/platform/STM32/exti.c |
| INAV | 9.1.0 | src/main/drivers/exti.c |
| ArduPilot | Copter-4.7.2 | libraries/AP_HAL_ChibiOS/GPIO.cpp |
| PX4 | v1.17.0 | src/drivers/imu/invensense/icm42688p/ICM42688P.cpp |
- В Betaflight драйвер датчика регистрирует обработчик функциями
EXTIHandlerInitиEXTIConfig, объявленными вexti.h. Реализация вsrc/platform/STM32/exti.cсама обслуживает общие обработчики линий 5–9 и 10–15 и вызывает нужную функцию драйвера по номеру линии. - В INAV устройство модуля
exti.cунаследовано от общего предка и похоже на Betaflight. - В ArduPilot метод
attach_interruptв файлеGPIO.cppподключает обработчик через события линий ввода-вывода операционной системы ChibiOS. - Драйвер
ICM42688P.cppв PX4 по прерыванию готовности данных запускает чтение очереди измерений датчика. Одновременно драйвер планирует резервный запуск через удвоенный интервал. Если прерывание не пришло, срабатывает резервный запуск: драйвер увеличивает счётчик «DRDY missed» и читает количество накопленных измерений из датчика напрямую. Так пропущенное прерывание не останавливает цикл управления.
10. Проверьте себя
- Почему кнопку не подключают к внешнему прерыванию напрямую?
- Можно ли одновременно использовать внешние прерывания на выводах PA4 и PC4?
- Что произойдёт, если в обработчике не сбросить флаг в регистре
EXTI->PR? - Когда для чтения общей переменной нужна критическая секция?
- Что делает драйвер ICM-42688-P в PX4, если прерывание готовности данных не пришло?
11. Чек-лист самопроверки
12. Источники
- Справочное руководство RM0090, раздел 12, контроллер прерываний и событий.
- Руководство программиста PM0214, разделы о контроллере NVIC и регистре PRIMASK.
- Описание платы MAMBAF405_2022B для Betaflight.
- Драйвер ICM-42688-P в PX4.
13. Что дальше
- Следующий урок: S6. Системное время и планировщик задач.
- Полный перечень уроков приведён в статье «Курс BeeFC: содержание уровня „Старт“».
Проверено: 13.10.2026
↑ К оглавлению- мод. : Четверг, 15 октября 2026