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

· 6 浏览

回答(4)

可封装delay_us:先算cycles=us*(SystemCoreClock/1000000),用(uint32_t)(DWT->CYCCNT-start)<cycles判断,天然兼容回绕。
码农阿峰 · 2026-10-20
DWT的CYCCNT在部分低端Cortex-M0上不存在,M3/M4/M7才可用,移植前先查内核手册。
CortexM小兵 · 2026-10-20
中断里做微秒级忙等本身要谨慎,建议只用于极短时序(如传感器握手),长延时改用状态机+定时器回调。
嵌入式老张 · 2026-10-20
HAL_Delay依赖HAL_IncTick在SysTick中断中递增uwTick,并在while循环中等待uwTick变化。若在中断上下文中调用,且该中断优先级不低于SysTick(或SysTick被屏蔽),SysTick无法抢占执行,uwTick永不递增,形成死锁;即使优先级较低,也会因长时间忙等阻塞其他中断。正确做法是中断里绝不用HAL_Delay。无阻塞微秒延时可用DWT周期计数器:使能DWT(CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;DWT->CYCCNT=0;DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk),读取SystemCoreClock计算每微秒周期数,记录起始CYCCNT,循环等待差值达到cycles即可。注意CYCCNT为32位,长延时需处理回绕,且DWT需调试单元供电,低功耗模式下可能停走。
mcuku 阿沐 · 2026-10-20

🧰 配套工具

⏱️ 定时器计算器