【STM32 系列】超好用的开源按键状态系统lwbtn,以及超详细的移植教程
GitHub开源按键状态机lwbtn
原项目地址:https://github.com/MaJerle/lwbtn
移植教程
第一步:找到lwbtn文件

点进这个文件夹,顺着点进去,就可以看到一共那么几个文件:

这几个就是接下来要移植的按键系统。
第二步:文件放入自己的工程
这里要注意的一个点:将 lwbtn_opts_template.h 文件改名为:lwbtn_opts.h 作为用户头文件,并且在keil中新建lwbtn_opts_use.c 文件作为用户.c文件,接下来我们就是要在这个俩个文件中编写我们所需要的函数。
结束以上操作后在keil中有那么几个文件:

第三步:了解各个文件的作用
lwbtn.c
大佬编写的按键状态机的各种状态库以及逻辑判断,这里用户不需要管,也不需要修改。
lwbtn.h
就是 lwbtn.c 状态库的头文件,用户也不需要管,不需要修改。
lwbtn_opt.h
包含按键各种事件的设置,有按下消抖、释放消抖、长按时间等等设置,用户可以在此修改宏定义来设置按键功能。
lwbtn_opts_use.c
用户编写函数的文件,在此增加按键处理函数等
lwbtn_opts.h
就是 lwbtn_opts_use.c 文件的头文件
第五步:在 lwbtn_opts_use.c 文件增加所需函数
点击查看代码
#include "lwbtn_opts.h"
/**
* @brief 全局变量,记录当前触发的按键编号
*
* - 0: 无按键
* - 1: KEY0
* - 2: KEY1
* - 3: KEY2
* - 4: KEY_UP
* 必须要 lwbtn_keys = btn_index + 1; 以摆脱为0时的按键状态
*/
uint8_t lwbtn_keys;
/* 为每个按键定义GPIO参数 */
lwbtn_argdata_port_pin_state_t key0_gpio = {
.port = KEY0_GPIO_Port, /* KEY0的GPIO端口 */
.pin = KEY0_Pin, /* KEY0的GPIO引脚 */
.state = 0 /* 低电平触发 */
};
lwbtn_argdata_port_pin_state_t key1_gpio = {
.port = KEY1_GPIO_Port, /* KEY1的GPIO端口 */
.pin = KEY1_Pin, /* KEY1的GPIO引脚 */
.state = 0 /* 低电平触发 */
};
lwbtn_argdata_port_pin_state_t key2_gpio = {
.port = KEY2_GPIO_Port, /* KEY2的GPIO端口 */
.pin = KEY2_Pin, /* KEY2的GPIO引脚 */
.state = 0 /* 低电平触发 */
};
lwbtn_argdata_port_pin_state_t key_up_gpio = {
.port = KEY_UP_GPIO_Port, /* KEY_UP的GPIO端口 */
.pin = KEY_UP_Pin, /* KEY_UP的GPIO引脚 */
.state = 1 /* 高电平触发 */
};
/* 定义按钮数组,每个按钮绑定对应的GPIO参数 */
lwbtn_btn_t buttons[] = {
{ .arg = &key0_gpio }, /* KEY0 */
{ .arg = &key1_gpio }, /* KEY1 */
{ .arg = &key2_gpio }, /* KEY2 */
{ .arg = &key_up_gpio }, /* KEY_UP */
};
/**
* @brief 获取按钮的当前状态
*
* 通过读取GPIO引脚的电平,判断按钮是否处于激活状态。
*
* @param lwobj: LwBTN实例(未使用)
* @param btn: 按钮实例,包含GPIO参数
* @return uint8_t: 1表示按钮激活,0表示按钮未激活
*/
uint8_t get_button_state(lwbtn_t* lwobj, lwbtn_btn_t* btn)
{
lwbtn_argdata_port_pin_state_t* cfg = btn->arg;
uint8_t pin_state = HAL_GPIO_ReadPin(cfg->port, cfg->pin);
return (pin_state == cfg->state) ? 1 : 0; // 返回激活状态
}
/**
* @brief 按钮事件处理函数
*
* 根据LwBTN库触发的事件类型,处理按钮的按下、释放、单击、双击和长按事件。
* * 每一个事件都会触发一个回调 *
*
* @param lwobj: LwBTN实例
* @param btn: 触发事件的按钮实例
* @param evt: 事件类型(按下、释放、单击、长按等)
*/
void button_event_handler(lwbtn_t* lwobj, lwbtn_btn_t* btn, lwbtn_evt_t evt)
{
// 根据按钮索引识别具体按键
uint8_t btn_index = (btn - lwobj->btns);
switch (evt) {
/* 按键按下事件 */
case LWBTN_EVT_ONPRESS:
// lwbtn_keys = btn_index + 1; // 记录按键编号
break;
/* 按键释放事件 */
case LWBTN_EVT_ONRELEASE:
// lwbtn_keys = btn_index + 1; // 记录按键编号
break;
/* 单击/双击事件 */
case LWBTN_EVT_ONCLICK:
if (btn->click.cnt == 2) { /* 双击 */
lwbtn_keys = btn_index + 1; // 记录按键编号
btn->click.cnt = 0; // 重置计数器
printf("按键%d 双击\r\n",lwbtn_keys);
} else { /* 单击 */
lwbtn_keys = btn_index + 1; // 记录按键编号
printf("按键%d 单击\r\n",lwbtn_keys);
}
break;
/* 长按事件 */
case LWBTN_EVT_KEEPALIVE:
lwbtn_keys = btn_index + 1; // 记录按键编号
printf("按键%d 长按保持\n", lwbtn_keys);
break;
}
}
/**
* @brief 初始化按钮管理器
*
* 使用LwBTN库初始化按钮管理器,绑定按钮数组、状态读取函数和事件处理函数。
*/
void button_init(void)
{
lwbtn_init_ex(NULL, buttons, BUTTON_COUNT, get_button_state, button_event_handler);
}
/**
* @brief 处理按键状态
*
* 定期调用此函数以处理按键状态,触发事件回调。
*/
void get_btn()
{
uint32_t tick = 0;
tick = HAL_GetTick(); // 获取当前系统时间
lwbtn_process(tick); // 处理按键状态
}
第六步:在lwbtn_opts.h 文件增加说明
点击查看代码
#ifndef LWBTN_OPTS_H
#define LWBTN_OPTS_H
/* 将此文件重命名为 "lwbtn_opts.h" 以适应您的应用程序 */
/*
* 打开 "include/lwbtn/lwbtn_opt.h" 并
* 复制并在此处替换您希望更改的设置值
*/
#include "main.h" // 此处修改为用户的主头文件
#define BUTTON_COUNT (sizeof(buttons) / sizeof(buttons[0]))
extern void button_init(void);
void get_btn();
extern uint8_t lwbtn_keys;
#endif /* LWBTN_OPTS_H */
第七步:主函数使用
点击查看代码
void main(void) {
button_init();
while(1) {
get_btn(); // 持续获取按键值
printf("%d\r\n", lwbtn_keys); // 打印出按下的按键
if(lwbtn_keys == ??) {
...
}
}
}
使用说明
在 button_event_handler 按钮事件处理函数中,按键按下分为:按下,释放;按下类型又分为:单击、双击、持续按下。
这每一个状态/事件,进行过后,其都会进行一次回调,即回到主函数一次,故也是分为了1、按下 2、释放 3、单击 4、双击 5、持续按下 五个回调状态。
你可以在 button_event_handler 函数中,switch 中,每 case 一个状态,就可以在此状态下执行某些操作
在本移植文件中,仅在按键单击和双击以及持续按下这三个状态中进行了 lwbtn_keys 变量赋值,并且打印当前状态。
目前测试得,同时按下四个按键,无论是单击、双击,还是持续按下,都有及其灵敏的反应,十分推荐使用!
源代码提供
包括原项目代码和我修改移植好的代码,下载链接:
博客导航
本文来自博客园,作者:膝盖中箭卫兵,转载请注明原文链接:https://www.cnblogs.com/Skyrim-sssuuu/p/18779666

浙公网安备 33010602011771号
https://orcid.org/0000-0001-5102-772X