STM32 独立按键扫描功能大全-支持连击、组合连击、任意连击
本人刚学习STM32开发,最近看了硬汉的按键检测程序,进行了架构的深度优化,所以跟大家分享一下:本人使用的STM32F103,有6个独立的按键;A、B、C、D、OK、Power,目前实现的功能如下:
1:单键短按,长按,连发,双击,3连击。。。。。最多不限制;
2:各种组合按键,组合按键的短按,长按,连发,组合按键的双击,连击;
3:这些功能都可以随意配置;
性能测试,STM32使用内部时钟,64M,有按键的时候,按键扫描函数执行时间是12us;
程序先不跟大家分享了,分享一下我对按键扫描的理解和实现的大概流程:
-
虚拟按键扫描功能说明:V1.0-2019.12.30
按键定义:单键/多键;单击/组合(连击);短按/长按;连发;
注:对于应用层来说,组合也是单击,不需要标识出来。A和B组合生效,可以单键A和单键B组合,也可以是多键AB单击;
定义说明:
1: 单键/多键:只有1个按键变化;多键:2个及以上的按键同变化(变化的时间接近即可,底层滤波自动处理,总线滤波参数控制);
后文中提到的“按键”,包括单键或者多键,多键也可以称之为一个按键!!!,大家认为的组合按键的双击,我们称之为多键连击;
“不同的按键”不能有相同的部分,如单键A,和多键AB不是不相同的按键;
2: 单击:设定的时间内,有按键(单键或多键)按下1次;如不支持连击/组合,单击:有按键(单键或多键)按下1次;
3: 组合:设定的时间内,有多个不同的按键(单键或者多键)按下1次;单键和单键,单键和多键,多键和多键都可以组合;
4: 连击:设定的时间内,相同的按键(单键或多键)按下2次及以上;
5: 长按:单击/组合/连击发生后,并且持续稳定的时间超过设定的时间阈值;
6: 连发:单击/组合/连击长按之后,按照设定的周期,不断的产生单击/组合/连击事件;
注:设定的时间内,要么发生连击,要么发生不同的按键进行组合,两者为互斥事件;
按照时间顺序排列,有几个按键(单键还是多键),是单击还是组合还是连击,稳定之后是长按,还是短按,长按之后是否连发;
按键扫描流程:
1: 将物理按键映射到逻辑按键上,多个按键映射成并口的数据通道,按键检测,转换成采集通道上的数据。
2: 某一个数据线上不用独立滤波,而是进行总线数据滤波。也就是多个按键一起滤波;
3: 组合/连击:总线上有数据时(有按键按下后),开始定时,发生数据变化时(又有按键按下),判断是组合,还是连击,
连击是只指相同的按键,组合是指不同的按键; 连击时,按键次数增加,组合时,有效按键个数增加,组合和连击,只能发生一个;
4: 连击时,可以复位定时器,组合时,可以不复位,也可以复位,正常不需要复位;
在这里插入代码片
/********************************************
- Copyright ©, 1993-2012, Liming Comm. Co., Ltd.
- @file :RM_KEY.c
- @brief :虚拟按键扫描
- @author :czm
- @version :V1.0
- @date :2019-11-15
- @time :20:22:35
- 函数列表
-
- Enter the name of the first function
-
- Enter the name of the second function
- 修改历史
- 2019-11-15 czm 建立文件
*******************************************************************************/
/*
- 虚拟按键扫描功能说明:V1.0-2019.12.30
按键定义:单键/多键;单击/组合(连击);短按/长按;连发;
注:对于应用层来说,组合也是单击,不需要标识出来。A和B组合生效,可以单键A和单键B组合,也可以是多键AB单击;
定义说明:
1: 单键/多键:只有1个按键变化;多键:2个及以上的按键同变化(变化的时间接近即可,底层滤波自动处理,总线滤波参数控制);
后文中提到的“按键”,包括单键或者多键,多键也可以称之为一个按键!!!,大家认为的组合按键的双击,我们称之为多键连击;
“不同的按键”不能有相同的部分,如单键A,和多键AB不是不相同的按键;
2: 单击:设定的时间内,有按键(单键或多键)按下1次;如不支持连击/组合,单击:有按键(单键或多键)按下1次;
3: 组合:设定的时间内,有多个不同的按键(单键或者多键)按下1次;单键和单键,单键和多键,多键和多键都可以组合;
4: 连击:设定的时间内,相同的按键(单键或多键)按下2次及以上;
5: 长按:单击/组合/连击发生后,并且持续稳定的时间超过设定的时间阈值;
6: 连发:单击/组合/连击长按之后,按照设定的周期,不断的产生单击/组合/连击事件;
注:设定的时间内,要么发生连击,要么发生不同的按键进行组合,两者为互斥事件;
按照时间顺序排列,有几个按键(单键还是多键),是单击还是组合还是连击,稳定之后是长按,还是短按,长按之后是否连发;
按键扫描流程:
1: 将物理按键映射到逻辑按键上,多个按键映射成并口的数据通道,按键检测,转换成采集通道上的数据。
2: 某一个数据线上不用独立滤波,而是进行总线数据滤波。
3: 组合/连击:总线上有数据时(有按键按下后),开始定时,发生数据变化时(又有按键按下),判断是组合,还是连击,
连击是只指相同的按键,组合是指不同的按键; 连击时,按键次数增加,组合时,有效按键个数增加,组合和连击,只能发生一个;
4: 连击时,可以复位定时器,组合时,可以不复位,也可以复位,正常不需要复位;
*/
#include “RM_KEY.h”
static RM_KEY_CONFIG_T s_RM_KEY_CFG = {0};
// RM 硬件键实时运行状态
static RM_KEY_RUN_DATA_T s_tRmKeyRunData = {0};
// 硬件按键GPIO和PIN定义
static const RM_KEY_GPIO_DEF_T s_atRmKeyGpioDef[RM_HARD_KEY_NUM] =
{
// 按键都是高电平有效 TRUE
{GPIOA, GPIO_Pin_4, TRUE}, // KEY A 按键 PA4
{GPIOC, GPIO_Pin_0, TRUE}, // KEY B 按键 PC0
{GPIOC, GPIO_Pin_15, TRUE}, // KEY C 按键 PC15
{GPIOC, GPIO_Pin_5, TRUE}, // KEY D 按键 PC5
{GPIOC, GPIO_Pin_14, TRUE}, // KEY OK 按键 PC14
{GPIOA, GPIO_Pin_0, TRUE}, // Power 按键 PA0
};
/**
- @brief 虚拟按键转化表,将所有实体按键都转换成一个bit
*/
static const u8 s_auKeyBitDef[RM_HARD_KEY_NUM] =
{
// 单按键定义 A、B、C、D、OK、Power
0x01, 0x02, 0x04, 0x08, 0x010, 0x20,
// 组合按键定义
};
// 可以用于LCD 没有操作时息屏 有操作时亮屏
///* 用于按键超时进入屏保 */
//static int32_t s_KeyTimeOutCount = 0;
//static uint8_t s_LcdOn = 1;
/**
-
@brief 计算8位数据中1的个数
-
@param [in] uData 需要计算的数据,8位
-
@return 数据中1的个数
-
@author
-
@since trunk.00001
-
@bug
*/
u8 Ones8(u8 uData)
{
uData -= ((uData >> 1) & 0x55);
uData = (((uData >> 2) & 0x33) + (uData & 0x33));
uData += (uData >> 4);return (uData & 0x0F);
}
/**
-
@brief 判断单独按键管脚是否有效 对上屏蔽底层 对上TRUE就是有效,FALSE就是弹开
-
@param [in] nKeyID 按键ID 0 ~ RM_HARD_KEY_NUM-1
-
@return TRUE:按键有效;FALSE:按键无效
-
@author
-
@since trunk.00001
-
@bug
*/
static BOOL RM_KEY_IsActive(RM_KEY_ID_E nKeyID)
{
BOOL bPinLevel;// 判断按键管脚IO电平 TRUE:高电平
if (s_atRmKeyGpioDef[nKeyID].ptGpio->IDR & s_atRmKeyGpioDef[nKeyID].u2Pin)
{
bPinLevel = TRUE;
}
else
{
bPinLevel = FALSE;
}if (bPinLevel == s_atRmKeyGpioDef[n