Вы наверняка можете. В соответствии с таблицей данных сторожевой таймер может быть настроен на сброс MCU или вызывать прерывание при его срабатывании. Кажется, вас больше интересует возможность прерывания.
WDT на самом деле проще в настройке, чем обычный таймер, по той же причине, по которой он менее полезен: меньше вариантов. Он работает на тактовой частоте 128 кГц, что означает, что его тактовая частота не зависит от основной тактовой частоты MCU. Он также может продолжать работать в самых глубоких режимах сна, чтобы обеспечить источник пробуждения.
Я рассмотрю несколько примеров таблиц, а также некоторый код, который я использовал (на языке C).
Включенные файлы и определения
Для начала, вы, вероятно, захотите включить следующие два заголовочных файла для работы:
#include <avr/wdt.h> // Supplied Watch Dog Timer Macros
#include <avr/sleep.h> // Supplied AVR Sleep Macros
Кроме того, я использую макрос <_BV (BIT)>, который определен в одном из стандартных заголовков AVR следующим образом (который может быть более привычным для вас):
#define _BV(BIT) (1<<BIT)
Начало кода
Когда MCU запускается впервые, вы обычно инициализируете ввод-вывод, настраиваете таймеры и т. Д. Где-то здесь хорошее время, чтобы убедиться, что WDT не вызвал сброс, потому что он мог сделать это снова, сохраняя вашу программу в нестабильная петля.
if(MCUSR & _BV(WDRF)){ // If a reset was caused by the Watchdog Timer...
MCUSR &= ~_BV(WDRF); // Clear the WDT reset flag
WDTCSR |= (_BV(WDCE) | _BV(WDE)); // Enable the WD Change Bit
WDTCSR = 0x00; // Disable the WDT
}
Настройка WDT
Затем, после того, как вы настроите остальную часть чипа, переделайте WDT. Настройка WDT требует «временной последовательности», но это действительно легко сделать ...
// Set up Watch Dog Timer for Inactivity
WDTCSR |= (_BV(WDCE) | _BV(WDE)); // Enable the WD Change Bit
WDTCSR = _BV(WDIE) | // Enable WDT Interrupt
_BV(WDP2) | _BV(WDP1); // Set Timeout to ~1 seconds
Конечно, ваши прерывания должны быть отключены во время этого кода. Обязательно включите их позже!
cli(); // Disable the Interrupts
sei(); // Enable the Interrupts
Программа обработки прерываний WDT
Следующее, о чем нужно беспокоиться, - это обработка WRT ISR. Это сделано так:
ISR(WDT_vect)
{
sleep_disable(); // Disable Sleep on Wakeup
// Your code goes here...
// Whatever needs to happen every 1 second
sleep_enable(); // Enable Sleep Mode
}
MCU Sleep
Вместо того, чтобы переводить MCU в спящий режим внутри ISD WDT, я рекомендую просто включить спящий режим в конце ISR, а затем заставить MAIN-программу перевести MCU в спящий режим. Таким образом, программа фактически покидает ISR до того, как переходит в спящий режим, и она просыпается и возвращается обратно в WDT ISR.
// Enable Sleep Mode for Power Down
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set Sleep Mode: Power Down
sleep_enable(); // Enable Sleep Mode
sei(); // Enable Interrupts
/****************************
* Enter Main Program Loop *
****************************/
for(;;)
{
if (MCUCR & _BV(SE)){ // If Sleep is Enabled...
cli(); // Disable Interrupts
sleep_bod_disable(); // Disable BOD
sei(); // Enable Interrupts
sleep_cpu(); // Go to Sleep
/****************************
* Sleep Until WDT Times Out
* -> Go to WDT ISR
****************************/
}
}