Ти, звичайно, можеш. Відповідно до таблиці, таймер сторожової собаки може бути налаштований для скидання MCU або викликати переривання при його спрацюванні. Здається, вас більше цікавить можливість переривання.
Налаштування WDT насправді простіше, ніж звичайний таймер, з тієї ж причини, що менш корисна: менше варіантів. Він працює на внутрішньо каліброваному тактовою частотою 128 кГц, тобто його терміни не впливають на основну тактову частоту MCU. Він також може продовжувати працювати під час найглибших режимів сну, щоб забезпечити джерело пробудження.
Я перегляну кілька прикладів даних, а також якийсь код, який я використав (на С).
Файли та визначення
Для початку ви, ймовірно, захочете включити наступні два файли заголовка для роботи.
#include <avr/wdt.h> // Supplied Watch Dog Timer Macros
#include <avr/sleep.h> // Supplied AVR Sleep Macros
Крім того, я використовую Macro <_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 Interrupt Service
Наступне, про що слід потурбуватися - це обробка WDT 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 спати всередині WDT ISR, я рекомендую просто увімкнути сплячий режим наприкінці 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
****************************/
}
}