您当然可以。根据数据表,可以设置看门狗定时器以复位MCU或在触发时引起中断。似乎您对中断可能性更感兴趣。
实际上,WDT实际上比普通定时器更容易设置,原因是它的用处不大:选项更少。它以内部校准的128kHz时钟运行,这意味着其时序不受MCU主时钟速度的影响。它也可以在最深的睡眠模式下继续运行,以提供唤醒源。
我将介绍几个数据表示例以及一些我使用过的代码(在C语言中)。
包含的文件和定义
首先,您可能需要包括以下两个头文件才能正常工作:
#include <avr/wdt.h> // Supplied Watch Dog Timer Macros
#include <avr/sleep.h> // Supplied AVR Sleep Macros
另外,我使用在标准AVR标头之一中定义的宏<_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睡眠
我建议不要在ISR的末尾启用睡眠模式,而不是将MCU置于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
****************************/
}
}