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

6.0 KiB

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

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