单片机的看门狗
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <Reg52.H> sfr WDT_CONTR=0xE1; //定义特殊 功能寄存器:STC单片机看门狗控制寄存器 #define uchar unsigned char #define true 1 #define false 0 #define WEIGOU WDT_CONTR=0x34 //看门狗启动设置 和“喂狗”操作 sbit LED=P1^6; //信号灯, 系统正常工作就一闪一闪的 sbit LED_busy=P1^7; //工作灯, 上电灭一会儿(约800ms),然后正常工作的时候一直亮着;用于指示系 统是否重启 uchar timer0_ctr,i; const uchar str[]="I love MCU!"; //定义一句话,让他从串口输出,只 有系统重启的时候才输出一次,所以也是用于验证看门狗有没有重启系统
所以如果同样选择12MHz晶振,使用传统的12 时钟周期,它最小的溢出时间是 (12*2*32768)/(12*106)=65.536ms,最大 溢出时间是(12*256*32768) /(12*106)≈8.38s。如果选择256分频,也就是 说只要在8.38秒之内喂一次狗就可以了。
对于我们用户来说,看门狗的时间是越长越好, 这样可以节省更多的单片机资源,尤其是对时 间要求精准的系统,如果执行过程中我们不停 地“喂狗”,那么是比较浪费时间的。所以 STC89C5X系列单片机的看门狗更有优势一些。 当然这个也是个人的选择,如果对时间要求的 不苛刻的话,勤喂几次狗也没关系。
//while大循环 while(true) { //约每隔800ms喂一次狗,可以通过调整这里的喂 狗时间来验证看门狗是否有效 //我们设置的看门狗约1秒。所以可以ቤተ መጻሕፍቲ ባይዱ800和2000 分别做一次试验,看是否会被看门狗复位 delay_ms(800); LED_busy=0; //第一次上电约延时 800ms工作灯点亮,如果系统不重启,他将一直亮着,用于指 示系统是否重启 WEIGOU; } }
S51的看门狗
AT89S52单片机看门狗定时器是14位的,最大 计数214=16384个数,每计16384个时钟周期 就溢出一次。也就是说如果使用12M晶振的话, 至少应该在16.384ms内喂一次狗。
STC89
STC89C5X系列单片机由于采用了“预分频技 术”,它的溢出时间是=(N*Prescale*32768)/ 晶振频率 (不要问我为什么,他们就是这么设计的,我 们就这么用就行)。
“看门狗”就是一个计数器,由于位数有限计 数器能够装的数值是有限的(比如8位的最多装 256个数、16位的最多装65536个数),从开 启“看门狗”那刻起,它就开始不停的数机器 周期,数一个机器周期就计数器加1,加到计 数器盛不下了(术语叫溢出)就就产生一个复 位信号,重启系统。
注解:
这里顺便说一下,一般教材上叫“看门狗定时 器”,其实定时器原理还是计数器,只是计的 是时钟周期,所以我为了初学者好理解叫统一 叫“计数器”,这里阐明一下。
STC看门狗应用举例
STC89C52最小单片机系统+两个指示灯
串行口接口(用于下载程序和测试本次试验
关于实验的注意事项: 1. 本次试验使用的是11.0592MHz晶振,设置 WDT_CONTR=(0011 0100)B,32预分频,单片机使 用12指令周期模式。 计算看门狗溢出时间: [12*32*32768/(11059200)]≈1s。 2. 本次试验的硬件电路很简单,就是最小系统上增 加两个LED灯,原理图见正文,用户可以很容易实现。 ****************************************** *********************************/
//延时函数,11.0592MHz晶振下延时约xms毫 秒 void delay_ms(unsigned xms) { unsigned x,y; for(x=xms; x>0; x--) for(y=110; y>0; y--); }
//主程序初始化函数 void InitMain() { //初始化时两盏灯都熄灭 LED=1; LED_busy=1; TMOD=0x21; //定时器0工作在方式1,作 为16位定时器;定时器1工作在方式2,作为串行口波特率发生器 TH0=0x4C; //定时器0装初值:每隔 50ms溢出一次 TL0=0x00; IE=0x82; //IE=(1000 0010)B, 使能定 时器0中断 TR0=1; //启动定时器0 }
89S52看门狗使用方法
在ATMEL的89S52系列的89S52与89C51功能相 同。指令兼容。HEX程序无需任何转换可以直 接使用。89S52比89C51增加了一个看门狗功 能。89S52的其它功能可以参见89C52的资料。 看门狗具体使用方法如下: 在程序初始化中向看门狗寄存器 (WDTRST地址是0A6H)中先写入01EH,再 写入0E1H。即可激活看门狗。
注意事项:
1. 89S51的看门狗必须由程序激活后才开始 工作。所以必须保证CPU有可靠的上电复位。 否则看门狗也无法工作。 2. 看门狗使用的是CPU的晶振。在晶振停振 的时候看门狗也无效。 3. 89S51只有14位计数器。在16383个机器 周期内必须至少喂狗一次。而且这个时间是固 定的,无法更改。当晶振为12M时每16个毫秒 需喂狗一次。
其中N是单片机的时钟周期,STC89C5X系列单 片机提供6时钟周期和12时钟周期两种时钟周 期,可以在烧写程序时修改; Prescale是预分频数,通过设置【看门狗控制 寄存器】可以设置为2、4、8、16、32、64、 128、256;怎么设置演示程序中有介绍; 晶振频率就是系统选用的晶振。
//串行口初始化程序 void InitCOM() { SCON=0x50; //SCON=(0101 0000)B,波特率不加倍,允许接收 TH1=0xFD; //设置波特率 =9600bps TL1=TH1; TR1=1; //启动定时器1 }
看门狗的看门原理
我们在设计程序时,先根据看门狗计数器的位 数和系统的时钟周期算一下计满数需要的时间, 就是说在这个时间内“看门狗”计数器是不会 装满的,然后在这个时间内告诉它重新开始计 数,就是把计数器清零,这个过程叫“喂狗”, 这样隔一段时间喂一次狗,只要程序正常运行 他就永远计不满,一旦出现死循环之类的故障, 没有及时来清零计数器,就会导致装满了溢出, 他就重启系统,这就是
每种单片机的“看门狗”实现方法不尽相同, 但是原理都一样,而且“看门狗”都是启动了 之后就不能被关闭,只能系统复位(重新断电 在上电)才能关闭。
设置“看门狗”的一般步骤如 下:
1. 设置“看门狗”相关寄存器, 启动 “看门狗”; 2. 隔一段时间清零一次,“喂狗”; 3. 如果程序正常,一直运行;如果程序出 错,没有按时“喂狗”,“看门狗”就在溢出 的时候复位系统。
单片机的看门狗
-S51及STC89系列
为什么要看门狗?
你家的看门狗是做什么的?
“看门狗定时器”是这样一种东西,从功能上 说它可以让微控制器在意外状况下(比如软件 陷入死循环或跑飞)重新回复到系统上电状态, 以保证系统出问题的时候重启一次。
就跟我们现在用电脑一样,死机了你就按一下 reset键重启一次电脑,看门狗就是负责干这个 事儿的。它是52单片机增加的一个功能,以前 Intel 8031、……、AT 89C51时代单片机片内 都没有“看门狗”功能,需要我们外扩看门狗 芯片,比如X5045。
//定时器0暂停,否则再次来中断会冲断程序
//定时器0重新启动
}
void main() { WEIGOU; 门狗定时器,并且启动 InitMain(); InitCOM();
//上来第一步设置看
//开机通过串口发送一次“I love MCU!”,使用串口调试助手可以查看 //由于在while大循环外边,所以只要系统不重新启动,则上电后只会发送一 次,用于判断系统是否重启 i=0; while(str[i]!='\0') { SBUF=str[i]; while(TI==0); TI=0; i++; }
举个例子说:8051 单片机选用12MHz晶振, 一个时钟周期为1us,如果“看门狗计数器” 是16位的,最大计数65536个,那么从0开始 计到65535需要约65ms,所以我们可以在程序 的50ms左右清零一次计数器(“喂狗”), 让他重新从0开始计,再过50ms,再清,……, 这样下去只要程序正常运行,计数器永远不会 计满,也就永远不会被“看门狗”复位。
当然这个喂狗的时间是大家自己选的,只要不 超过65ms,你选多少都可以,一般不要喂得 太勤,这样单片机运行时间浪费了,比如你 1ms喂一次就太勤了,也不要说那我65ms喂一 次,这样太边缘,这样抗干扰能力就下降了, 最好是留一定的余量,这个就是设计者自己掌 握了,我一般是让计到90%左右就清一次。
89S51的看门狗应用
在C语言中要增加一个声明语句。 在AT89X51.h声明文件中增加一行 sfr WDTRST = 0xA6; 程序代码 sfr WDTRST = 0xA6; main() { WDTRST=0x1E; WDTRST=0xE1;//初始化看门狗。
While (1) { WDTRST=0x1E; WDTRST=0xE1;//喂狗指令 } }
/定时器0中断服务程序程序,控制信号灯闪烁。如果系统正常运行,信号灯1.5秒 闪一次 void Timer0_isr() interrupt 1 { TH0=0x4C; TL0=0x00; timer0_ctr++; if(timer0_ctr>=30) { TR0=0; timer0_ctr=0; LED=0; delay_ms(100); LED=1; TR0=1; }