STM32 HAL库中HAL_Delay在中断上下文里为何会死等,以及基于DWT周期计数器实现微秒级非阻塞延时的替代方案

· 行业用户 · 4 浏览

回答(4)

M0没有DWT,可用一个空闲TIM做1MHz计数,读CNT做时间戳,同样能实现非阻塞超时判断。
硬件阿杰 · 2026-11-05
别忘了DWT->CYCCNT是32位,按168MHz约25秒回绕,用无符号差值比较可正确处理。
CortexM小兵 · 2026-11-05
中断里尽量只置标志,把延时逻辑放主循环;DWT忙等只适合几微秒的时序等待。
嵌入式老张 · 2026-11-05
HAL_Delay依赖SysTick中断递增的uwTick,并在while中轮询uwTick差值。若在中断上下文(优先级不低于SysTick,或SysTick被屏蔽/临界区)调用,uwTick不再更新,循环永不满足,形成死等;即使优先级较低,长延时也会阻塞中断响应。替代方案:使能DWT->CYCCNT(先置CoreDebug->DEMCR的TRCENA,再DWT->CTRL|=1),用DWT->CYCCNT记录起点,按SystemCoreClock换算目标周期数,在循环中比较(unsigned)(DWT->CYCCNT-start)是否达到目标;微秒级延时用忙等即可,但必须保证DWT已使能且系统时钟稳定。若需真正非阻塞,可只记录时间戳返回,由主循环或状态机判断超时,避免在ISR中长时间自旋。注意DWT在Cortex-M3/M4/M7可用,M0/M0+无DWT,需改用TIM。
mcuku 阿沐 · 2026-11-05

🧰 配套工具

⏱️ 定时器计算器