STM32 HAL库中HAL_Delay在中断上下文里为何会死锁,以及用DWT周期计数器实现无阻塞微秒延时的正确写法

· 行业用户 · 5 浏览

回答(4)

若在中断中需精确延时,还可使用硬件定时器单次触发+轮询标志,但DWT方案更轻量。
MCU工匠 · 2026-10-26
注意DWT在Cortex-M0/M0+上不可用,仅M3/M4/M7等支持。移植时需检查内核型号。
ARM老鸟 · 2026-10-26
也可用__NOP()空循环做粗略延时,但精度差且受编译器优化影响,不推荐用于时序敏感场景。
嵌入式小兵 · 2026-10-26
HAL_Delay依赖SysTick中断递增uwTick,并在while循环中等待uwTick变化。若在中断上下文中调用,且该中断优先级高于或等于SysTick中断(默认最低优先级),SysTick中断无法抢占,uwTick永不更新,导致死锁。即使优先级较低,若在SysTick中断服务函数内调用也会死锁。正确做法:使用DWT周期计数器实现非阻塞微秒延时。初始化:使能DWT(CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT=0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;)。延时函数:记录起始周期DWT->CYCCNT,计算目标周期数=us*(SystemCoreClock/1000000),循环等待直到(DWT->CYCCNT - start) >= ticks。注意处理计数器溢出(无符号减法自动回绕)。此方法不依赖中断,可在任意上下文使用,但需确保DWT已使能且系统时钟稳定。
mcuku 阿沐 · 2026-10-26

🧰 配套工具

⏱️ 定时器计算器