第2-7讲:看门狗定时器
-
- 学习目的
- 了解看门狗定时器的作用。
- 掌握看门狗定时器的应用和使用步骤。
- 看门狗定时器原理
- 看门狗定时器的作用
看门狗定时器(WDT:Watchdog Timer)的作用是在发生软件故障时(如程序陷入死循环或者程序跑飞),强制复位单片机,让单片机重新运行程序。
看门狗定时器本质上是一个计数器,只不过这个计数器的作用是固定的,一旦计数值递增达到设定的值(向上计数)或者计数值递减到0(向下计数),即“超时”时,看门狗定时器产生复位信号,复位系统。
程序正常运行时,会在看门狗定时器“超时”前清零计数值(向上计数)或重装计数值(向下计数),俗称“喂狗”。这样就保证了看门狗定时器永不会“超时”,而一旦程序运行出现故障,无法正常“喂狗”时,看门狗定时器最终会“超时”复位系统,使系统从头开始运行。
- STC8A8K64D4看门狗定时器
STC8A8K64D4的看门狗功能比较简单,使用时只需配置看门狗控制寄存器“WDT_CONTR”即可。
看门狗控制寄存器:
- WDT_FLAG:看门狗溢出标志。
看门狗发生溢出时,硬件自动将此位置 1,需要软件清零。
- EN_WDT:看门狗使能位。
0:对单片机无影响。
1:启动看门狗定时器。
看门狗启动有两种方式:软件启动和硬件启动,软件启动方式只需把看门狗使能位“EN_WDT”设置为1就可以了。
WDT_CONTR |= 0x10;
硬件启动方式在使用STC-ISP软件下载时设置,如下图所示,勾选“上电复位时由硬件自动启动看门狗”选项即可。
图1:硬件启动看门狗
- CLR_WDT:看门狗定时器清零。
0: 对单片机无影响。
1: 清零看门狗定时器,硬件自动将此位复位。
- IDL_WDT:IDLE 模式时的看门狗控制位。
0:IDLE 模式时看门狗停止计数。
1:IDLE 模式时看门狗继续计数。
- WDT_PS[2:0]:看门狗定时器时钟分频系数。
分频系数决定了看门狗的溢出时间,其计算公式如下:
下面列出了12M和24M主频时,不同的分频系数对应的看门狗溢出时间。
表1:不同主频和分频系数时看门狗溢出时间
WDT_PS[2:0] | 分频系数 | 12M 主频时的溢出时间 | 24M主频时的溢出时间 |
000 | 2 | ≈65.5毫秒 | ≈32.7毫秒 |
001 | 4 | ≈131毫秒 | ≈65.5毫秒 |
010 | 8 | ≈262毫秒 | ≈131毫秒 |
011 | 16 | ≈524毫秒 | ≈262毫秒 |
100 | 32 | ≈1.05秒 | ≈524毫秒 |
101 | 64 | ≈2.1秒 | ≈1.05秒 |
110 | 128 | ≈4.2秒 | ≈2.1秒 |
111 | 256 | ≈8.39秒 | ≈4.2秒 |
-
- 软件设计
- 看门狗应用步骤
- 软件设计
使用看门狗的时候,只需配置看门狗控制寄存器“WDT_CONTR”就可以了。在配置前,我们需要确定以下几点:
- 确定自己的程序中需要设置多长时间的溢出时间,以此来配置看门狗定时器的分频系数。
- IDLE 模式时看门狗是否计数。
- 确定合适的喂狗时机(看门狗定时器清零“CLR_WDT”位置位即可喂狗),确保程序在正常运行时,在溢出时间内至少执行一次喂狗操作。
配置完成后,看门狗使能位“EN_WDT”设置为1启动看门狗即可。此后,若单片机软件运行出现故障,无法正常喂狗,看门狗溢出后会强制复位单片机,让单片机重新运行程序。
-
-
- 看门狗实验
-
- 注:本节的实验是在“实验2-3-2:触摸按键检测”的基础上修改,本节对应的实验源码是:“实验2-7-1:看门狗实验”。
-
-
- 实验内容
-
-
配置看门狗超时时间为2.1秒,即程序运行时2.1秒不执行喂狗操作,系统复位。看门狗在IDLE 模式时看门狗定时器不计数。
为了观察到复位现象,程序启动后,D1闪烁4次,指示系统启动,之后初始化并启动看门狗,每按动一次KEY1按键执行一次喂狗,如果连续在2.1秒内按动KEY1按键喂狗,系统不会复位,如果2.1秒内不按动KEY1按键喂狗,系统会复位重新启动,可以看到D1闪烁4次。
-
-
-
- 代码编写
-
-
- 新建一个名称为“wdt.c”的文件及其头文件“wdt.h”并保存到工程的“Source”文件夹,并将“wdt.c”加入到Keil工程中的“SOURCE”组。
- 引用头文件
因为在“main.c”文件中使用了“wdt.c”文件中的函数,所以需要引用下面的头文件“wdt.h”。
代码清单:引用头文件
- //引用看门狗的头文件
- #include "wdt.h"
- 初始化并启动看门狗
看门狗初始化函数代码清单如下,配置看门狗溢出时间为2.1秒,初始化完成后启动了看门狗。
代码清单:初始化并启动看门狗
- /*************************************************************************************
- * 描 述 : 初始化并启动看门狗
- * 入 参 : 无
- * 返回值 : 无
- ************************************************************************************/
- void wdt_init(void)
- {
- WDT_CONTR &= 0xF7; //IDLE_WDT位置0,看门狗定时器在空闲模式下不计数
- WDT_CONTR &= 0xF8; //配置分频系数,先清零配置位PS2~PS0,再写入配置
- WDT_CONTR |= 0x06; //PS2~PS0配置为110,即看门狗溢出时间为2.1秒
- WDT_CONTR &= 0x7F; //WDT_FLAG位置0,看门狗溢出标志位清零
- WDT_CONTR |= 0x20; //EN_WDT位置1,开启看门狗定时器
- }
- 初始化并启动看门狗
主函数中加入系统启动指示,以方便观察系统复位。接着,调用wdt_init()函数初始化并启动WDT,之后在循环查询按键S3状态,若检测到按键S3按下后,则执行喂狗操作。
代码清单:主函数
- /**************************************************************************
- 功能描述:主函数
- 入口参数:无
- 返回值:int类型
- *************************************************************************/
- int main(void)
- {
- ……
- //闪烁指示灯D1表示系统启动,方便观察系统复位
- for(i=0;i<8;i++)
- {
- led_toggle(LED_1);
- delay_ms(100);
- }
- wdt_init(); //初始化并启动看门狗
- while(1)
- {
- temp=buttons_scan(0); //获取开发板用户按键检测值,不支持连按
- if(temp == BUTTON1_PRESSED) //如果按键KEY1按下
- {
- led_toggle(LED_2); //控制用户指示灯D2翻转
- wdt_feed(); //喂狗
- }
- }
- }
-
-
- 硬件连接
-
-
本实验需要使用LED指示灯和按键,因此需要用跳线帽短接复用引脚的指示灯(D1和D2)和按键(KEY1),如下图所示。
图2:跳线帽短接
-
-
-
- 实验步骤
-
-
- 解压“…\第3部分:配套例程源码”目录下的压缩文件“实验2-7-1:看门狗实验”,将解压后得到的文件夹拷贝到合适的目录,如“D\STC8”(这样做的目的是为了防止中文路径或者工程存放的路径过深导致打开工程出现问题)。
- 双击“…\wdt\Project\object”目录下的工程文件“wdt.uvproj”。
- 点击编译按钮编译工程,编译成功后生成的HEX文件“wdt.hex”位于工程的“…\wdt \project”目录下。
- 打开STC-ISP软件下载程序,下载使用内部IRC时钟,IRC频率选择:24MHz。
- 程序运行后,可以观察到D1指示灯闪烁4次,之后熄灭,指示系统复位启动。
- 连续在每个2.1秒内按动KEY1按键执行喂狗操作,系统不会复位。
- 2.1秒内不按动KEY1按键,看门狗溢出,系统复位重新启动,可观察到D1闪烁4次。