您现在的位置是:网站首页> 硬件

Arduino使用watchdog方法

  • 硬件
  • 2021-03-27
  • 955人已阅读
摘要

bug修补者-watchdog

最近在自己的一个Arduino项目中发现了一个很奇怪的异常,系统开机一段时间后出现死机,死机出现的时间和触发原因看起来似乎没有任何规律,检查程序也找不到任何错误,同时因为死机出现的随机性,也很难进行调试。问题可能是程序中的一些隐藏bug,或者与硬件有关,但无论如何,一直没有找到确切原因。因此在其中加入watchdog作为一种修补,至少每次出现异常后系统可以自动复位总比一直卡在那好。


Arduino的WDT

Arduino的语法参考中没有包括WDT,但相关开发板的atmega系列单片机的数据手册均显示是支持wdt的,同时因为Arduino IDE本身是基于AVR GCC编译器,因此可以直接在Arduino IDE中使用AVR的原生语句与函数库。需要包含头文件#include <avr/wdt.h>。可以参考avr的详细库函数说明

avr的WDT 的基本功能语句有三个:

  • WDT使能定时间隔设置wdt_enable(),参数可以从几十ms到几s之间调整,当超过这个时间而单片机又没有复位WDT定时器时,单片机就会进行复位操作,一般来说不要设置过低的时间间隔。
  • WDT禁用语句wdt_disable(),为防止再次烧写程序时复位后反复进入
    wdt复位,需要在初始化程序的最开始位置禁用wdt,这在wdt定时间隔设置过短时尤为重要,否则可能会导致无法再次烧写。
  • WDT定时器复位语句wdt_reset(),如果在WDT的定时间隔内没有使用该语句复位定时器,则WDT会自动复位单片机,该语句的位置根据具体程序的耗时决定,可能需要多处加入。

下面给出了一个wdt的测试程序,主循环内的led闪烁频率会越来越慢,当闪烁间隔超过wdt定时后,会触发wdt复位,在setup()中led快速闪烁三次以标志进入复位。

#include <avr/wdt.h>

const int onboardLED = 13; 


void setup() {

 wdt_disable();  //disable wdt at the first of code to prevent it always reboot


  //the WDT time can be choose from

  //WDTO_25MS  WDTO_30MS  WDTO_60MS  WDTO_250MS  WDTO_500MS

  //WDTO_1S  WDTO_3S  WDTO_4S  WDTO_8S

  //be very carfully when use too short time value because  most avr's WDT still on work even after reboot

  wdt_enable(WDTO_4S);


  pinMode(onboardLED, OUTPUT);


  for (int k = 1; k <= 10; k = k + 1) {

    digitalWrite(onboardLED, HIGH);

    delay(50);

    digitalWrite(onboardLED, LOW);

    delay(50);

  }

  delay(750L);

}


void loop() {

  for (int k = 1; k <= 10000; k = k + 1) {

     wdt_reset();  //reset the watchdog timer every loop to prevent reboot

    digitalWrite(onboardLED, HIGH);

    delay(k * 250L);

    digitalWrite(onboardLED, LOW);

    delay(250L);

  }

}

bootloader 与WDT冲突解决

用上面的代码实际测试中发现当自己用的arduino产生触发wdt复位的条件时,单片机并没有复位而是直接卡死,指示灯快速闪烁或者无反应。且再次烧写程序时出现了问题,强制上电复位才成功。查阅了一些资料后可能原因在于旧版本的arduino的bootloader与wdt间有冲突。
我拿来一块新买的mega2560测试了同样的程序,发现果然可以正常使用wdt。于是我又用avr的usb asp烧写器烧写了新版本的bootloader进我的旧的arduino中,结果显示mega2560使用新的bootloader后可以正常工作,但pro mini仍然无法正常工作。关于如何烧写bootloader已经超过了本篇的范围,请参考我的另外一篇博客Arduino烧写bootloader





Top