看门狗电路的应用,使微控制器可以在无人状态下实现连续工作,其工作原理是:看门狗芯片和微控制器的一个I/O引脚相连,并定时地往看门狗的这个引脚上送入高电平(或低电平),这一程序语句是分散地放在微控制器其他控制语句中间的,一旦微控制器由于干扰造成程序跑飞后而陷入某一程序段进入死循环状态时,写看门狗引脚的程序便不能被执行,这个时候,看门狗电路就会由于得不到微控制器送来的信号,便在它和微控制看门狗器复位引脚相连的引脚上送出一个复位信号,使微控制器发生复位,即程序从程序存储器的起始位置开始执行,这样便实现了微控制器的自动复位。
在以前传统的8051往往没有内置看门狗,都是需要外置看门狗的,例如常用的看门狗芯片有Max813、5045、IMP706、DS1232。
例如芯片DS1232在系统工作时如下图,必须不间断的给引脚|ST输入一个脉冲系列,这个脉冲的时间间隔由引脚TD设定,如果脉冲间隔大于引脚TD的设定值,芯片将输出一个复位脉冲使微控制器复位。一般将这个功能称为看门狗,将输入给看门狗的一系列脉冲称为“喂狗”。这个功能可以防止微控制器系统死机。
特征
? 18位的向上看门狗定时器可满足用户溢出时间间隔要求。
? 溢出时间间隔(24 ~218)个WDT_CLK时钟周期可选,如WDT_CLK = 10 kHz,那么溢出时间间隔是1.6 ms ~ 26.214s。
? 系统复位保持时间(1/WDT_CLK)*63 。
? 支持看门狗定时器复位延时周期, 包括 1026、130、18 或 3 个WDT_CLK的复位延时时间。
? 通过设置CONFIG0中CWDTEN[2:0]位为1,支持芯片上电或复位条件下看门狗强制打开。
? 如果时钟源选择内部低速10k时钟或LXT时钟,支持看门狗定时器溢出唤醒。
虽然看门狗的好处是很多,但是其成本制约着是否使用外置看门狗抉择。不过幸运的是,现在很多微控制器都内置看门狗,例如AVR、PIC、ARM,当然现在的M451系列微控制器也不例外,其已经内置了看门狗,而且基本上满足了项目的需要。
Demo:
使能看门狗超时中断和超时唤醒中断,设计程序让看门狗产生3次超时中断进行喂狗,3 次过后则不执行喂狗,让系统复位
-
#include "stdio.h"
-
#include "M451Series.h"
-
#include "Common.h"
-
#include "Typedef.h"
-
-
#include "wdt.h"
-
-
/*-------------------------------------------------------*/
-
/* 全局变量 */
-
/*-------------------------------------------------------*/
-
EXTERN_C INT32 IsDebugFifoEmpty(VOID);
-
VOLATILE UINT32 g_unWDTINTCounts;
-
VOLATILE UINT8 g_bIsWDTWakeupINT;
-
-
INT32 main(VOID)
-
{
-
-
PROTECT_REG
-
(
-
/* 系统时钟初始化 */
-
SYS_Init(PLL_CLOCK);
-
-
/* 使能看门狗时钟 */
-
CLK_EnableModuleClock(WDT_MODULE);
-
-
/* 看门狗时钟源为内部低速10KHzRC*/
-
CLK_SetModuleClock(WDT_MODULE, CLK_CLKSEL1_WDTSEL_LIRC, 0);
-
-
/* 串口0初始化波特率为115200bps */
-
UART0_Init(115200);
-
)
-
-
-
printf("+----------------------------------------+\n");
-
printf("| WDT Time-out Wake-up Sample Code |\n");
-
printf("+----------------------------------------+\n\n");
-
-
/* 检查复位是否看门狗复位导致 */
-
if(WDT_GET_RESET_FLAG() == 1)
-
{
-
WDT_CLEAR_RESET_FLAG();
-
printf("*** System has been reset by WDT time-out event ***\n\n");
-
while(1);
-
}
-
-
/* 使能看门狗NVIC中断 */
-
NVIC_EnableIRQ(WDT_IRQn);
-
-
/* 受保护的寄存器都进行解锁 */
-
SYS_UnlockReg(); //看门狗设置需要 UnlockReg.
-
-
g_unWDTINTCounts = g_bIsWDTWakeupINT = 0;
-
-
/* 设置看门狗超时时间为2^14次方看门狗时钟周期,看门狗延迟复位为18个看门狗时钟周期,启动看门狗计数 */
-
WDT_Open(WDT_TIMEOUT_2POW14, WDT_RESET_DELAY_18CLK, TRUE, TRUE);
-
2^14=16,384, 时钟为 10KHz, 那么相当于 1.6秒 WDT超时中断一次.
-
-
/* 使能看门狗触发中断 */
-
WDT_EnableInt();
-
-
while(1)
-
{
-
/* 系统进入掉电模式前必须对受保护的寄存器进行解锁,因为改写PWRCTL寄存器需要对其解锁 */
-
SYS_UnlockReg();
-
-
printf("\nSystem enter to power-down mode ...\n");
-
-
/* 检查是否所有打印信息已经结束 */
-
while(IsDebugFifoEmpty() == 0);
-
-
/* 系统进入掉电模式 */
-
CLK_PowerDown();
-
-
/* 检查当前看门狗是否触发了超时中断和唤醒中断 */
-
while(g_bIsWDTWakeupINT == 0);
-
-
g_bIsWDTWakeupINT = 0;
-
-
/* 打印当前看门狗触发中断的次数 */
-
printf("System has been waken up done. WDT interrupt counts: %d.\n\n", g_unWDTINTCounts);
-
}
-
}
-
-
-
/*-------------------------------------------------------*/
-
/* 中断服务函数 */
-
/*-------------------------------------------------------*/
-
VOID WDT_IRQHandler(VOID)
-
{
-
if(g_unWDTINTCounts < 3)
-
{
-
/* 看门狗复位计数值亦即喂狗 */
-
WDT_RESET_COUNTER();
-
}
-
-
/* 检查当前看门狗触发的中断是否超时中断 */
-
if(WDT_GET_TIMEOUT_INT_FLAG() == 1)
-
{
-
/* 清除看门狗超时中断标志位 */
-
WDT_CLEAR_TIMEOUT_INT_FLAG();
-
-
g_unWDTINTCounts++;
-
}
-
-
/* 检查当前看门狗触发的中断是否超时唤醒中断 */
-
if(WDT_GET_TIMEOUT_WAKEUP_FLAG() == 1)
-
{
-
/* 清除看门狗超时唤醒中断标志位 */
-
WDT_CLEAR_TIMEOUT_WAKEUP_FLAG();
-
-
g_bIsWDTWakeupINT = 1;
-
}
- }