Vous le pouvez très certainement. Selon la fiche technique, le temporisateur de surveillance peut être configuré pour réinitialiser le MCU ou provoquer une interruption lors de son déclenchement. Il semble que vous soyez plus intéressé par la possibilité d'interruption.
Le WDT est en fait plus facile à configurer qu'un minuteur normal pour la même raison qu'il est moins utile: moins d'options. Il fonctionne sur une horloge de 128 kHz calibrée en interne, ce qui signifie que sa synchronisation n'est pas affectée par la vitesse d'horloge principale du MCU. Il peut également continuer à fonctionner pendant les modes de sommeil les plus profonds pour fournir une source de réveil.
Je vais passer en revue quelques exemples de fiches techniques ainsi que du code que j'ai utilisé (en C).
Fichiers et définitions inclus
Pour commencer, vous souhaiterez probablement inclure les deux fichiers d'en-tête suivants pour que les choses fonctionnent:
#include <avr/wdt.h> // Supplied Watch Dog Timer Macros
#include <avr/sleep.h> // Supplied AVR Sleep Macros
En outre, j'utilise la macro <_BV (BIT)> qui est définie dans l'un des en-têtes AVR standard comme suit (qui pourrait être plus familiale pour vous):
#define _BV(BIT) (1<<BIT)
Début du code
Lorsque le MCU est démarré pour la première fois, vous initialisez généralement les E / S, configurez des temporisateurs, etc. une boucle instable.
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
}
Configuration WDT
Ensuite, après avoir configuré le reste de la puce, refaites le WDT. La configuration du WDT nécessite une "séquence chronométrée", mais c'est vraiment facile à faire ...
// 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
Bien sûr, vos interruptions doivent être désactivées pendant ce code. Assurez-vous de les réactiver par la suite!
cli(); // Disable the Interrupts
sei(); // Enable the Interrupts
Routine de service d'interruption WDT
La prochaine chose dont vous devez vous soucier est la manipulation de l'ISR WDT. Cela se fait comme tel:
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
}
Veille MCU
Plutôt que de mettre le MCU en veille à l'intérieur du WDT ISR, je recommande simplement d'activer le mode veille à la fin de l'ISR, puis de laisser le programme MAIN mettre le MCU en veille. De cette façon, le programme quitte réellement l'ISR avant de s'endormir, et il se réveillera et retournera directement dans l'ISR 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
****************************/
}
}