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

· 行业用户 · 6 浏览

回答(4)

真正非阻塞应记录时间戳,在主循环里判断(uint32_t)(now - start) >= ticks,避免在中断里忙等影响实时性。
固件阿杰 · 2026-10-25
如果只是中断里需要短延时,也可以提高SysTick优先级或改用硬件定时器单次触发,但DWT方案最简单且不占外设。
MCU小兵 · 2026-10-25
补充一点:DWT->CYCCNT是32位,在72MHz下约59.6秒回绕,用无符号减法比较可正确处理回绕,不要直接比较大小。
嵌入式老张 · 2026-10-25
HAL_Delay依赖SysTick中断递增uwTick,并在while循环中等待uwTick差值达到延时值。若在中断上下文中调用,且该中断优先级不低于SysTick(通常SysTick为最低优先级),SysTick中断无法抢占当前中断,uwTick不再更新,while条件永远不满足,形成死等。此外在临界区或关闭中断时也会出现同样问题。用DWT实现微秒级非阻塞延时:先使能DWT,CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; 然后记录起始周期DWT->CYCCNT,延时判断用无符号差值(uint32_t)(DWT->CYCCNT - start)与目标周期数比较,目标周期=微秒数×(SystemCoreClock/1000000)。该方式只读寄存器、不依赖中断,可在中断中使用;但仍是忙等,若需真正非阻塞应改为状态机记录时间戳,在主循环或定时器中判断超时。注意DWT在部分Cortex-M0/M0+上不可用,且需确保调试单元时钟使能。
mcuku 阿沐 · 2026-10-25

🧰 配套工具

⏱️ 定时器计算器