如何在Microchip Studio中不中断主循环,5分钟后调用restart()?
解决方案:非阻塞式5分钟重启实现(基于Microchip Studio单片机开发)
核心思路
单片机主循环的执行周期不固定,靠循环计数或阻塞delay的方法都不可靠。最稳妥的方式是利用硬件定时器中断实现精准定时,同时保证主循环不被阻塞,剩余代码能正常执行。
具体实现步骤
1. 全局变量定义
需要几个全局变量维护定时状态:
#include <avr/io.h> #include <avr/interrupt.h> // 全局毫秒计数器,由定时器中断更新 volatile uint32_t system_ms = 0; // 记录ErrorFlag置位时的时间点 volatile uint32_t error_trigger_time = 0; // 标记是否已启动错误定时(避免重复记录时间) volatile uint8_t error_timer_started = 0; // 你的错误标志位 uint8_t ErrorFlag = 0;
注意:涉及中断修改的变量必须加
volatile关键字,防止编译器优化导致值异常。
2. 硬件定时器初始化
以AVR系列单片机的Timer0为例(适配Microchip Studio环境),配置为1ms触发一次中断:
void timer_init(void) { // 设置Timer0为CTC(清除定时器比较匹配)模式 TCCR0A = (1 << WGM01); // 设置预分频系数为64,时钟源为系统时钟 TCCR0B = (1 << CS01) | (1 << CS00); // 设置比较值:假设系统时钟为16MHz,1ms需要计数250次(16000000/64/1000=250) // 由于计数器从0开始,所以比较值设为249 OCR0A = 249; // 启用Timer0比较匹配A中断 TIMSK0 = (1 << OCIE0A); // 开启全局中断 sei(); } // Timer0比较匹配中断服务函数,每1ms执行一次 ISR(TIMER0_COMPA_vect) { system_ms++; // 毫秒计数器自增 }
3. 主循环逻辑修改
主循环中仅做状态检查和计时判断,完全不阻塞:
int main(void) { timer_init(); // 初始化定时器 while(1) { if (ErrorFlag == 1) { if (!error_timer_started) { // 首次检测到错误,记录当前时间点 error_trigger_time = system_ms; error_timer_started = 1; } // 检查是否已达到5分钟(300000毫秒) if (system_ms - error_trigger_time >= 300000) { restart(); // 调用重启函数 // 重置状态,避免重复触发 ErrorFlag = 0; error_timer_started = 0; } } else { // 错误标志清除时,重置定时状态 error_timer_started = 0; } // 剩余代码:这里的逻辑会正常执行,不受定时逻辑影响 // ... } } // 示例重启函数(可根据实际需求修改) void restart(void) { // 比如通过看门狗实现硬件复位 WDTCR = (1 << WDE) | (1 << WDTOE); // 允许修改看门狗设置 // 设置看门狗超时为2秒,触发复位 WDTCR = (1 << WDE) | (1 << WDP3) | (1 << WDP0); while(1); // 等待看门狗复位 }
方案优势
- 定时精准:硬件定时器不受主循环执行速度影响,能保证5分钟的定时精度
- 非阻塞:主循环始终能正常执行剩余代码,不会被delay或嵌套循环卡住
- 状态可控:错误标志清除时自动重置定时状态,避免误触发
内容的提问来源于stack exchange,提问作者Dominik
相关产品推荐
相关产品推荐

