間違いなくできます。データシートによると、ウォッチドッグタイマーをセットアップして、MCUをリセットするか、トリガー時に割り込みを発生させることができます。割り込みの可能性に興味があるようです。
実際には、WDTはあまり有用ではない同じ理由で、通常のタイマーよりもセットアップが簡単です。つまり、オプションが少なくなります。内部で較正された128kHzクロックで動作します。つまり、そのタイミングはMCUのメインクロック速度の影響を受けません。また、最も深いスリープモード中も実行を継続して、ウェイクアップソースを提供できます。
いくつかのデータシートの例と、(Cで)使用したいくつかのコードについて説明します。
含まれるファイルと定義
まず、動作するように次の2つのヘッダーファイルを含める必要があります。
#include <avr/wdt.h> // Supplied Watch Dog Timer Macros
#include <avr/sleep.h> // Supplied AVR Sleep Macros
また、標準のAVRヘッダーの1つで次のように定義されているマクロ<_BV(BIT)>を使用します(これはより家族的なものかもしれません)。
#define _BV(BIT) (1<<BIT)
コードの始まり
MCUを最初に起動するとき、通常はI / Oの初期化、タイマーのセットアップなどを行います。ここで、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割り込みサービスルーチン
次に心配することは、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スリープ
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
****************************/
}
}