Lo más seguro es que puedas. De acuerdo con la hoja de datos, el temporizador de vigilancia puede configurarse para restablecer la MCU o provocar una interrupción cuando se dispara. Parece que estás más interesado en la posibilidad de interrupción.
El WDT es realmente más fácil de configurar que un temporizador normal por la misma razón que es menos útil: menos opciones. Se ejecuta en un reloj de 128 kHz calibrado internamente, lo que significa que su tiempo no se ve afectado por la velocidad del reloj principal de la MCU. También puede continuar ejecutándose durante los modos de suspensión más profundos para proporcionar una fuente de activación.
Voy a repasar un par de ejemplos de hojas de datos, así como algunos códigos que he usado (en C).
Archivos y definiciones incluidos
Para comenzar, es probable que desees incluir los siguientes dos archivos de encabezado para que las cosas funcionen:
#include <avr/wdt.h> // Supplied Watch Dog Timer Macros
#include <avr/sleep.h> // Supplied AVR Sleep Macros
También utilizo la macro < _BV (BIT) > que se define en uno de los encabezados estándar de AVR como los siguientes (que pueden ser más familiares para usted):
#define _BV(BIT) (1<<BIT)
Comienzo del código
Cuando se inicia por primera vez la MCU, normalmente se inicializa la E / S, se configuran los temporizadores, etc. En algún lugar aquí es un buen momento para asegurarse de que el WDT no causó un restablecimiento porque podría hacerlo nuevamente, manteniendo su programa en un bucle inestable.
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
}
Configuración de WDT
Luego, una vez que haya configurado el resto del chip, vuelva a hacer el WDT. La configuración de WDT requiere una "secuencia programada", pero es muy fácil de hacer ...
// 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
Por supuesto, sus interrupciones deben estar deshabilitadas durante este código. ¡Asegúrate de volver a habilitarlos después!
cli(); // Disable the Interrupts
sei(); // Enable the Interrupts
Rutina de servicio de interrupción de WDT
Lo siguiente de lo que preocuparse es el manejo del ISR de WDT. Esto se hace como tal:
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
En lugar de poner la MCU en reposo dentro del ISR de WDT, recomiendo simplemente habilitar el modo de suspensión al final de la ISR, luego hacer que el programa PRINCIPAL ponga a la MCU en suspensión. De esa manera, el programa en realidad está dejando el ISR antes de irse a dormir, y se activará y regresará directamente al ISR de WDT.
// 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
****************************/
}
}