STM32 独立按键扫描功能大全-支持连击、组合连击、任意连击

本文介绍了STM32独立按键扫描的实现,包括单键、多键、连击、组合连击等各种功能。通过总线滤波处理,支持单击、长按、连发等模式,并详细阐述了按键扫描的流程和逻辑。
摘要由CSDN通过智能技术生成

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

  • 函数列表
    1. Enter the name of the first function
    1. 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

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,针对您的问题,以下是一种基于STM32独立按键扫描的实现方法: 1. 首先,将需要扫描的按键引脚连接到STM32的GPIO端口上。 2. 在初始化时,将相应的GPIO端口配置为输入模式,并设置上拉或下拉电阻。 3. 在程序中,通过读取GPIO端口的状态来检测按键是否被按下。可以使用HAL库提供的函数来读取GPIO端口的状态,如HAL_GPIO_ReadPin()。 4. 为了避免按键的抖动,需要进行软件消抖处理。一种简单的方法是在检测到按键状态改变时,延时一段时间再进行状态读取,如果状态仍然改变,则认为按键确实被按下。可以使用HAL库提供的延时函数来实现延时。 5. 可以在主循环中不断进行按键扫描,如果检测到按键被按下,则执行相应的操作。 下面是一个简单的代码示例,仅供参考: ```c #include "stm32f4xx_hal.h" #define KEY1_GPIO_PIN GPIO_PIN_0 #define KEY1_GPIO_PORT GPIOA int main(void) { HAL_Init(); // 配置KEY1引脚为输入模式,上拉电阻 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = KEY1_GPIO_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStruct); while (1) { // 延时消抖 HAL_Delay(10); if (HAL_GPIO_ReadPin(KEY1_GPIO_PORT, KEY1_GPIO_PIN) == GPIO_PIN_RESET) { // KEY1被按下 // 执行相应操作 } } } ``` 希望上述内容能够对您有所帮助!如果您还有其他问题,欢迎随时提出。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值