1. 中断服务函数中的延时陷阱
最近有个朋友在调试STM32的按键中断时遇到了一个奇怪的问题:程序运行后,按键第一次按下能正常触发中断,但第二次按下就完全没反应了,整个系统像"死机"了一样。我一看他的代码,发现他在中断服务函数里用了HAL_Delay()做按键消抖——这简直就是嵌入式开发中的经典"新手坑"啊!
这个问题看似简单,但背后涉及STM32的中断优先级机制和HAL库的实现原理。我自己刚入门时也踩过这个坑,当时调试了整整一天才搞明白。现在回想起来,这种"系统假死"的现象其实很有代表性,它暴露出很多开发者对中断处理机制的理解盲区。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. HAL_Delay阻塞的根源剖析
2.1 SysTick与HAL_Delay的亲密关系
先来看看HAL_Delay()的庐山真面目。这个函数在stm32xx_hal.c文件中定义,核心逻辑其实很简单:
c复制__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
while((HAL_GetTick() - tickstart) < wait) {
// 空循环等待
}
}
关键点在于HAL_GetTick()的实现。这个函数返回的是uwTick变量的值,而这个变量是在SysTick中断服务函数中被递增的:
c复制void SysTick_Handler(void)
{
HAL_IncTick();
}
__weak void HAL_IncTick(void)
{
uwTick += uwTickFreq;
}
这就形成了一个依赖链:HAL_Delay()依赖SysTick中断来更新计时,而SysTick本身也是个中断源。当你在更高优先级的中断里调用HAL_Delay()时,问题就来了。
2.2 中断优先级的生死博弈
STM32的中断控制器(NVIC)允许设置每个中断源的优先级。默认情况下:
- SysTick中断优先级:最低(数值最大,通常是15)
- 外部中断优先级:通常设置为中等(比如5-10)
当按键触发外部中断时:
- CPU
