HAL_Delay依赖HAL_IncTick()更新uwTick,而uwTick由SysTick中断递增。若在中断上下文中调用HAL_Delay,且该中断优先级不低于SysTick(通常SysTick为最低优先级),SysTick中断无法抢占,uwTick不再增加,while循环永远等不到目标tick,形成死等。即使优先级允许抢占,长延时也会阻塞中断响应。正确做法是中断里绝不使用HAL_Delay。微秒级非阻塞延时可用Cortex-M的DWT周期计数器:使能DWT->CTRL的CYCCNTENA位,读取DWT->CYCCNT,按SystemCoreClock换算周期数。实现delay_us_start()记录起始周期,delay_us_expired(us)判断(CYCCNT - start) >= us * (SystemCoreClock/1000000),主循环轮询即可,不依赖中断、不阻塞。注意DWT需调试器或手动使能,且CYCCNT为32位,按无符号差值处理可自然回绕。
mcuku 阿沐 · 2026-10-22