看门狗定时器的主要作用是在程序因为干扰而跑飞后,能够使系统复位,不至于使系统永远的死下去。
它的原理与一般的定时器没有多大区别,就是先要设置好一段时间,当超过这段时间后,就从当前运行的程序中跳出进入中断处理程序中。但两者的主要差别是,一般的定时器中断是我们希望它发生的,因此我们不会在定时器中断发生前的那个时间段内干预它;而看门狗定时器中断是我们不希望它发生的,因此我们要想方设法地避免其发生。主要的方法就是在中断发生前,重新对看门狗定时器的寄存器进行赋值,使它的定时器重新开始计时。这种方法俗称喂狗,形象地比喻就是一条看门狗每隔一段时间(比如说一个小时)就会饿,所以就要叫唤,唯一使它不叫的方法就是给它喂食,那么下次叫唤的时间就是从当前喂食起的一个小时后。因此只要在上次喂食后的一个小时内再给它喂食,它就永远不会叫唤。
s3c2440的看门狗定时器不仅可以引起系统复位,还可以引起一般的中断,因此s3c2440的看门狗定时器可以当作一般的定时器使用。
s3c2440看门狗定时器的时钟频率的公式为:
PCLK÷(Prescaler + 1)÷Division
其中Prescaler的取值范围为0~255,Division的取值为16,32,64和128。例如,当PCLK为50MHz时,设置Prescaler为249,Division为16,则看门狗定时器的时钟频率为12.5kHz。这两个参数由寄存器WTCON提供,除此以外,该寄存器还可以设置是否有效看门狗定时器的超时复位,是否有效看门狗定时器的超时中断等。看门狗定时器还有两个寄存器WTDAT和WTCNT,WTDAT用于确定超时期限,WTCNT为当前看门狗定时器的计数值,在第一次设置看门狗超时时间时,这两个寄存器都要被写入超时时间的初始值。当要启动超时中断时,还要设置必要的中断寄存器,
下面这个程序就是一个看门狗定时器的实例。该程序就是正常的跑马灯程序,但加了一个看门狗定时器。我们设置的看门狗定时器超时时,只会触发中断,不会引起系统复位。在中断函数内,蜂鸣器会响。我们设置看门狗定时器的超时期限为4秒,为了不让程序进入看门狗中断,必须在该期限内,往寄存器WTCNT内写数,迫使看门狗定时器重新开始计时。
#define _ISR_STARTADDRESS 0x33ffff00
#define pISR_WDT_AC97 (*(unsigned *)(_ISR_STARTADDRESS+0x44))
#define U32 unsigned int
#define rGPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define rGPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define rGPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
#define rSRCPND (*(volatile unsigned *)0x4a000000) //Interrupt request status
#define rINTMSK (*(volatile unsigned *)0x4a000008) //Interrupt mask control
#define rINTPND (*(volatile unsigned *)0x4a000010) //Interrupt request status
#define rSUBSRCPND (*(volatile unsigned *)0x4a000018) //Sub source pending
#define rINTSUBMSK (*(volatile unsigned *)0x4a00001c) //Interrupt sub mask
#define rWTCON (*(volatile unsigned *)0x53000000) //Watch-dog timer mode
#define rWTDAT (*(volatile unsigned *)0x53000004) //Watch-dog timer data
#define rWTCNT (*(volatile unsigned *)0x53000008) //Eatch-dog timer count
void delay(int a)
{
int k;
;
}
void __irq watchdog(void)
{
rGPBDAT |= 1; //蜂鸣器响
//清中断标志位
rSRCPND = 0x1<<9;
rSUBSRCPND = 0x1<<13;
rINTPND = 0x1<<9;
}
void Main(void)
{
int light;
int temp;
int i;
rGPBCON = 0x015551; //B0输出,给蜂鸣器;B5~B8输出,给LED
rGPBUP = 0x7ff;
rWTCON = 0xf9<<8; //Prescaler = 249,Division = 16,时钟频率为12.5kHz
//禁止看门狗复位
rWTDAT = 50000; //设置看门狗定时器超时时间为4秒(50÷12.5)
rWTCNT = 50000;
rWTCON |= (1<<5)|(1<<2); //开启看门狗定时器中断
rSRCPND = 0x1<<9;
rSUBSRCPND = 0x1<<13;
rINTPND = 0x1<<9;
rINTSUBMSK = ~(0x1<<13); //打开中断子屏蔽
rINTMSK = ~(0x1<<9); //打开中断屏蔽
pISR_WDT_AC97 = (U32)watchdog;
light = 0x10;
light = light<<1;
temp = light | 1;
rGPBDAT = ~temp;
delay(500000);
while(1)
{
for (i=0;i<3;i++)
{
light = light<<1;
temp = light | 1;
rGPBDAT = ~temp;
delay(500000);
}
rWTCNT = 50000; //喂狗,重新赋值,防止中断
for (i=0;i<3;i++)
{
light = light>>1;
temp = light | 1;
rGPBDAT = ~temp;
delay(500000);
}
}
}
如果我们把程序中红色的那条语句注释掉,则看门狗定时器可以被看成是一个一般的定时器,即每隔4秒钟,蜂鸣器会响一下。如果我们使能看门狗定时器超时复位,则一定要加上这一句,否则系统会每隔4秒钟复位一次。