深入解析STM32 HAL_Delay()在中断中的阻塞陷阱与SysTick优先级配置

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

1. 为什么HAL_Delay()在中断中会卡死?

这个问题困扰过很多STM32开发者,我自己也踩过这个坑。记得有一次在做一个电机控制项目,我在定时器中断里加了个HAL_Delay(100)想让LED闪烁指示状态,结果整个系统直接卡死,电机停转,吓得我赶紧断电检查。

根本原因在于中断优先级冲突。HAL_Delay()的实现原理很简单:它依赖一个叫做uwTick的全局变量,这个变量每毫秒在SysTick中断里自增1。当你调用HAL_Delay(100)时,程序会记录当前的uwTick值,然后死循环检查是否过去了100个滴答。

// HAL_Delay的核心代码
while ((HAL_GetTick() - tickstart) < wait) {
    // 在这里死等
}

问题就出在这里:如果你的中断优先级比SysTick高(数字更小),那么在这个中断执行期间,SysTick中断根本无法触发,uwTick的值永远不会增加,HAL_Delay()就永远等不到它想要的那个时间点,整个程序就卡死在这个while循环里了。

2. SysTick的工作原理深度解析

要彻底理解这个问题,我们需要深入看看SysTick定时器是怎么工作的。SysTick是Cortex-M内核自带的24位递减计数器,不是STM32外设,所以所有Cortex-M芯片都有这个定时器。

SysTick的四个核心寄存器

寄存器 功能 位宽
CTRL 控制状态寄存器 32位
LOAD 重装载值寄存器 24位
VAL 当前值寄存器 24位
CALIB 校准值寄存器 32位

以STM32F103为例,如果系统时钟是72MHz,想要1ms中断一次,需要这样计算:

重装载值 = 系统时钟频率 / 分频系数 / 期望频率 - 1
          = 72,000,000 / 1 / 1000 - 1 
          = 71999

在HAL库中,这个配置是通过HAL_Init()函数完成的:

HAL_StatusTypeDef

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值