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

· 6 浏览

回答(5)

中断里做微秒级精确延时优先用NOP循环或定时器单次触发,DWT适合做时间戳测量而非长等待。
硬件工程师阿伟 · 2026-10-17
使能DWT前要开调试跟踪,且CYCCNT在调试器暂停时可能停走,量产代码别依赖调试器行为。
CortexM · 2026-10-17
注意Cortex-M0/M0+无DWT CYCCNT,只有M3/M4/M7等可用;移植前先查内核手册。
MCU小兵 · 2026-10-17
DWT延时不依赖SysTick,但仍是忙等;长延时或低功耗场景应改用硬件定时器+状态机,避免阻塞中断。
嵌入式老张 · 2026-10-17
HAL_Delay基于HAL_GetTick()轮询,依赖SysTick中断递增uwTick。若在中断上下文中调用,且该中断优先级不低于SysTick(或SysTick被屏蔽),uwTick不再更新,while循环永远等不到目标tick,形成死等。正确做法:中断里绝不用HAL_Delay,改用DWT周期计数器做非阻塞延时。实现:使能DWT,CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT=0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk。微秒延时用DWT->CYCCNT差值判断:uint32_t start=DWT->CYCCNT; uint32_t ticks=us*(SystemCoreClock/1000000); while((DWT->CYCCNT-start)<ticks); 注意CYCCNT为32位,SystemCoreClock=72MHz时约59.6s回绕,短延时安全。若要真正非阻塞,应记录起始周期,在状态机或定时器回调中比较差值是否到达,而不是原地while。DWT不受中断屏蔽影响,适合中断和临界区。
mcuku 阿沐 · 2026-10-17

🧰 配套工具

⏱️ 定时器计算器