仓库地址:https://github.com/0x1abin/MultiButton

一个高效、灵活的多按键状态机库,支持多种按键事件检测。

功能特性

  • ✅ 多种按键事件: 按下、抬起、单击、双击、长按开始、长按保持、重复按下

  • ✅ 硬件去抖: 内置数字滤波,消除按键抖动

  • ✅ 状态机驱动: 清晰的状态转换逻辑,可靠性高

  • ✅ 多按键支持: 支持无限数量的按键实例

  • ✅ 回调机制: 灵活的事件回调函数注册

  • ✅ 内存优化: 紧凑的数据结构,低内存占用

  • ✅ 配置灵活: 可自定义时间参数和功能选项

  • ✅ 参数验证: 完善的错误检查和边界条件处理

快速开始

1.包含头文件

#include "multi_button.h"

2.定义按键实例

static Button btn1;

3.实现 GPIO 读取函数

/**
 * @brief  按键 GPIO 采样函数
 * @param  button_id  按键编号
 * @return uint8_t    当前按键电平 (0/1)
 */
uint8_t read_pin_level(uint8_t button_id)
{
  switch (button_id)
  {
  case 1: // KEY1
    return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);

  default:
    return 0;
  }
}

4.初始化按键

  /* 1. 初始化按键对象
       参数:
       - &btn1:             按键对象
       - read_pin_level:   用户提供的 GPIO 读取函数
       - 1:                 按键有效电平(1=按下)
       - 1:                 按键编号(回调中识别用)
  */
  button_init(&btn1, read_pin_level, 1, 1);

5.注册事件回调

/**
 * @brief 单击回调
 */
void btn1_single_click_cb(Button *btn)
{
  if (btn->button_id == 1)
  {
    key1_state = KEY1_STATE_SINGLE_CLICK; // 单击
  }
}

button_attach(&btn1, BTN_SINGLE_CLICK, btn1_single_click_cb);

6.启动按键处理

button_start(&btn1);

7.定时调用处理函数

void HAL_SYSTICK_Callback(void)
{
  static uint8_t tick_5ms = 0;

  if (++tick_5ms >= 5)
  {
    tick_5ms = 0;
    button_ticks(); // 每 5ms 扫描一次
  }
}

8.完整示例

static Button btn1;

typedef enum
{
  KEY1_STATE_IDLE = 0,     // 无操作
  KEY1_STATE_SINGLE_CLICK, // 单击确认
  KEY1_STATE_DOUBLE_CLICK, // 双击确认
  KEY1_STATE_LONG_PRESS    // 长按触发(开始长按)
} Key1State;

Key1State key1_state = KEY1_STATE_IDLE;

/**
 * @brief  按键 GPIO 采样函数(交给按键库调用)
 * @param  button_id  按键编号(允许多键)
 * @return uint8_t    当前按键电平 (0/1)
 */
uint8_t read_pin_level(uint8_t button_id)
{
  switch (button_id)
  {
  case 1: // KEY1
    return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);

  default:
    return 0;
  }
}

/**
 * @brief 单击回调
 */
void btn1_single_click_cb(Button *btn)
{
  if (btn->button_id == 1)
  {
    key1_state = KEY1_STATE_SINGLE_CLICK; // 单击
  }
}

/**
 * @brief 双击回调
 */
void btn1_double_click_cb(Button *btn)
{
  if (btn->button_id == 1)
  {
    key1_state = KEY1_STATE_DOUBLE_CLICK; // 双击
  }
}

/**
 * @brief 长按开始回调
 */
void btn1_long_press_start_cb(Button *btn)
{
  if (btn->button_id == 1)
  {
    key1_state = KEY1_STATE_LONG_PRESS; // 长按
  }
}

/**
 * @brief 初始化按键 1:绑定 GPIO、配置有效电平、注册事件回调
 */
void my_button_library_init(void)
{
  /* 1. 初始化按键对象
       参数:
       - &btn1:             按键对象
       - read_pin_level:   用户提供的 GPIO 读取函数
       - 1:                 按键有效电平(1=按下)
       - 1:                 按键编号(回调中识别用)
  */
  button_init(&btn1, read_pin_level, 1, 1);

  /* 2. 注册回调(按键库内部会自动触发) */
  button_attach(&btn1, BTN_SINGLE_CLICK, btn1_single_click_cb);
  button_attach(&btn1, BTN_DOUBLE_CLICK, btn1_double_click_cb);
  button_attach(&btn1, BTN_LONG_PRESS_START, btn1_long_press_start_cb);

  /* 3. 启动按键(加入内部链表 / 状态机) */
  button_start(&btn1);
}

void HAL_SYSTICK_Callback(void)
{
  static uint8_t tick_5ms = 0;

  if (++tick_5ms >= 5)
  {
    tick_5ms = 0;
    button_ticks(); // 每 5ms 扫描一次
  }
}

配置选项

在 multi_button.h 中可以配置以下参数:

// 配置常量 - 可根据您的需求修改
#define TICKS_INTERVAL 5                   // ms - 定时器中断间隔
#define DEBOUNCE_TICKS 3                   // MAX 7 (0 ~ 7) - 消抖滤波深度
#define SHORT_TICKS (300 / TICKS_INTERVAL) // 短按阈值
#define LONG_TICKS (1000 / TICKS_INTERVAL) // 长按阈值
#define PRESS_REPEAT_MAX_NUM 15            // 最大连击计数值

使用注意事项

  1. 定时器设置: 必须配置与TICKS_INTERVAL宏相同的定时器中断,在中断中调用 button_ticks()

  2. GPIO 配置: 按键引脚需配置为输入模式,根据需要启用上拉或下拉电阻

  3. 回调函数: 回调函数应尽量简短,避免长时间阻塞

  4. 内存管理: 按键实例可以是全局变量或动态分配

  5. 多按键: 每个物理按键需要独立的 Button 实例和唯一的 button_id

状态机说明

[IDLE] --按下--> [PRESS] --长按--> [LONG_HOLD]
   ^                |                    |
   |             抬起|                 抬起|
   |                v                    |
   |          [RELEASE] <----------------+
   |          |       ^
   |       超时|       |快速按下
   |          |       |
   +----------+   [REPEAT]

兼容性

  • C99 标准

  • 适用于各种微控制器平台 (STM32, Arduino, ESP32, etc.)

  • 支持裸机和 RTOS 环境

  • 内存占用小,适合资源受限的系统

例程

单片机:STM32F407VGT6

https://www.notion.so/ahhh111/MultiButton-7-RTOS-2aaa84b2a47b80dcb445ca3c77446466?source=copy_link

想看更多嵌入式干货、工具技巧,也欢迎关注:公众号「单片机那点事」

 

更多推荐