Arduino с Atmega328: не могу очистить сторожевой таймер

Я использую встроенный программный сторожевой таймер Atmega328, как описано здесь .
Моя цель — ограничить выполнение части кода двумя секундами, что может привести к бесконечным вычислениям.

Это схема псевдокода:

enable watchdog (2 seconds)
run may-be-endless code
clear watchdog
run the rest

Остальная часть кода должна быть запущена, если код, который может быть бесконечным, успеет выполниться за заданное количество времени, в противном случае необходимо перезапустить всю программу.

Это код Arduino, который я загрузил в плату:

#include <avr/wdt.h>

void setup() {

  Serial.begin(9600);

  Serial.println("Started");

  wdt_enable(WDTO_2S);
  Serial.println("watchdog ON");

  wdt_reset();
  Serial.println("watchdog OFF");

}

void loop(){
  Serial.println("loop...");
  delay(1000);
}

На этом этапе ожидаемым результатом должна быть бесконечная печать loop...сообщений после тех, что указаны в настройках ( Started, watchdog ON/ OFF).

Удивительно, но вместо этого я получаю следующее:

Started
watchdog ON
watchdog OFF
loop...
loop...
loop...
Started
watchdog ON
watchdog OFF
loop...
loop...
loop...
Started
watchdog ON
watchdog OFF
loop...
loop...
[...]

По-видимому, сторожевой таймер устанавливается, но не может быть очищен. Почему?

Ответы (2)

wdt_reset() 

не отключает сторожевой таймер, он просто сбрасывает свой таймер, задерживая истечение срока действия.

Вы, наверное, хотите

wdt_disable()

Тем не менее, ваш общий подход может быть не самым разумным - позволить сторожевому таймеру истечь, может быть умно, но это также довольно тяжело по сравнению с такими подходами, как использование обычного прерывания таймера или ограничение вашего кода. Обычно сторожевой таймер предназначен для непредвиденных ошибок.

Спасибо... Мне стыдно, что я не проверила wdt_disableраньше, это было так просто. Меня отвлекли несколько руководств, которые я прочитал, в которых говорилось, что это wdt_resetтак, а также документация была для меня немного двусмысленной.

Чтобы отключить сторожевой таймер, вызовите wdt_disable() . Все wdt_reset(), что нужно сделать, это сбросить тайм-аут сторожевого таймера, что в вашем случае избыточно: вы просто включаете его двумя строками выше. wdt_reset()не выключает сторожевой таймер (в отличие от вашего серийного вывода).