软件SPI可以驱动屏幕
This commit is contained in:
192
STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.c
Normal file
192
STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 模块名称:按键驱动适配层
|
||||
* 模块功能:提供MultiButton库与STM32 HAL库的适配接口
|
||||
* 适用平台:STM32F103C8T6
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-13
|
||||
* 修改记录:
|
||||
* 2026-07-13 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#include "button_driver.h"
|
||||
#include "main.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* 按键句柄数组 */
|
||||
static Button s_button_handles[BUTTON_ID_MAX];
|
||||
|
||||
/* 按键GPIO端口和引脚映射表 */
|
||||
typedef struct {
|
||||
GPIO_TypeDef* port; /* GPIO端口 */
|
||||
uint16_t pin; /* GPIO引脚 */
|
||||
} ButtonGpio_t;
|
||||
|
||||
static const ButtonGpio_t s_button_gpio[BUTTON_ID_MAX] = {
|
||||
{KEY1_GPIO_Port, KEY1_Pin}, /* KEY1: PB4 左上*/
|
||||
{KEY2_GPIO_Port, KEY2_Pin}, /* KEY2: PB5 右上*/
|
||||
{KEY3_GPIO_Port, KEY3_Pin}, /* KEY3: PB3 右下*/
|
||||
{KEY4_GPIO_Port, KEY4_Pin}, /* KEY4: PC14 左下*/
|
||||
{KEY5_GPIO_Port, KEY5_Pin}, /* KEY5: PC15 中间*/
|
||||
};
|
||||
|
||||
/*
|
||||
* 函数功能:获取指定按键的电平状态
|
||||
* 入口参数:button_id - 按键标识符
|
||||
* 返回值:GPIO电平值 (0或1)
|
||||
* 函数说明:根据按键ID读取对应GPIO引脚的电平
|
||||
*/
|
||||
uint8_t button_driver_read_level(uint8_t button_id)
|
||||
{
|
||||
if (button_id >= BUTTON_ID_MAX) {
|
||||
return 0;
|
||||
}
|
||||
return HAL_GPIO_ReadPin(s_button_gpio[button_id].port, s_button_gpio[button_id].pin);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:KEY1按键回调函数
|
||||
* 入口参数:handle - 按键句柄
|
||||
* user_data - 用户数据指针
|
||||
* 返回值:无
|
||||
* 函数说明:KEY1按下时翻转LED
|
||||
*/
|
||||
static void button_key1_callback(Button* handle, void* user_data)
|
||||
{
|
||||
(void)handle;
|
||||
(void)user_data;
|
||||
printf("KEY1\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:KEY2单击回调函数
|
||||
* 入口参数:handle - 按键句柄
|
||||
* user_data - 用户数据指针
|
||||
* 返回值:无
|
||||
* 函数说明:KEY2单击时点亮LED
|
||||
*/
|
||||
static void button_key2_single_click(Button* handle, void* user_data)
|
||||
{
|
||||
(void)handle;
|
||||
(void)user_data;
|
||||
printf("KEY2\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:KEY3单击回调函数
|
||||
* 入口参数:handle - 按键句柄
|
||||
* user_data - 用户数据指针
|
||||
* 返回值:无
|
||||
* 函数说明:KEY3单击事件处理
|
||||
*/
|
||||
static void button_key3_single_click(Button* handle, void* user_data)
|
||||
{
|
||||
(void)handle;
|
||||
(void)user_data;
|
||||
printf("KEY3: \n");
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:KEY4单击回调函数
|
||||
* 入口参数:handle - 按键句柄
|
||||
* user_data - 用户数据指针
|
||||
* 返回值:无
|
||||
* 函数说明:KEY4单击事件处理
|
||||
*/
|
||||
static void button_key4_single_click(Button* handle, void* user_data)
|
||||
{
|
||||
(void)handle;
|
||||
(void)user_data;
|
||||
printf("KEY4\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:KEY5单击回调函数
|
||||
* 入口参数:handle - 按键句柄
|
||||
* user_data - 用户数据指针
|
||||
* 返回值:无
|
||||
* 函数说明:KEY5单击事件处理
|
||||
*/
|
||||
static void button_key5_single_click(Button* handle, void* user_data)
|
||||
{
|
||||
(void)handle;
|
||||
(void)user_data;
|
||||
printf("KEY5\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:按键驱动初始化
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 函数说明:初始化所有按键对象,注册回调函数,启动按键轮询
|
||||
*/
|
||||
void button_driver_init(void)
|
||||
{
|
||||
/* 初始化KEY1 */
|
||||
button_init(&s_button_handles[BUTTON_ID_KEY1],
|
||||
button_driver_read_level,
|
||||
BUTTON_ACTIVE_LEVEL_LOW,
|
||||
BUTTON_ID_KEY1);
|
||||
button_attach(&s_button_handles[BUTTON_ID_KEY1],
|
||||
BTN_SINGLE_CLICK,
|
||||
button_key1_callback,
|
||||
NULL);
|
||||
button_start(&s_button_handles[BUTTON_ID_KEY1]);
|
||||
|
||||
/* 初始化KEY2 */
|
||||
button_init(&s_button_handles[BUTTON_ID_KEY2],
|
||||
button_driver_read_level,
|
||||
BUTTON_ACTIVE_LEVEL_LOW,
|
||||
BUTTON_ID_KEY2);
|
||||
button_attach(&s_button_handles[BUTTON_ID_KEY2],
|
||||
BTN_SINGLE_CLICK,
|
||||
button_key2_single_click,
|
||||
NULL);
|
||||
button_start(&s_button_handles[BUTTON_ID_KEY2]);
|
||||
|
||||
/* 初始化KEY3 */
|
||||
button_init(&s_button_handles[BUTTON_ID_KEY3],
|
||||
button_driver_read_level,
|
||||
BUTTON_ACTIVE_LEVEL_LOW,
|
||||
BUTTON_ID_KEY3);
|
||||
button_attach(&s_button_handles[BUTTON_ID_KEY3],
|
||||
BTN_SINGLE_CLICK,
|
||||
button_key3_single_click,
|
||||
NULL);
|
||||
button_start(&s_button_handles[BUTTON_ID_KEY3]);
|
||||
|
||||
/* 初始化KEY4 */
|
||||
button_init(&s_button_handles[BUTTON_ID_KEY4],
|
||||
button_driver_read_level,
|
||||
BUTTON_ACTIVE_LEVEL_LOW,
|
||||
BUTTON_ID_KEY4);
|
||||
button_attach(&s_button_handles[BUTTON_ID_KEY4],
|
||||
BTN_SINGLE_CLICK,
|
||||
button_key4_single_click,
|
||||
NULL);
|
||||
button_start(&s_button_handles[BUTTON_ID_KEY4]);
|
||||
|
||||
/* 初始化KEY5 */
|
||||
button_init(&s_button_handles[BUTTON_ID_KEY5],
|
||||
button_driver_read_level,
|
||||
BUTTON_ACTIVE_LEVEL_LOW,
|
||||
BUTTON_ID_KEY5);
|
||||
button_attach(&s_button_handles[BUTTON_ID_KEY5],
|
||||
BTN_SINGLE_CLICK,
|
||||
button_key5_single_click,
|
||||
NULL);
|
||||
button_start(&s_button_handles[BUTTON_ID_KEY5]);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:获取指定按键的事件
|
||||
* 入口参数:button_id - 按键标识符
|
||||
* 返回值:按键事件
|
||||
* 函数说明:返回指定按键的当前事件
|
||||
*/
|
||||
ButtonEvent button_driver_get_event(uint8_t button_id)
|
||||
{
|
||||
if (button_id >= BUTTON_ID_MAX) {
|
||||
return BTN_NONE_PRESS;
|
||||
}
|
||||
return button_get_event(&s_button_handles[button_id]);
|
||||
}
|
||||
63
STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.h
Normal file
63
STM32F103C8T6/Drivers/BSP/MultiButton/button_driver.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 模块名称:按键驱动适配层
|
||||
* 模块功能:提供MultiButton库与STM32 HAL库的适配接口
|
||||
* 适用平台:STM32F103C8T6
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-13
|
||||
* 修改记录:
|
||||
* 2026-07-13 王建锋 创建初始版本
|
||||
*/
|
||||
|
||||
#ifndef __BUTTON_DRIVER_H
|
||||
#define __BUTTON_DRIVER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "multi_button.h"
|
||||
#include "main.h"
|
||||
|
||||
/* 按键ID定义 */
|
||||
typedef enum {
|
||||
BUTTON_ID_KEY1 = 0, /* KEY1: PB4 */
|
||||
BUTTON_ID_KEY2, /* KEY2: PB5 */
|
||||
BUTTON_ID_KEY3, /* KEY3: PB3 */
|
||||
BUTTON_ID_KEY4, /* KEY4: PC14 */
|
||||
BUTTON_ID_KEY5, /* KEY5: PC15 */
|
||||
BUTTON_ID_MAX /* 按键总数 */
|
||||
} ButtonId_t;
|
||||
|
||||
/* 按键有效电平定义 */
|
||||
#define BUTTON_ACTIVE_LEVEL_LOW 0 /* 低电平有效 */
|
||||
#define BUTTON_ACTIVE_LEVEL_HIGH 1 /* 高电平有效 */
|
||||
|
||||
/*
|
||||
* 函数功能:按键驱动初始化
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 函数说明:初始化所有按键对象,注册回调函数,启动按键轮询
|
||||
*/
|
||||
void button_driver_init(void);
|
||||
|
||||
/*
|
||||
* 函数功能:获取指定按键的电平状态
|
||||
* 入口参数:button_id - 按键标识符
|
||||
* 返回值:GPIO电平值 (0或1)
|
||||
* 函数说明:根据按键ID读取对应GPIO引脚的电平
|
||||
*/
|
||||
uint8_t button_driver_read_level(uint8_t button_id);
|
||||
|
||||
/*
|
||||
* 函数功能:获取指定按键的事件
|
||||
* 入口参数:button_id - 按键标识符
|
||||
* 返回值:按键事件
|
||||
* 函数说明:返回指定按键的当前事件
|
||||
*/
|
||||
ButtonEvent button_driver_get_event(uint8_t button_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __BUTTON_DRIVER_H */
|
||||
334
STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.c
Normal file
334
STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.c
Normal file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Zibin Zheng <znbin@qq.com>
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "multi_button.h"
|
||||
|
||||
/* 回调执行宏,包含空值检查,传递user_data */
|
||||
#define EVENT_CB(ev) do { if (handle->cb[ev]) handle->cb[ev](handle, handle->user_data); } while(0)
|
||||
|
||||
/* 按键句柄链表头 */
|
||||
static Button* head_handle = NULL;
|
||||
|
||||
/* 前向声明 */
|
||||
static void button_handler(Button* handle);
|
||||
static inline uint8_t button_read_level(Button* handle);
|
||||
|
||||
/*
|
||||
* 函数功能:初始化按键结构体句柄
|
||||
* 入口参数:handle - 按键句柄结构体指针
|
||||
* pin_level - 读取按键GPIO电平的函数指针
|
||||
* active_level - 按下时的有效电平
|
||||
* button_id - 按键标识符
|
||||
* 返回值:无
|
||||
* 函数说明:初始化按键状态机和所有参数
|
||||
*/
|
||||
void button_init(Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id)
|
||||
{
|
||||
if (!handle || !pin_level) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(handle, 0, sizeof(Button));
|
||||
handle->event = (uint8_t)BTN_NONE_PRESS;
|
||||
handle->hal_button_level = pin_level;
|
||||
handle->button_level = !active_level;
|
||||
handle->active_level = active_level;
|
||||
handle->button_id = button_id;
|
||||
handle->state = BTN_STATE_IDLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:绑定按键事件回调函数
|
||||
* 入口参数:handle - 按键句柄结构体指针
|
||||
* event - 触发事件类型
|
||||
* cb - 回调函数
|
||||
* user_data - 传递给回调的用户上下文指针
|
||||
* 返回值:无
|
||||
* 函数说明:为指定事件注册回调函数
|
||||
*/
|
||||
void button_attach(Button* handle, ButtonEvent event, BtnCallback cb, void* user_data)
|
||||
{
|
||||
if (!handle || event >= BTN_EVENT_COUNT) {
|
||||
return;
|
||||
}
|
||||
handle->cb[event] = cb;
|
||||
handle->user_data = user_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:解绑按键事件回调函数
|
||||
* 入口参数:handle - 按键句柄结构体指针
|
||||
* event - 触发事件类型
|
||||
* 返回值:无
|
||||
* 函数说明:移除指定事件的回调函数
|
||||
*/
|
||||
void button_detach(Button* handle, ButtonEvent event)
|
||||
{
|
||||
if (!handle || event >= BTN_EVENT_COUNT) {
|
||||
return;
|
||||
}
|
||||
handle->cb[event] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:获取按键事件
|
||||
* 入口参数:handle - 按键句柄结构体指针
|
||||
* 返回值:按键事件
|
||||
* 函数说明:返回当前发生的按键事件
|
||||
*/
|
||||
ButtonEvent button_get_event(Button* handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return BTN_NONE_PRESS;
|
||||
}
|
||||
return (ButtonEvent)(handle->event);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:获取按键重复按下次数
|
||||
* 入口参数:handle - 按键句柄结构体指针
|
||||
* 返回值:重复按下次数
|
||||
* 函数说明:返回连击次数
|
||||
*/
|
||||
uint8_t button_get_repeat_count(Button* handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return 0;
|
||||
}
|
||||
return handle->repeat;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:重置按键状态到空闲
|
||||
* 入口参数:handle - 按键句柄结构体指针
|
||||
* 返回值:无
|
||||
* 函数说明:将按键状态机重置为初始状态
|
||||
*/
|
||||
void button_reset(Button* handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
handle->state = BTN_STATE_IDLE;
|
||||
handle->ticks = 0;
|
||||
handle->repeat = 0;
|
||||
handle->event = (uint8_t)BTN_NONE_PRESS;
|
||||
handle->debounce_cnt = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:检查按键是否按下
|
||||
* 入口参数:handle - 按键句柄结构体指针
|
||||
* 返回值:1 - 按下,0 - 未按下,-1 - 错误
|
||||
* 函数说明:检查当前按键是否处于按下状态
|
||||
*/
|
||||
int button_is_pressed(Button* handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return -1;
|
||||
}
|
||||
return (handle->button_level == handle->active_level) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:读取按键电平
|
||||
* 入口参数:handle - 按键句柄结构体指针
|
||||
* 返回值:按键电平
|
||||
* 函数说明:通过HAL函数读取GPIO电平
|
||||
*/
|
||||
static inline uint8_t button_read_level(Button* handle)
|
||||
{
|
||||
return handle->hal_button_level(handle->button_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:按键驱动核心函数,驱动状态机
|
||||
* 入口参数:handle - 按键句柄结构体指针
|
||||
* 返回值:无
|
||||
* 函数说明:实现按键消抖和事件检测的状态机
|
||||
*/
|
||||
static void button_handler(Button* handle)
|
||||
{
|
||||
uint8_t read_gpio_level = button_read_level(handle);
|
||||
|
||||
/* 非空闲状态下增加tick计数器(饱和处理) */
|
||||
if (handle->state > BTN_STATE_IDLE) {
|
||||
if (handle->ticks < UINT16_MAX) {
|
||||
handle->ticks++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 按键消抖处理 */
|
||||
if (read_gpio_level != handle->button_level) {
|
||||
if (++(handle->debounce_cnt) >= DEBOUNCE_TICKS) {
|
||||
handle->button_level = read_gpio_level;
|
||||
handle->debounce_cnt = 0;
|
||||
}
|
||||
} else {
|
||||
handle->debounce_cnt = 0;
|
||||
}
|
||||
|
||||
/* 状态机 */
|
||||
switch (handle->state) {
|
||||
case BTN_STATE_IDLE:
|
||||
if (handle->button_level == handle->active_level) {
|
||||
/* 检测到按键按下 */
|
||||
handle->event = (uint8_t)BTN_PRESS_DOWN;
|
||||
EVENT_CB(BTN_PRESS_DOWN);
|
||||
handle->ticks = 0;
|
||||
handle->repeat = 1;
|
||||
handle->state = BTN_STATE_PRESS;
|
||||
} else {
|
||||
handle->event = (uint8_t)BTN_NONE_PRESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTN_STATE_PRESS:
|
||||
if (handle->button_level != handle->active_level) {
|
||||
/* 按键释放 */
|
||||
handle->event = (uint8_t)BTN_PRESS_UP;
|
||||
EVENT_CB(BTN_PRESS_UP);
|
||||
handle->ticks = 0;
|
||||
handle->state = BTN_STATE_RELEASE;
|
||||
} else if (handle->ticks > LONG_TICKS) {
|
||||
/* 检测到长按 */
|
||||
handle->event = (uint8_t)BTN_LONG_PRESS_START;
|
||||
EVENT_CB(BTN_LONG_PRESS_START);
|
||||
handle->state = BTN_STATE_LONG_HOLD;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTN_STATE_RELEASE:
|
||||
if (handle->button_level == handle->active_level) {
|
||||
/* 按键再次按下 */
|
||||
handle->event = (uint8_t)BTN_PRESS_DOWN;
|
||||
EVENT_CB(BTN_PRESS_DOWN);
|
||||
if (handle->repeat < PRESS_REPEAT_MAX_NUM) {
|
||||
handle->repeat++;
|
||||
}
|
||||
handle->event = (uint8_t)BTN_PRESS_REPEAT;
|
||||
EVENT_CB(BTN_PRESS_REPEAT);
|
||||
handle->ticks = 0;
|
||||
handle->state = BTN_STATE_REPEAT;
|
||||
} else if (handle->ticks > SHORT_TICKS) {
|
||||
/* 超时,判断点击类型 */
|
||||
if (handle->repeat == 1) {
|
||||
handle->event = (uint8_t)BTN_SINGLE_CLICK;
|
||||
EVENT_CB(BTN_SINGLE_CLICK);
|
||||
} else if (handle->repeat == 2) {
|
||||
handle->event = (uint8_t)BTN_DOUBLE_CLICK;
|
||||
EVENT_CB(BTN_DOUBLE_CLICK);
|
||||
}
|
||||
handle->state = BTN_STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTN_STATE_REPEAT:
|
||||
if (handle->button_level != handle->active_level) {
|
||||
/* 按键释放 */
|
||||
handle->event = (uint8_t)BTN_PRESS_UP;
|
||||
EVENT_CB(BTN_PRESS_UP);
|
||||
if (handle->ticks < SHORT_TICKS) {
|
||||
handle->ticks = 0;
|
||||
handle->state = BTN_STATE_RELEASE;
|
||||
} else {
|
||||
handle->state = BTN_STATE_IDLE;
|
||||
}
|
||||
} else if (handle->ticks > SHORT_TICKS) {
|
||||
/* 按住时间过长,视为普通按下 */
|
||||
handle->ticks = 0;
|
||||
handle->repeat = 0;
|
||||
handle->state = BTN_STATE_PRESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case BTN_STATE_LONG_HOLD:
|
||||
if (handle->button_level == handle->active_level) {
|
||||
/* 继续保持按下 */
|
||||
handle->event = (uint8_t)BTN_LONG_PRESS_HOLD;
|
||||
EVENT_CB(BTN_LONG_PRESS_HOLD);
|
||||
} else {
|
||||
/* 从长按中释放 */
|
||||
handle->event = (uint8_t)BTN_PRESS_UP;
|
||||
EVENT_CB(BTN_PRESS_UP);
|
||||
handle->state = BTN_STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* 无效状态,重置为空闲 */
|
||||
handle->state = BTN_STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:启动按键工作,将句柄添加到工作链表
|
||||
* 入口参数:handle - 目标句柄结构体指针
|
||||
* 返回值:0 - 成功,-1 - 已存在,-2 - 无效参数
|
||||
* 函数说明:将按键添加到轮询链表中
|
||||
*/
|
||||
int button_start(Button* handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
Button* target = head_handle;
|
||||
while (target) {
|
||||
if (target == handle) {
|
||||
return -1;
|
||||
}
|
||||
target = target->next;
|
||||
}
|
||||
|
||||
handle->next = head_handle;
|
||||
head_handle = handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:停止按键工作,从工作链表移除句柄
|
||||
* 入口参数:handle - 目标句柄结构体指针
|
||||
* 返回值:无
|
||||
* 函数说明:将按键从轮询链表中移除
|
||||
*/
|
||||
void button_stop(Button* handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
Button** curr;
|
||||
for (curr = &head_handle; *curr; ) {
|
||||
Button* entry = *curr;
|
||||
if (entry == handle) {
|
||||
*curr = entry->next;
|
||||
entry->next = NULL;
|
||||
return;
|
||||
} else {
|
||||
curr = &entry->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:后台tick处理,定时器重复调用,间隔5ms
|
||||
* 入口参数:无
|
||||
* 返回值:无
|
||||
* 函数说明:遍历链表调用每个按键的状态机处理函数
|
||||
*/
|
||||
void button_ticks(void)
|
||||
{
|
||||
Button* target;
|
||||
Button* next;
|
||||
|
||||
target = head_handle;
|
||||
while (target) {
|
||||
next = target->next;
|
||||
button_handler(target);
|
||||
target = next;
|
||||
}
|
||||
}
|
||||
95
STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.h
Normal file
95
STM32F103C8T6/Drivers/BSP/MultiButton/multi_button.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Zibin Zheng <znbin@qq.com>
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef MULTI_BUTTON_H
|
||||
#define MULTI_BUTTON_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 版本信息 */
|
||||
#define MULTIBUTTON_VERSION_MAJOR 1
|
||||
#define MULTIBUTTON_VERSION_MINOR 1
|
||||
#define MULTIBUTTON_VERSION_PATCH 1
|
||||
|
||||
/* 配置常量 - 可根据需求修改 */
|
||||
#define TICKS_INTERVAL 5 /* 定时器轮询间隔,单位:毫秒 */
|
||||
#define DEBOUNCE_TICKS 3 /* 消抖滤波深度,最大7 (0~7) */
|
||||
#define SHORT_TICKS (300 / TICKS_INTERVAL) /* 短按阈值 */
|
||||
#define LONG_TICKS (1000 / TICKS_INTERVAL) /* 长按阈值 */
|
||||
#define PRESS_REPEAT_MAX_NUM 15 /* 最大重复计数器值 */
|
||||
|
||||
/* 编译时检查:debounce_cnt 是3位域,最大值为7 */
|
||||
#if DEBOUNCE_TICKS > 7
|
||||
#error "DEBOUNCE_TICKS exceeds 3-bit field maximum (7)"
|
||||
#endif
|
||||
|
||||
/* 前向声明 */
|
||||
typedef struct _Button Button;
|
||||
|
||||
/* 按键回调函数类型 */
|
||||
typedef void (*BtnCallback)(Button* handle, void* user_data);
|
||||
|
||||
/* 按键事件类型 */
|
||||
typedef enum {
|
||||
BTN_PRESS_DOWN = 0, /* 按键按下 */
|
||||
BTN_PRESS_UP, /* 按键释放 */
|
||||
BTN_PRESS_REPEAT, /* 重复按下检测 */
|
||||
BTN_SINGLE_CLICK, /* 单击完成 */
|
||||
BTN_DOUBLE_CLICK, /* 双击完成 */
|
||||
BTN_LONG_PRESS_START, /* 长按开始 */
|
||||
BTN_LONG_PRESS_HOLD, /* 长按保持 */
|
||||
BTN_EVENT_COUNT, /* 事件总数 */
|
||||
BTN_NONE_PRESS /* 无事件 */
|
||||
} ButtonEvent;
|
||||
|
||||
/* 按键状态机状态 */
|
||||
typedef enum {
|
||||
BTN_STATE_IDLE = 0, /* 空闲状态 */
|
||||
BTN_STATE_PRESS, /* 按下状态 */
|
||||
BTN_STATE_RELEASE, /* 释放后等待超时 */
|
||||
BTN_STATE_REPEAT, /* 重复按下状态 */
|
||||
BTN_STATE_LONG_HOLD /* 长按保持状态 */
|
||||
} ButtonState;
|
||||
|
||||
/* 按键结构体 */
|
||||
struct _Button {
|
||||
uint16_t ticks; /* tick计数器 */
|
||||
uint8_t repeat : 4; /* 重复计数器 (0-15) */
|
||||
uint8_t event : 4; /* 当前事件 (0-15) */
|
||||
uint8_t state : 3; /* 状态机状态 (0-7) */
|
||||
uint8_t debounce_cnt : 3; /* 消抖计数器 (0-7) */
|
||||
uint8_t active_level : 1; /* 有效GPIO电平 (0或1) */
|
||||
uint8_t button_level : 1; /* 当前按键电平 */
|
||||
uint8_t button_id; /* 按键标识符 */
|
||||
uint8_t (*hal_button_level)(uint8_t button_id); /* HAL读取GPIO函数 */
|
||||
BtnCallback cb[BTN_EVENT_COUNT]; /* 回调函数数组 */
|
||||
void* user_data; /* 传递给回调的用户上下文指针 */
|
||||
Button* next; /* 链表中的下一个按键 */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 公共API函数 */
|
||||
void button_init(Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id);
|
||||
void button_attach(Button* handle, ButtonEvent event, BtnCallback cb, void* user_data);
|
||||
void button_detach(Button* handle, ButtonEvent event);
|
||||
ButtonEvent button_get_event(Button* handle);
|
||||
int button_start(Button* handle);
|
||||
void button_stop(Button* handle);
|
||||
void button_ticks(void);
|
||||
|
||||
/* 工具函数 */
|
||||
uint8_t button_get_repeat_count(Button* handle);
|
||||
void button_reset(Button* handle);
|
||||
int button_is_pressed(Button* handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MULTI_BUTTON_H */
|
||||
Reference in New Issue
Block a user