本帖最后由 田裕中 于 2021-11-20 14:32 编辑
按键的多功能触发
概述
本文所介绍的按键是基于STM32F系列独立按键模式,目的是使单个按键具备多种按键效果。常见的有单击、长按等功能。为拓展功能多样性,对按键驱动进行设计,实现按键功能的多样性,本设计已达到的功能包括单击、长按、双击、三击、四击......等,剩余可由用户自行添加。按键消息通过消息队列进行传递。
按键对象封装 类似于面向对象中类的封装,该结构体包含按键触发函数、硬件接口、计数器及按键状态标记。 typedef void (*KEYFUNC) (uint16_t tick_cnt_ptr);
该定义为:声明一个函数指针,指向一个参数为uint16_t 类型的变量的函数。
typedef struct
{
KEYFUNC key_function;
KEYFUNC fast_key_fun;
GPIO_TypeDef* GPIOx;
uint16_t Pin;
uint16_t key_cnt;
uint16_t Status;
} KEYSTATUS;
按键事件注册 注册按键的触发函数、初始状态State、按键初始化等。声明两个枚举变量进行按键的开启与关闭(DISABLE_KEY、GENERAL_KEY)。 enum
{
DISABLE_KEY,
GENERAL_KEY
};申明一个map对象,为每个按键引用驱动类:
KEYSTATUS io_key_map[IOKEY_NUM];在此函数开启之前确保按键引脚已成功初始化。
void ap_peripheral_key_register(INT8U type)
{
io_key_num = 0;
switch(type)
{
case DISABLE_KEY:
{
//disable all key
}
break;
case GENERAL_KEY:
{
#if IO_KEY
io_key_map[io_key_num].GPIOx = KEY_Pin_GPIO_Port;
io_key_map[io_key_num].Pin = KEY_Pin_Pin;
io_key_map[io_key_num].key_function = ap_peripheral_io_key_exe;
//io_key_map[io_key_num].fast_key_fun = ap_peripheral_io_fast_key_exe;
io_key_map[io_key_num].key_cnt = 0;
io_key_map[io_key_num++].Status = 0;
#endif
#if CHARGE
io_key_map[io_key_num].GPIOx = STAT_CHG_GPIO_Port;
io_key_map[io_key_num].Pin = STAT_CHG_Pin;
io_key_map[io_key_num].key_function = ap_peripheral_charge_exe;
io_key_map[io_key_num].key_cnt = 0;
io_key_map[io_key_num++].Status = 0;
#endif
#if IO_USB
io_key_map[io_key_num].GPIOx = USB_CH_GPIO_Port;
io_key_map[io_key_num].Pin = USB_CH_Pin;
io_key_map[io_key_num].key_function = ap_peripheral_io_usb_exe;
io_key_map[io_key_num].key_cnt = 0;
io_key_map[io_key_num++].Status = 0;
#endif
}
break;
default:
ap_peripheral_key_register(DISABLE_KEY);
break;
}
}
按键回调函数 按键事件注册后,每个按键引脚功能编写对应的回调函数,为事件注册使用。说明:按键消息是基于消息队列进行消息传递,可根据用户的需求自行设计回调函数功能! 第一个按键回调函数: void ap_peripheral_io_key_exe(INT16U tick_cnt_ptr)
{
if(tick_cnt_ptr >= LONG_KEY_TIME)
{
msgQSend(APQ, MSG_APQ_LONG_KEY,MSG_PRI_NORMAL);
}
else if(tick_cnt_ptr == TWO_KEY_VALUE)
{
msgQSend(APQ, MSG_APQ_TWO_KEY,MSG_PRI_NORMAL);
}
else if(tick_cnt_ptr == THREE_KEY_VALUE)
{
msgQSend(APQ, MSG_APQ_THREE_KEY,MSG_PRI_NORMAL);
}
else if(tick_cnt_ptr == FOUR_KEY_VALUE)
{
msgQSend(APQ, MSG_APQ_FOUR_KEY,MSG_PRI_NORMAL);
}
else if(tick_cnt_ptr == FIVE_KEY_VALUE)
{
msgQSend(APQ, MSG_APQ_FIVE_KEY,MSG_PRI_NORMAL);
}
else
{
msgQSend(APQ, MSG_APQ_CLICK_KEY,MSG_PRI_NORMAL);
}
}
其他按键的回调函数与其相似,可自行设计......
按键扫描 按键扫描通过定时器中断进行扫描,优点是有稳定的扫描时间,可计算按键的持续时间及消抖,本设计是20ms扫描一次。此函数中,由按键事件注册函数提供一个io_key_num为其提供扫描范围: 总结 该独立按键的多种功能设计,目的是实现单个按键实现多种功能,就好比遥控器的上、下、左、右、确定、返回等,通过单个按键就可实现其所有功能。该按键功能的实现,依赖于消息队列进行按键消息传递,项目引入消息队列后,极大方便了按键回调函数的设计实现。 个人笔记总结,若有问题,欢迎留言、批评指正! 公众号为个人资料总结,内有资料文档!
|