【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 變量賦值,并且打印當前狀態。
目前測試得,同時按下四個按鍵,無論是單擊、雙擊,還是持續按下,都有及其靈敏的反應,十分推薦使用!
源代碼提供
包括原項目代碼和我修改移植好的代碼,下載鏈接:
博客導航
本文來自博客園,作者:膝蓋中箭衛兵,轉載請注明原文鏈接:http://www.rzrgm.cn/Skyrim-sssuuu/p/18779666

浙公網安備 33010602011771號
https://orcid.org/0000-0001-5102-772X