以前做项目时用到看门狗,在使用时遇到一些问题,现在写下来和大家分享:
用到的芯片是LPC2292,内置有看门狗功能。
/****************************************************************************
* 名称:WdtFeed()
* 功能:喂狗
* 说明:
****************************************************************************/
void WdtFeed(void)
{
WDFEED = 0xAA;
WDFEED = 0x55;
}
/****************************************************************************
* 名称:WdtInit()
* 功能:启动看门狗
* 说明:
****************************************************************************/
void WdtInit(void)
{
WDTC = 0x500000;
WDMOD= 0x03;
}
在程序中的一些关键处进行喂狗,结果发现程序不能正常运行,经过排错发现原来是主程序中的喂狗函数影响。
WdtInit(); //使能看门狗
...
while(1)
{//1
WdtFeed();//喂狗
if( )
{
Test();
}
else if()
{
Sleep();
}
else if()
{
Wakeup();
}
else if()
{
SelfTest();
...
}
ARM模块程序的基本框架是通过while(1)死循环等待外部中断,中断来临后接收上级模块传送来的数据,并对其进行解码。于是上网尝试查找答案。发现一个帖子对这个问题进行解答。他的答案如下:
"在周立功的<<ARM微控制起基础与实战>>里关于看门狗喂狗寄存器WDFEED有一句话:
向WDFEED寄存器写入0XAA的下一个操作应当是向WDFEED寄存器写入0X55"
意思就是说向WDFEED寄存器写入0XAA和0X55之间的空闲时间里,中断可能突然发生,从而没有完成一次喂狗操作,程序发生自动复位。
他建议把喂狗函数改成下面的形式:
/****************************************************************************
* 名称:RstWdt()
* 功能:看门狗喂狗操作。
* 入口参数:无
* 出口参数:无
* !!!!喂狗操作必须是写完0xAA后下一步是写0x55,就是说不能被中断,否则复位
****************************************************************************/
void RstWdt(void)
{
IRQDisable(); //关中断
WDFEED = 0xAA;
WDFEED = 0x55;
IRQEnable(); // 打开中断
}
看到这里,我对这位老兄的崇敬简直有如滔滔江水,连绵不绝。这么细节的问题都能想到,实在是高手之中的高手。于是按照他的方法改进程序,结果上电后发现问题依然存在,接着我改变了WdtInit()中设置的定时器初值,让程序自动复位的时间远大于完成一次循环所需要的时间,结果问题依然无法解决。
此时,我觉得此君有可能是个书呆子,没有什么实战经验。最后,经过反复的摸索,终于找的了解决问题的方法,其实很简单,在喂狗以后立刻跟一个延时函数就可以了。如下:
while(1) // 等待中断
{
WdtFeed();//喂狗
delay(10);//不能删除
...
}
后来,从一些高手那里得到的经验,在写ARM和单片机程序中,延时函数会被常常用到。表面看来在逻辑上可能没什么道理,但实际上在用C/C++编写硬件程序时,由于他们的编译器不可能做得像VC那些纯软件编译器那样完善,因而有时在语法上可能会同过,但实际运行起来往往会出现意想不到的问题。这些都需要通过在实践中去不断发现、积累。
写到这里,我不禁想起两句古诗“纸上得来终觉浅,绝知此事要躬行”。
用户79986 2007-7-7 16:50