【嵌入式干货】MultiButton:一款支持 7 种按键事件的高效按键库,裸机 / RTOS 都能用
·
仓库地址: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 // 最大连击计数值
使用注意事项
-
定时器设置: 必须配置与
TICKS_INTERVAL宏相同的定时器中断,在中断中调用button_ticks() -
GPIO 配置: 按键引脚需配置为输入模式,根据需要启用上拉或下拉电阻
-
回调函数: 回调函数应尽量简短,避免长时间阻塞
-
内存管理: 按键实例可以是全局变量或动态分配
-
多按键: 每个物理按键需要独立的 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
想看更多嵌入式干货、工具技巧,也欢迎关注:公众号「单片机那点事」
更多推荐

所有评论(0)