一文看懂看门狗(附STM和英飞凌芯片应用)
文章目录
- 一文看懂看门狗(附STM和英飞凌芯片应用)
- (一)看门狗概述
- (二)硬件看门狗
- (三)软件看门狗
(一)看门狗概述
看门狗定时器(WDT,Watch Dog Timer)是单片机的一个组成部分,它实际上是一个计数器,一般给看门狗一个数字,程序开始运行后看门狗开始计数。如果程序运行正常,过一段时间CPU应发出指令让看门狗置零,重新开始计数。如果看门狗增加到设定值就认为程序没有正常工作,强制整个系统复位。
一般情况下看门狗可分为硬件看门狗和软件看门狗,两种形式实现方法,优先级和使用环境不同。
(二)硬件看门狗
原理图如下:
在看门狗( watchdog timer),是一个定时器电路, 一般有一个输入,叫喂狗(kicking the dog or service the dog),一个输出到MCU的RST端,MCU正常工作的时候,每隔一段时间输出一个信号到喂狗端,给WDT清零,如果超过规定的时间不喂狗,(一般在程序跑飞时),WDT 定时超过,就会给出一个复位信号到MCU,使MCU复位. 防止MCU死机. 看门狗的作用就是防止程序发生死循环,或者说程序跑飞。
(三)软件看门狗
看门狗命令在程序的中断中拥有最高的优先级。防止程序跑飞。也可以防止程序在线运行时候出现死循环。
相对于一个监视守护进程,避免关键程序出现死锁影响系统功能。
下面是一个基于STC的IO控制软件看门狗示例代码:
#define MAIN_Fosc 22118400L //定义主时钟
#include "STC15Fxxxx.H"
#define DIS_DOT 0x20
#define DIS_BLACK 0x10
#define DIS_ 0x11
#define Timer0_Reload \
(65536UL - (MAIN_Fosc / 1000)) // Timer 0 中断频率, 1000次/秒
u8 code t_display[] = { //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C,
0x39, 0x5E, 0x79, 0x71,
// black - H J K L N o P U t G Q r M y
0x00, 0x40, 0x76, 0x1E, 0x70, 0x38, 0x37, 0x5C, 0x73, 0x3E, 0x78, 0x3d,
0x67, 0x50, 0x37, 0x6e, 0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87,
0xFF, 0xEF, 0x46}; // 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8 code T_COM[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; //位码
sbit P_HC595_SER = P4 ^ 0; // pin 14 SER data input
sbit P_HC595_RCLK = P5 ^ 4; // pin 12 RCLk store (latch) clock
sbit P_HC595_SRCLK = P4 ^ 3; // pin 11 SRCLK Shift data clock
u8 LED8[8]; //显示缓冲
u8 display_index; //显示位索引
u16 ms_cnt;
u8 tes_cnt; //测试用的计数变量
void delay_ms(u8 ms);
void DisplayScan(void);
void main(void) {
u8 i;
P0M1 = 0;
P0M0 = 0; //设置为准双向口
P1M1 = 0;
P1M0 = 0; //设置为准双向口
P2M1 = 0;
P2M0 = 0; //设置为准双向口
P3M1 = 0;
P3M0 = 0; //设置为准双向口
P4M1 = 0;
P4M0 = 0; //设置为准双向口
P5M1 = 0;
P5M0 = 0; //设置为准双向口
P6M1 = 0;
P6M0 = 0; //设置为准双向口
P7M1 = 0;
P7M0 = 0; //设置为准双向口
display_index = 0;
for (i = 0; i < 8; i++)
LED8[i] = DIS_BLACK; //全部消隐
tes_cnt = 0;
ms_cnt = 0;
LED8[7] = ms_cnt;
while (1)
{
delay_ms(1); //延时1ms
DisplayScan();
if (tes_cnt <= 5) // 5秒后不喂狗, 将复位,
WDT_CONTR = (D_EN_WDT + D_CLR_WDT + D_WDT_SCALE_16); // 喂狗
if (++ms_cnt >= 1000)
{
ms_cnt = 0;
tes_cnt++;
LED8[7] = tes_cnt;
}
}
}
void delay_ms(u8 ms)
{
u16 i;
do {
i = MAIN_Fosc / 13000;
while (--i) ; // 14T per loop
} while (--ms);
}
void Send_595(u8 dat)
{
u8 i;
for (i = 0; i < 8; i++)
{
dat <<= 1;
P_HC595_SER = CY;
P_HC595_SRCLK = 1;
P_HC595_SRCLK = 0;
}
}
void DisplayScan(void)
{
Send_595(~T_COM[display_index]); //输出位码
Send_595(t_display[LED8[display_index]]); //输出段码
P_HC595_RCLK = 1;
P_HC595_RCLK = 0; //锁存输出数据
if (++display_index >= 8)
display_index = 0; // 8位结束回0
}
此文做自己学习使用