一文看懂看门狗(附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 F0x3F, 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 y0x00, 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); //延时1msDisplayScan();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
}
此文做自己学习使用