尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

【嵌入式成长13】STC89C51看门狗WDT|防止程序跑飞死机,自动复位实战

【嵌入式成长13】STC89C51看门狗WDT|防止程序跑飞死机,自动复位实战 一、看门狗的作用看门狗本质是一个独立递减计数器启动看门狗后计数器开始不停计数程序正常运行时需要定时“喂狗”把计数器清零重置一旦程序跑飞、死循环、卡死代码无法执行喂狗操作计数器计数溢出看门狗产生硬件复位信号单片机整机自动重启。通俗比喻定时给看门狗“喂食”如果长时间不喂看门狗就会触发系统重启。⚠️注意普通AT89C51没有内置看门狗STC89C52RC才有内置硬件看门狗。二、看门狗控制寄存器 WDT_CONTR寄存器地址0xE1标准reg52.h头文件没有定义该寄存器代码需要手动声明。位符号功能说明B5EN_WDT看门狗使能位1启动看门狗看门狗一旦开启软件不能关闭只能通过复位关闭B4CLR_WDT喂狗清零位写1看门狗计数器清零硬件会自动把该位清0B3IDLE_WDT空闲模式看门狗是否继续计数0空闲模式停止计数本教程配置为0B2‑B0PS2 PS1 PS0预分频位用来设置看门狗溢出时间溢出时间计算公式WDT溢出时间12×预分频数×32768晶振频率WDT_{溢出时间}\frac{12 × 预分频数 × 32768}{晶振频率}WDT溢出时间​晶振频率12×预分频数×32768​溢出时间参考表12MHz晶振PS2PS1PS0预分频溢出时间000265.5 ms0014131.0 ms0108262.1 ms01116524.2 ms100321.0485 s101642.0971 s1101284.1943 s1112568.3886 s11.0592MHz晶振开发板常用PS2PS1PS0预分频溢出时间000271.1 ms0014142.2 ms0108284.4 ms01116568.8 ms100321.1377 s101642.2755 s1101284.5511 s1112569.1022 s开发建议喂狗周期必须小于看门狗溢出时间。例如溢出时间2.27s代码要在小于2.27s内执行喂狗。三、看门狗使用三步初始化配置WDT_CONTR寄存器开启看门狗设置预分频确定溢出超时时间。定时喂狗程序正常运行过程中定期写CLR_WDT1重置看门狗计数器。异常自动复位程序卡死无法执行喂狗计数器溢出单片机硬件自动复位重启。重要提醒看门狗一旦软件开启代码无法软件关闭只有上电复位/看门狗自己产生复位才能关闭看门狗。四、完整代码示例示例1基础看门狗正常喂狗系统不会复位11.0592M晶振设置预分频64溢出时间约2.27s主循环1s喂一次狗。#include reg52.h //STC扩展看门狗寄存器reg52.h没有必须手动定义 sfr WDT_CONTR 0xE1; sbit led P2^7; void delay_ms(unsigned int xms) { unsigned int i,j; for(ixms;i0;i--) for(j124;j0;j--); } //看门狗初始化溢出时间约2.27s void WDT_Init(void) { // 0011 0101 // EN_WDT1启动IDLE_WDT0空闲停止计数PS2 PS1 PS0 101 预分频64 WDT_CONTR 0x35; } //喂狗函数重置看门狗计数器 void WDT_Feed(void) { WDT_CONTR | 0x10; //CLR_WDT置1硬件自动清零该位 } void main(void) { WDT_Init(); led 0; delay_ms(500); led 1; while(1) { delay_ms(1000); WDT_Feed(); //每1000ms喂狗一次小于2.27s溢出时间系统正常运行 } }示例2模拟程序死机不喂狗观察看门狗自动复位把喂狗语句注释掉看门狗超时单片机会不断自动复位LED反复闪烁。#include reg52.h sfr WDT_CONTR 0xE1; sbit led P2^7; void delay_ms(unsigned int xms) { unsigned int i,j; for(ixms;i0;i--) for(j124;j0;j--); } void WDT_Init(void) { WDT_CONTR 0x35; } void main(void) { WDT_Init(); led 0; delay_ms(500); led 1; while(1) { delay_ms(3000); // WDT_Feed(); //注释掉喂狗超过溢出时间看门狗自动复位 } }示例3工程化写法把喂狗放到主循环真实项目主循环轮询业务每次循环末尾执行喂狗不要在中断里面喂狗。#include reg52.h sfr WDT_CONTR 0xE1; void delay_ms(unsigned int xms) { unsigned int i,j; for(ixms;i0;i--) for(j124;j0;j--); } void WDT_Init(void) { WDT_CONTR 0x35; } void WDT_Feed(void) { WDT_CONTR | 0x10; } void main(void) { WDT_Init(); while(1) { //此处放置项目业务代码按键扫描、传感器读取、串口处理等 delay_ms(200); WDT_Feed(); //主循环末尾喂狗 } }五、开发踩坑总结reg52.h没有WDT_CONTR寄存器必须手动写sfr WDT_CONTR 0xE1;否则编译报错。看门狗开启后软件不能关闭只有硬件复位可以关闭看门狗。调试阶段可注释掉WDT_Init()避免调试时频繁自动复位。喂狗周期一定要小于看门狗溢出时间如果业务最长执行时间是1.5s溢出时间设置2.27s比较安全。不要在中断服务函数里面喂狗。如果主while(1)已经死循环卡死但中断还在跑中断里面喂狗会导致看门狗失效检测不出主程序死机。STC‑ISP烧录工具硬件选项中有看门狗硬件使能位不要和软件配置混淆。普通AT89C51没有内置看门狗只有STC89C52RC才有片内WDT。六、本章小结看门狗WDT用于提高单片机抗干扰能力程序跑飞卡死无法喂狗自动硬件复位。WDT_CONTR寄存器控制看门狗EN_WDT开启CLR_WDT实现喂狗清零PS2‑PS0设置预分频决定溢出时间。使用流程初始化开启看门狗主循环中定时喂狗。调试阶段建议关闭看门狗正式产品版本打开看门狗提升稳定性。
返回列表