软件看门狗实现

图片

一文看懂看门狗(附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
}

此文做自己学习使用

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炸弹气旋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值