指针的基本了解
枚举+结构体+定时器完成状态机用于按键检测以及消抖

我们仔细看这上面的宏定义代码,是不是很麻烦,所以c语言就有了一个新的概念,枚举,枚举可以达成和下面一样的效果


在默认情况下第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。我们在这个实例中把第一个枚举成员的值定义为 1,第二个就为 2,以此类推。不过可以强行修改值
当然关于枚举的定义我们有下面两种方式

// 按键状态枚举
//typedef 是 C 语言中的关键字,用于为已有的数据类型定义一个新的名称(别名)
typedef enum {
KEY_STATE_IDLE, // 空闲(未按下)
KEY_STATE_DEBOUNCE, // 消抖检测中
KEY_STATE_PRESSED, // 已确认按下
KEY_STATE_RELEASE // 等待释放
} KeyState;
// 单个按键的数据结构
typedef struct {
GPIO_TypeDef *GPIOx; // GPIO端口(如 GPIOB)
uint16_t GPIO_Pin; // 引脚号(如 GPIO_PIN_0)
KeyState state; // 当前状态
uint8_t is_pressed; // 按键是否被按下(供外部读取)
uint32_t press_time; // 按下时间(用于长按检测)
} Key;
// 定义所有按键(假设4个按键)
Key keys[] = {
{GPIOB, GPIO_PIN_0, KEY_STATE_IDLE, 0, 0}, // KEY1
{GPIOB, GPIO_PIN_1, KEY_STATE_IDLE, 0, 0}, // KEY2
{GPIOB, GPIO_PIN_2, KEY_STATE_IDLE, 0, 0}, // KEY3
{GPIOA, GPIO_PIN_0, KEY_STATE_IDLE, 0, 0} // KEY4
};
了解了枚举我们就可以写以上代码,这样我们就有了新的框架,下面是使用方法
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim->Instance == TIM3) {
for (int i = 0; i < 4; i++) {
Key *key = &keys[i];
uint8_t current_level = HAL_GPIO_ReadPin(key->GPIOx, key->GPIO_Pin);
switch (key->state) {
//---------------- 空闲状态 -------------------
case KEY_STATE_IDLE:
if (current_level == GPIO_PIN_RESET) { // 检测到低电平(可能按下)
key->state = KEY_STATE_DEBOUNCE; // 进入消抖检测
}
break;
//---------------- 消抖检测 -------------------
case KEY_STATE_DEBOUNCE:
if (current_level == GPIO_PIN_RESET) { // 持续低电平,确认按下
key->state = KEY_STATE_PRESSED;
key->is_pressed = 1; // 标记按键已按下
key->press_time = HAL_GetTick(); // 记录按下时间戳
} else { // 电平恢复,视为抖动
key->state = KEY_STATE_IDLE;
}
break;
//---------------- 已按下状态 -----------------
case KEY_STATE_PRESSED:
if (current_level == GPIO_PIN_SET) { // 检测到高电平(释放)
key->state = KEY_STATE_RELEASE;
} else {
// 此处可扩展长按检测(例如持续按下超过 2s)
// if (HAL_GetTick() - key->press_time > 2000) { ... }
}
break;
//---------------- 释放检测 -------------------
case KEY_STATE_RELEASE:
if (current_level == GPIO_PIN_SET) { // 确认释放
key->state = KEY_STATE_IDLE;
key->is_pressed = 0; // 清除按下标记
}
break;
}
}
}
}
这种状态机的方法延时时间近似一个中断周期,若需要加时间,可以在最前面添加逻辑,

1万+

被折叠的 条评论
为什么被折叠?



