一、問題
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()
函數,這樣系統可以有機會處理看門狗定時器的喂養操作。