gpio_button — кнопка по прерыванию и светодиод
Короткое нажатие кнопки BOOT/USER переключает светодиод D2 (PG3). Кнопка обрабатывается по прерыванию с подавлением дребезга контактов.
Включить
Заголовок раздела «Включить»cmake --preset Release -DH723_RECIPES="gpio_button"Вывод на плате
Заголовок раздела «Вывод на плате»gpio_button: started, press BOOT to toggle LEDgpio_button: press 1 (196 ms), LED ongpio_button: press 2 (202 ms), LED offgpio_button: press 3 (181 ms), LED ongpio_button: press 4 (152 ms), LED offПодавление дребезга: если прерывание пришло, а уровень на выводе не изменился, в лог попадает
gpio_button: bounce, ignored, и светодиод не переключается.
Как это работает
Заголовок раздела «Как это работает»- Схема. Кнопка замыкает PC13 на 3,3 В, резистор 10 кОм на плате тянет вывод к земле: нажата — 1, отпущена — 0. Та же кнопка подаёт 1 на BOOT0, поэтому если держать её во время сброса, стартует системный загрузчик (DFU), а не прошивка.
- Долгое нажатие занято. Прошивка (
app/app.c) сбрасывает плату, если кнопку держать ~1 с. Рецепт считает только нажатия корочеSHORT_PRESS_MS(800 мс). - Прерывание по обоим фронтам. PC13 переводится в режим
GPIO_MODE_IT_RISING_FALLING— линия EXTI13. Её обработчикEXTI15_10_IRQHandlerиHAL_GPIO_EXTI_Callbackживут вapp/exti.cи отдают прерывание приложению черезappGpioExti(pin); что приложение не забрало, уходит в Lua (pio.attachInterrupt), если прошивка собрана с ним. Рецепт переопределяетappGpioExtiи забирает PC13 себе. - Дребезг. Контакты кнопки при нажатии несколько миллисекунд замыкаются и размыкаются, давая
пачку прерываний. Прерывание только будит задачу (
vTaskNotifyGiveFromISR): ждать и печатать в нём нельзя, пока оно идёт, стоит вся система. Задача ждёт 20 мс, сбрасывает накопившиеся уведомления и читает вывод. Если уровень не изменился — это был дребезг. - Приоритет прерывания 6 — из него можно звать
...FromISR(см. правила в общем README). - Светодиод. Обычно им мигает idle-задача (
appLedHeartbeatвapp/app.c); рецепт выключает мигание и управляет PG3 сам. Состояние хранится в переменной, а не читается с вывода:HAL_GPIO_ReadPinсразу после записи в выход может вернуть старое значение.
Переделать под себя
Заголовок раздела «Переделать под себя»- Внешняя кнопка: любой свободный вывод (
docs/board.md), кнопка на GND и подтяжкаGPIO_PULLUP— тогда нажата = 0. МеняютсяBUTTON_PORT,BUTTON_PINи проверка уровня. Для выводов 0–4 у линий EXTI свои обработчики, для 5–9 —EXTI9_5_IRQHandler, тоже вapp/exti.c. appGpioExtiпереопределяется только в одном модуле, поэтому при нескольких кнопках все выводы обрабатываются в этой одной функции.- Двойное нажатие, удержание и т. п. — в
buttonTaskесть время нажатия (ms), этого достаточно.
Исходники рецепта: recipes/gpio_button
