STM32之按键长短按设计【一键多用】
在嵌入式开发中,按键的短按和长按功能是提升交互效率的关键。本文将详解如何在STM32中通过状态机和时间戳实现按键的“一键多用”,并提供完整的代码和设计思路。
一、设计原理
1. 核心需求
- 消抖处理:消除机械按键的抖动(20ms)。
- 长短按区分:按下时间 < 1s 为短按,≥1s 为长按。
- 事件触发:通过标志位分离按键检测与事件处理。
2. 状态机设计
定义三种按键状态:
typedef enum {
BUTTON_STATE_RELEASED, // 松开状态
BUTTON_STATE_PRESSED, // 按下状态
BUTTON_STATE_DEBOUNCING // 消抖状态
} ButtonState;
二、代码实现
- 按键结构体与宏定义(key.h)
#define DEBOUNCE_TIME 20 // 消抖时间20ms
#define LONG_PRESS_TIME 1000 // 长按阈值1000ms
typedef struct {
ButtonState state; // 当前状态
uint32_t buttonTime; // 状态切换时间戳
uint32_t presstime; // 按下时刻时间戳
uint8_t pressedFlag; // 短按标志
uint8_t longPressFlag; // 长按标志
GPIO_TypeDef* gpioPort; // GPIO端口(如GPIOA)
uint16_t gpioPin; // GPIO引脚(如GPIO_PIN_0)
} Button;
- 中断回调函数(key.c)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == key1.gpioPin) {
if (key1.state == BUTTON_STATE_RELEASED) {
// 按下:进入消抖状态,记录时间戳
key1.state = BUTTON_STATE_DEBOUNCING;
key1.buttonTime = HAL_GetTick(); //记录按下时刻,用于消抖计时
key1.presstime = key1.buttonTime; // 记录按下时刻,用于长按计时
} else if (key1.state == BUTTON_STATE_PRESSED) {
// 松开:进入消抖状态,记录时间戳
key1.state = BUTTON_STATE_DEBOUNCING;
key1.buttonTime = HAL_GetTick(); //记录松开时刻,用于消抖计时
}
}
// 其他按键类似...
}
- 按键处理函数(核心逻辑)
void Button_Process(Button* button) {
// 1. 消抖处理