按键状态机(实现单击,长按,双击)的模块分享

文章介绍了如何使用定时器和状态机来区分按键的单击、双击和长按操作。通过设置不同的状态和计时器,实现了对按键不同动作的精确识别,包括按键按下和弹起状态的拆分以及不同反馈的判断逻辑。

目录

一、相关说明

二、分析

三、模块代码

三、代码讲解

四、作者的话


一、相关说明

        1.需要的资源:一个定时器,一个按键。

        2.相关设置:利用定时器计时中断,10ms进行一次按键扫描。

        3.使用说明:定时器中断的优先级要设置高一点,相关的宏定义可以自行定义。

        4.实现功能:区分单个按键的单击,双击,长按。

        5.规定:双击:2次按下的间隔不超过200ms属于双击。

                      单击:第一次按下持续时间小于1s属于单击。

                      长按:第一次按下持续时间不小于1s属于长按。

        (时间长短可自己调整)

        6.目标:帮助理解按键的状态机。

二、分析

        1.时间线分析和状

### 按键状态机的设计与实现 在嵌入式系统中,使用按键检测功能来识别不同的用户操作(如短按、按、双击)是常见的需求。为了高效地实现这一功能,通常采用**状态机设计**结合**定时器中断**进行处理。 #### 状态机的基本状态 按键状态机可以包含以下主要状态: - **IDLE**:空闲状态,等待按键按下。 - **PRESSED**:按键被按下,开始计时以判断是否为按或双击。 - **RELEASED**:按键释放,记录单击事件或准备检测双击。 - **LONG_PRESS**:按状态,当按键持续按下超过设定时间后进入此状态。 - **DOUBLE_CLICK**:双击状态,第二次按键按下且时间间隔符合双击条件时触发。 #### 实现步骤 1. **初始化全局变量** 定义必要的变量用于记录按键的状态和时间戳: ```c uint8_t key_pressed = 0; // 按键按下标志 uint8_t key_released = 0; // 按键释放标志 uint32_t press_time = 0; // 记录按键按下时间 uint32_t release_time = 0; // 记录按键释放时间 uint8_t click_count = 0; // 双击计数器 ``` 2. **配置定时器** 使用HAL库的定时器模块,设置一个定时周期为1ms的定时器中断[^3]。例如,在CubeMX中启用TIM2并配置为中断模式。 3. **按键中断处理** 在按键中断服务函数中,记录按键按下时间并切换到`PRESSED`状态: ```c void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == KEY_PIN) { if (HAL_GPIO_ReadPin(KEY_PORT, KEY_PIN) == GPIO_PIN_RESET) { press_time = HAL_GetTick(); // 获取当前时间 key_pressed = 1; click_count++; // 增加点击次数 } else { release_time = HAL_GetTick(); key_released = 1; } } } ``` 4. **主循环中的状态判断** 在主循环中根据按键状态进行判断,并切换状态机: ```c while (1) { if (key_pressed) { uint32_t current_time = HAL_GetTick(); if ((current_time - press_time) > LONG_PRESS_TIME) { // 按事件 handle_long_press(); key_pressed = 0; } } if (key_released) { uint32_t interval = release_time - press_time; if (interval < SHORT_PRESS_TIME) { // 短按事件 handle_short_press(); } if (click_count == 2) { // 双击事件 handle_double_click(); click_count = 0; } key_released = 0; } } ``` 5. **定义时间常量** 根据实际需求定义相关的时间阈值: ```c #define SHORT_PRESS_TIME 200 // 短按时间阈值(毫秒) #define LONG_PRESS_TIME 1000 // 按时间阈值(毫秒) #define DOUBLE_CLICK_INTERVAL 300 // 双击时间间隔(毫秒) ``` #### 优化建议 - **去抖动处理**:在按键中断中加入软件去抖动逻辑,避免误触发。 - **状态超时机制**:为每个状态设置超时机制,确保状态机不会卡死。 - **多按键支持**:通过扩展结构体和数组,支持多个按键的独立检测。 ###
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

废话文学创始人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值