Arduino 上实现高精度软件定时器,如何避免 millis() 溢出与中断冲突?

· 1 浏览

回答(4)

补充:对纳秒级需求,直接操作AVR的TCNT1寄存器,但注意与millis()共用Timer0,需禁用其溢出中断,否则冲突。
硬件极客李工 · 2026-08-27
补充:若中断频繁,建议将时间戳读取放在主循环,ISR只置标志位,主循环统一处理,减少临界区长度。
嵌入式小张 · 2026-08-27
补充:用`millis()`差值判断时,记得用`const uint32_t interval`避免符号比较陷阱,且interval应小于2^31,否则比较逻辑会出错。
码农老王 · 2026-08-27
核心方案:用无符号32位减法处理溢出,即`(uint32_t)(millis() - lastTime) >= interval`,这天然规避溢出问题(因为无符号回绕是定义行为)。避免中断冲突的关键是:1) 在ISR中绝不调用millis()(它依赖定时器中断,嵌套会死锁),改用微秒级`micros()`或直接读TCNT寄存器;2) 若必须用millis(),在ISR中先关中断(cli())读取,再恢复(sei()),但会引入抖动;3) 高精度场景建议用Timer1的CTC模式(16位定时器)配合比较匹配中断,精度达微秒级,且不占用millis()的Timer0。实操建议:将定时器逻辑封装为类,用`volatile uint32_t`存储时间戳,并在主循环中非阻塞检查。若需多定时器,用链表或数组管理,避免在ISR中做复杂运算。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

⏱️ 定时器计算器