WATCHDOG定时器简介:
WATCHDOG定时器也可以像一般的16位定时器一样用于产生周期性中断,也可以用于发出复位信号以重启时常的系统。它的结构与PWM很相似,如下图所示:
从上图我们可以发现,WATCHDOG 定时器先经过8位预分频将PCLK分频后,被再次分频得到4种频率,16分频、32分频、64分频、128分频,WATCHDOG 定时器可以通过设置 WTCON[4:3]来决定工作在哪种频率之下,WTCHT 寄存器按照其工作频率减1计数,当达到0时,可以产生中断信号,可以输出复位信号。在第一次使用WATCHDOG 定时器时,需要往WTCNT 寄存器中写入初始计数值,以后在计数值到达0时,自动从WATDAT 寄存器中装入,重新开始下一个计数值。
使用WATCHDOG定时器的“WATCHDOG 功能”时,在正常的程序中,必须不断重新设置WTCNT 寄存器,使之不为0,这样可以保证系统不被重启,这就是所谓的“喂狗”啦。当程序崩溃时不能正常“喂狗”,计数值达到0后系统将被重启,这样程序将重新运行。
有关WATCHDOG 定时器的寄存器只有3个。我们来简单介绍一下:
1、WTCON 寄存器(WATCHDOG TIMER CONTROL)
用于设置分频系数,选择工作频率,决定是否使能中断,是否启用WATDOG 功能(即是否输出复位信号),WATCHDOG 定时器的工作频率可以通过下面这个公式计算:
WATCHDOG 定时器工作频率 = PCLK / {prescaler +1 } / {divider value }
{prescaler value } = 0~255, {divider value} = 16,32,64,128。
2、WTDAT 寄存器(WATCHDOG TIMER DATA)
WTDAT 寄存器被用来决定WATCHDOG 定时器的超时周期,在定时器启动后,当计数达到0时,WTDAT 寄存器的值会自动传入 WTCNT 寄存器。不过,第一次启动WATCHDOG 定时器时,WTDAT 寄存器的值不会自动传入WTNT寄存器,这就需要首先在WTNT装入初值啦。
3、WTCNT 寄存器(WATCHDOG TIMR COUNT)
在启动WATCHDOG 定时器前,必须往WTCNT这个寄存器写入初始计数值。启动定时器后,它减1计数,当计数值达到0时,如果中断被使能的话,就会发出中断请求;如WATCHDOG功能被使能的话,将会发出复位信号,装载 WTDAT寄存器的值并重新计数。
注意:
当使能中断的时候,WATCHDOG定时器中断是有次级中断源的,初始化中断的时候需要格外注意。
————————————————————————————————————————————
下面开始讲解main.c程序:
#include "2440addr.h"
#include "Option.h"
#define LED1_ON (rGPBDAT &=~(1<<5))
#define LED1_OFF (rGPBDAT |=(1<<5) )
#define LED2_ON (rGPBDAT &=~(1<<6))
#define LED2_OFF (rGPBDAT |=(1<<6))
#define LED3_ON (rGPBDAT &=~(1<<7))
#define LED3_OFF (rGPBDAT |=(1<<7))
#define LED4_ON (rGPBDAT &=~(1<<8))
#define LED4_OFF (rGPBDAT |=(1<<8))
void __irq Wdt_Int(void);
void Delay(void)
{
int i;
for(i=0;i<1000000;i++);
}
void Main(void)
{
rGPBCON &=~((3<<10)|(3<<12)|(3<<14)|(3<<16)); //对GPBCON[10:17]清零
rGPBCON |=((1<<10)|(1<<12)|(1<<14)|(1<<16)); //设置GPB5~8为输出
rGPBUP &=~((1<<5)|(1<<6)|(1<<7)|(1<<8)); //设置GPB5~8的上拉功能
rGPBDAT |=(1<<5)|(1<<6)|(1<<7)|(1<<8); //关闭LED
rGPBCON |=1; //输出
rGPBUP |=0;
rGPBDAT|=0; //关闭蜂鸣器
rWTDAT=50000; //设置看门狗定时器超时时间为4秒(50÷12.5)
rWTCNT=50000;
rWTCON=(249<<8)|(1<<5)|(0<<3)|(1<<2);//预分频值为249,使能看门狗,分频系数为16,中断使能
rSRCPND |=BIT_WDT_AC97;
rINTPND |=BIT_WDT_AC97;
rSUBSRCPND |= BIT_SUB_WDT; //清除中断标志
rINTMSK &= ~(BIT_WDT_AC97);
rINTSUBMSK &= ~(BIT_SUB_WDT);//开中断
pISR_WDT_AC97=(unsigned)Wdt_Int;//设置中断程序入口
while(1)
{
LED1_ON;Delay();LED1_OFF;
LED2_ON;Delay();LED2_OFF;
LED3_ON;Delay();LED3_OFF;
LED4_ON;Delay();LED4_OFF;
rWTCNT=50000; //喂狗 没喂狗蜂鸣器很响
}
}
void __irq Wdt_Int(void)
{
rSRCPND |=BIT_WDT_AC97;
rINTPND |=BIT_WDT_AC97;
rSUBSRCPND |= BIT_SUB_WDT; //清除中断标志
rGPBDAT =1;
Delay(); // from 2440lib.c
rGPBDAT =0; //蜂鸣器响一段时间
}
—————————————————————————————————————————————
我们首先来看main函数,进入main函数之后,首先是设置LED1~4对应管脚为输出、使能上拉、关闭全部LED。(前面四句)
接着三句是设置蜂鸣器控制管脚GPB0为输出、使能上拉、关闭蜂鸣器。
我们先来看这句 rWTCON=(249<<8)|(1<<5)|(0<<3)|(1<<2);//预分频值为249,使能看门狗,分频系数为16,中断使能
通过WATCHDOG 定时器工作频率 = PCLK / {prescaler +1 } / {divider value }
{prescaler value } = 0~255, {divider value} = 16,32,64,128。
计算求得WATCHDOG工作频率为12500Hz,即每秒钟计数12500次。
再回头来看看上面那二句就很清楚的知道是定时器4秒的意思啦。
rWTDAT=50000; //设置看门狗定时器超时时间为4秒(50÷12.5)
rWTCNT=50000;
接下来是清除中断标志,注意WATCHDOG是有次级中断源的,所以需要清除二个中断挂起寄存器。
rSRCPND |=BIT_WDT_AC97;
rINTPND |=BIT_WDT_AC97;
rSUBSRCPND |= BIT_SUB_WDT; //清除中断标志
接下来是打开中断,也是打开二个中断允许寄存器。
rINTMSK &= ~(BIT_WDT_AC97);
rINTSUBMSK &= ~(BIT_SUB_WDT);//开中断
接下来是设置中断的起始地址,将中断服务程序的起始地址映射到内存。
pISR_WDT_AC97=(unsigned)Wdt_Int;//设置中断程序入口
我们进入中断服务程序看看:
——————————————————————————————————————————————
void __irq Wdt_Int(void)
{
rSRCPND |=BIT_WDT_AC97;
rINTPND |=BIT_WDT_AC97;
rSUBSRCPND |= BIT_SUB_WDT; //清除中断标志
rGPBDAT =1; //蜂鸣器响
Delay();
rGPBDAT =0; //蜂鸣器响一段时间
}
——————————————————————————————————————————————
进入中断服务程序后,首先清楚中断标志,接着让蜂鸣器响一下,接着关闭。
最后进入死循环,前面四句是循环点亮LED灯,接着重新赋值给WTCNT,实现喂狗功能。
rWTCNT=50000; //喂狗 没喂狗蜂鸣器很响
——————————————————————————————————————————————
到这里,我们WATCHDOG 定时器的讲解结束啦。