一、问题
Arduino 程序使用<Ticker.h>包时,使用不当情况下,会导致“看门狗WDT超时”
1.1问题控制台报错
在串口监视器显示
--------------- CUT HERE FOR EXCEPTION DECODER ---------------Soft WDT resetException (4):
epc1=0x402077cb epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000>>>stack>>>ctx: sys
sp: 3fffed40 end: 3fffffb0 offset: 0160
3fffeea0: 3ffeeab0 00001946 0000003d 40207921
3fffeeb0: 00001946 000003e8 0000159b 40207996
出现这种串口输出(即 Soft WDT reset 错误)通常表示你的代码遇到了看门狗定时器(WDT)超时。具体原因是代码运行中有一段时间没有及时喂给看门狗定时器,导致系统认为程序卡住了并重启。
在 ESP8266 或 ESP32 这类使用看门狗定时器的设备中,看门狗定时器用于监控程序是否在执行时挂起。如果程序在一定时间内没有重置(喂)看门狗,系统会认为程序出了问题并触发重启。
1.2问题代码
#include <Ticker.h>Ticker ticker;void setup() {
pinMode(LED_BUILTIN, OUTPUT);//串口-------------------------------------------------bool openSerial = true; // 串口开启if (openSerial) {Serial.begin(115200); // 设置波特率为115200}ticker.attach_ms(10, control); // 10毫秒执行一次
}// 控制状态
void control() {if (ledFlag == 0) {digitalWrite(LED_BUILTIN, LOW); // LED设置为低电平} else {digitalWrite(LED_BUILTIN, HIGH); // LED设置为高电平}ledFlag = !ledFlag; // 切换ledFlag的值delay(1000); // 延时1秒钟
}
1.3错误发现
delay(1000); // 延时1秒钟
错误就在control方法的 delay函数。
ticker.attach_ms(10, control); // 10毫秒执行一次
定时器在实现每10毫秒调用control方法,但是control方法中由存在delay延迟。导致长时间的阻塞代码: 如果程序在某个操作中执行了很长时间(如等待某个外设响应,或者进行复杂的运算),而没有调用 yield()
或 delay()
等函数来让系统有机会喂看门狗定时器,这就可能导致看门狗超时并重启系统。
二、解决
#include <Ticker.h>volatile int ledFlag = 0;void setup() {pinMode(LED_BUILTIN, OUTPUT);//串口-------------------------------------------------bool openSerial = true; // 🍄改改改 根据需要设置是否开启串口if (openSerial) {Serial.begin(115200); // 设置波特率为115200}ticker.attach_ms(1000, control); // 10毫秒执行一次,1秒 1000
}// 控制状态
void control() {if (ledFlag == 0) {digitalWrite(LED_BUILTIN, LOW); // LED设置为低电平} else {digitalWrite(LED_BUILTIN, HIGH); // LED设置为高电平}ledFlag = !ledFlag; // 切换ledFlag的值
}
2.1取消delay()
volatile int ledFlag = 0;
使用易变数据类型参数。取消delay函数。用外部的ticker直接实现定时,不要再定时中再延时。再control方法中将ledFlag取异即可。
三、总结
看门狗超时引起的系统重启,通常是由于代码中存在长时间阻塞操作,或者没有及时喂看门狗导致的。你可以通过优化代码执行的时间,或定期调用 yield()
或 delay()
来防止这个问题发生。
适当使用 yield()
或 delay()
: 如果你的代码执行时间较长,可以在适当的地方调用 yield()
或 delay()
函数,这样系统可以有机会处理看门狗定时器的喂养操作。