Files
DS_Library_Docs/docs/DS_Button.md
T
2026-06-27 00:39:04 +03:00

85 lines
6.0 KiB
Markdown

# Универсальный драйвер тактовых кнопок 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 мс для поддержки автоповтора события при непрерывном удержании.