6.0 KiB
Универсальный драйвер тактовых кнопок DS_Button
Легковесная библиотека на Си для оцифровки пользовательского ввода через тактовые кнопки. Драйвер реализует накопительный интегральный алгоритм антидребезга, что гарантирует защиту от ложных срабатываний и дребезга контактов без использования блокирующих задержек типа HAL_Delay.
📌 Особенности реализации
- Интегральный фильтр антидребезга: Состояние кнопки определяется поведением программного «конденсатора» (счетчик
Storageот 0 до 10). Изменение состояния фиксируется только после серии стабильных чтений пина. - Три уровня фиксации времени: Встроенная поддержка мгновенного клика, длинного удержания (>1000 мс) и сверхдлинного удержания (>5000 мс).
- Событийные фронты (Edges): Функции
RisingEdgeиFallingEdgeработают как триггеры — они возвращают истину строго один раз в момент нажатия или отпускания кнопки, автоматически сбрасывая свой флаг.
🔌 Конфигурация периферии в STM32CubeMX
Драйвер ориентирован на работу с кнопками, замыкающимися на высокий уровень (VCC).
- Выберите пин микроконтроллера и переведите его в режим
GPIO_Input. - В окне параметров пина в поле Pull-up/Pull-down обязательно выберите Pull-down (внутренняя подтяжка к земле).
- Физическую кнопку на плате подключайте между выбранным пином STM32 и шиной питания 3.3V.
💻 Пример использования в main.c
Для корректной работы интегрального фильтра функция обновления должна вызываться циклически с фиксированным периодом (рекомендуется 10 мс).
#include "DS_Button.h"
DS_Button user_button;
int main(void) {
// ... Автоматическая инициализация HAL, GPIO ...
/* 1. Первичная привязка аппаратного пина к структуре */
DS_ButtonInit(&user_button, GPIOA, GPIO_PIN_0);
while (1) {
/* 2. Опрос состояния кнопки. Встроенный фильтр
выполняет проверку каждые 10 мс внутри функции */
DS_ButtonUpdate(&user_button);
/* 3. Обработка фронтов (вызывается строго ОДИН раз за нажатие/отпускание) */
if (DS_ButtonRisingEdge(&user_button)) {
// Кнопку физически нажали (момент замыкания контактов)
}
if (DS_ButtonFalingEdge(&user_button)) {
// Кнопку физически отпустили (момент размыкания контактов)
}
/* 4. Обработка удержаний */
if (DS_ButtonPressedLong(&user_button)) {
// Кнопку удерживают больше 1 секунды.
// Функция вернет true, сбросит флаг и сгенерирует повтор через 500 мс
}
if (DS_ButtonPressedLongLong(&user_button)) {
// Кнопку удерживают больше 5 секунд.
}
// Небольшая задержка основного цикла, чтобы Update работал корректно
HAL_Delay(10);
}
}
📋 Справочник API функций
void DS_ButtonInit(DS_Button* Button, GPIO_TypeDef *Port, uint16_t Pin)
Сбрасывает все внутренние таймеры, устанавливает начальный заряд интегратора Storage в значение 5 и привязывает GPIO порт и пин.
void DS_ButtonUpdate(DS_Button *Button)
Конечный автомат обработки дребезга и удержаний. Опрашивает физический пин. Содержит встроенную отсечку времени if ((CurrentTick - Button->PrevTick) < 10) return;, благодаря чему стабильно работает при вызове с любой частотой чаще 10 мс.
bool DS_ButtonPressed(DS_Button *Button)
Возвращает текущее отфильтрованное состояние кнопки. true — кнопка зажата в данный момент.
bool DS_ButtonRisingEdge(DS_Button *Button) / bool DS_ButtonFalingEdge(DS_Button *Button)
Фиксируют момент нажатия или отпускания кнопки соответственно. Возвращают true один раз за событие.
bool DS_ButtonPressedLong(DS_Button *Button) / bool DS_ButtonPressedLongLong(DS_Button *Button)
Фиксируют программное удержание клавиши на 1 и 5 секунд соответственно. Автоматически сдвигают временную точку вперед на 500 мс для поддержки автоповтора события при непрерывном удержании.