# Универсальный драйвер тактовых кнопок DS_Button Легковесная библиотека на Си для оцифровки пользовательского ввода через тактовые кнопки. Драйвер реализует **накопительный интегральный алгоритм антидребезга**, что гарантирует защиту от ложных срабатываний и дребезга контактов без использования блокирующих задержек типа `HAL_Delay`. ## 📌 Особенности реализации * **Интегральный фильтр антидребезга**: Состояние кнопки определяется поведением программного «конденсатора» (счетчик `Storage` от 0 до 10). Изменение состояния фиксируется только после серии стабильных чтений пина. * **Три уровня фиксации времени**: Встроенная поддержка мгновенного клика, длинного удержания (**>1000 мс**) и сверхдлинного удержания (**>5000 мс**). * **Событийные фронты (Edges)**: Функции `RisingEdge` и `FallingEdge` работают как триггеры — они возвращают истину строго один раз в момент нажатия или отпускания кнопки, автоматически сбрасывая свой флаг. --- ## 🔌 Конфигурация периферии в STM32CubeMX Драйвер ориентирован на работу с кнопками, замыкающимися на высокий уровень (**VCC**). 1. Выберите пин микроконтроллера и переведите его в режим `GPIO_Input`. 2. В окне параметров пина в поле **Pull-up/Pull-down** обязательно выберите **Pull-down** (внутренняя подтяжка к земле). 3. Физическую кнопку на плате подключайте между выбранным пином STM32 и шиной питания **3.3V**. --- ## 💻 Пример использования в `main.c` Для корректной работы интегрального фильтра функция обновления должна вызываться циклически с фиксированным периодом (рекомендуется **10 мс**). ```c #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 мс для поддержки автоповтора события при непрерывном удержании.