定时中断进不来?别只怪 Prescaler,看看 Counter Mode
摘要TIM 配置 1ms 中断示波器测出来却是 1.024ms或者中断偶尔丢失不是 SystemCoreClock 算错而是Counter Mode计数模式 与Center-Aligned中心对齐 配置导致的隐性误差。本文还原 TIM 中断的真实时序。一、问题描述现象**TIM 配置 1ms 进一次中断用 IO 翻转测周期发现有时 1ms有时 2ms或者在主循环中加了一句延时中断就不准了。**很多工程师的排查方向是SystemCoreClock不对Prescaler算错了中断里代码太多二、原理分析1. 物理模型TIM 中断触发链CLK - PSC - CNT - ARR - Update Event - IRQ2. 核心参数Prescaler (PSC)预分频器。ARR自动重装值。Counter Mode向上 / 向下 / 中心对齐。3. 反直觉真相“向上计数”和“中心对齐”的 ARR 含义完全不同。Up Counting向上CNT 从 0 数到 ARR溢出产生中断。实际周期 (ARR 1)个计数周期。Center-Aligned中心对齐CNT 从 0 → ARR → 0。实际周期 (2 × ARR)个计数周期。如果你把 Center-Aligned 当 Up 来配定时直接翻倍。三、工程级解决方案方案 1标准 1ms 定时配置STM32 72MHz向上计数模式最常用// 72MHz / 72 1MHz (1us) htim.Init.Prescaler 72 - 1; // 1000 次 1ms htim.Init.Period 1000 - 1; htim.Init.CounterMode TIM_COUNTERMODE_UP; HAL_TIM_Base_Init(htim);方案 2避免中断里“堵车”不要在 TIM 中断里做这些事printfHAL_Delay复杂运算正确做法void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { // 只做标记 g_tim_flag 1; }方案 3Center-Aligned 的正确打开方式如果必须用中心对齐如 PWM 对称输出htim.Init.CounterMode TIM_COUNTERMODE_CENTERALIGNED1; htim.Init.Period 500 - 1; // 注意ARR 要减半四、选型避坑建议HAL 库的坑__HAL_TIM_SET_AUTORELOAD()默认不生成 Update 事件可能导致第一次中断延迟。优先级TIM 中断优先级不要设太低防止被 SPI/DMA 长时间抢占。不要在中断里清 UIFHAL 会自动清手动清可能会丢失下一次中断。五、总结 Checklist[ ] 是否确认了 Counter ModeUp / Center[ ] 向上计数时ARR 是否减了 1[ ] 中断里是否只做了轻量级操作[ ] 是否避免了在中断中使用 HAL_Delay六、写在最后关注我少走弯路我是 gqqsherry一个拒绝调包、专注底层逻辑的嵌入式工程师。TIM 是基础中的基础但越是基础的东西坑往往越隐蔽。关注我的专栏《嵌入式底层避坑指南》至此《TIM 底层避坑指南》系列正式完结。接下来我们将开启《电源管理底层避坑指南》。新系列预告《LDO 啸叫怎么来的别只换电容看看环路稳定性与 ESR》原创文章转载请注明出处。