1. 从轮询到中断:按键检测的进阶之路
刚开始玩STM32的时候,我最常用的按键检测方式就是在主循环里不断读取GPIO状态。这种方法简单直接,就像你每隔5秒就去检查一次门铃有没有人按一样。但实际项目中很快就发现问题了——当主循环里有其他耗时任务时,按键响应就会变得迟钝,甚至完全丢失快速按键动作。
这时候**外部中断(EXTI)**就像个尽职的门房,只要有人按门铃(按键触发),它就会立即通知你。以STM32F103C8T6为例,它的所有GPIO都支持中断功能。通过STM32CubeMX配置PA0为外部中断模式时,我通常会注意这三个关键点:
- 触发边沿选择:一般机械按键推荐用下降沿触发(按键按下瞬间)
- 消抖处理:硬件上可以加0.1uF电容,软件里我习惯用20-50ms延时
- 中断优先级:如果系统中有其他中断,需要合理设置NVIC优先级
c复制// 典型的中断服务函数示例
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if(GPIO_Pin == KEY_Pin) {
HAL_Delay(50); // 软件消抖
if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET) {
// 实际处理逻辑放在这里
}
}
}
实测发现,中断方式比轮询的响应速度能快10倍以上。特别是在处理双击、长按等复合操作时,中断配合定时器能实现更精确的时间检测。不过要注意,中断服务函数里不宜做复杂操作,我的经验是只设置标志位,具体逻辑放到主循环处理。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 状态机:让LED控制更智能
刚开始做LED控制时,我的代码里全是if-else判断,后来发现当需要实现单击亮、双击闪、长按呼吸灯等功能时,代码就变成了难以维护的"面条代码"。这时候**状态机(State Machine)**就像个智能管家,把杂乱的控制逻辑梳理得井井有条。
以最常见的LED开关为例,我们可以定义这些状态:
- OFF:LED熄灭状态
- ON:LED点亮状态
- BLINK:闪烁状态(用于双击触发)
c复制typedef enum {
