[STM32]Day14独立看门狗+窗口看门狗

WDG看门狗

WDG(Watch Dog),看门狗可以监控程序的运行状态,当程序因为设计漏洞、硬件故障、电磁干扰等原因出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性

看门狗本质上是一个定时器,当指定事件范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号

STM32内置两个看门狗:

  • 独立看门狗(IWDG):独立工作,对时间精度要求较低
  • 窗口看门狗(WWDG):要求看门狗在精确计时窗口起作用

独立看门狗框图

IWDG键寄存器

键寄存器本质上是控制寄存器,用于控制硬件电路的工作

在可能存在干扰的情况下,一般通过在整个键寄存器写入特定值来代替控制寄存器写入一位的功能,以降低硬件电路受到干扰的概率

写入键寄存器的值 作用
0xCCCC 启动独立看门狗
0xAAAA IWDG_RLR中的值重新加载到计数器(喂狗)
0x5555 解除IWDG_PR和IWDG_RLR的写保护
其他值 启用IWDG_PR和IWDG_RLR的写保护

IWDG超时时间

超时时间:T_IWDG = T_LSI * PR分频系数 * (RL + 1)

其中:T_LSI = 1 / F_LSI

WWDG框图

窗口看门狗使用PCLK1也就是APB1的时钟,默认为36MHz,经过预分频器分频后驱动计数器递减计数。T6 - T0为计数位,T6为溢出标志位,T6 = 0时表示计数器溢出。当设置CNT初值为111 1111时,如果把T6看作计数器的一部分,计数器在100 0000 = 0x40溢出;如果把T6看作标志位,计数器在00 0000 = 0x00溢出

WDGA时窗口看门狗使能位,WDGA = 1启用窗口看门狗。T6 = 0时,可以产生复位信号。

W6:0存放的是最早界限的计数值,写入后保持不变。每次喂狗(写入WWDG_CR)时,比较器比较W6:0与当前计数值T6:0,如果T6:0 > W6:0说明喂狗时间太早(注意计数器递减),比较器输出1,产生复位信号。

WWDG工作特性

递减计数器T6:0的值小于0x40时,WWDG产生复位

递减计数器T6:0在窗口W6:0外被重新装载时,WWDG产生复位

递减计数器T6:0等于0x40时可以产生早期唤醒中断(EWI),用于重装载计数器以避免WWDG复位

定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位

超时时间:T_WWDG = T_PCLK1 * 4096 * WDGTB预分频系数 * (T5:0 + 1)

窗口时间:T_WIN = T_PCLK1 * 4096 * WDGTB预分频系数 * (T5:0 - W5:0

其中:T_PCLK1 = 1 / F_PCLK1

乘以4096是因为在进入WDGTB之前还经过了分频,分频系数为4096

WDGTB预分频系数 = 2的WDGTP次方

IWDG和WWDG对比

独立看门狗

按键用于阻塞喂狗

独立看门狗配置流程:开启LSI时钟(开启看门狗后系统自动开启,无需手动操作) -> 解除预分频器和重装载寄存器写保护 -> 向预分频器和重装载寄存器写入 -> 向键寄存器写入0xCCCC启动看门狗 -> 主循环中喂狗

F_LSI = 40kHz,T_LSI = 0.025ms

c 复制代码
#include "stm32f10x.h"                  // Device header
#include "OLED_Software.h"
#include "Delay.h"
#include "Button.h"

int main(void)
{
	
	OLED_Init();
	Button_Init();
	
	OLED_ShowString(1, 1, "IWDG TEST");
	
	if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET) {
		// 独立看门狗引起的复位
		OLED_ShowString(2, 1, "IWDGRST");
		Delay_ms(500);
		OLED_ShowString(2, 1, "       ");
		Delay_ms(100);
		
		RCC_ClearFlag();
	} else {
		OLED_ShowString(3, 1, "RST");
		Delay_ms(500);  
		OLED_ShowString(3, 1, "   ");
		Delay_ms(100);
	}
	
	// 解除预分频器和重装寄存器写保护
	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
	
	// 向预分频器和重装寄存器写入,T_LSI = 0.025ms,设置超时时间为1000ms
	IWDG_SetPrescaler(IWDG_Prescaler_16);
	IWDG_SetReload(2499);
	
	// 先喂一次狗,确保重装寄存器中的值为2499
	IWDG_ReloadCounter();
	
	// 启动看门狗
	IWDG_Enable();

	while(1)
	{
		Button_Read(Pin_11);
		
		IWDG_ReloadCounter();
		
		OLED_ShowString(4, 1, "FEED");
		Delay_ms(200);  
		OLED_ShowString(4, 1, "    ");
		Delay_ms(600);
	}
}

窗口看门狗

窗口看门狗初始化流程:开启时钟(开启APB1时钟) -> 配置预分频器和配置寄存器 -> 使能WWDG并写入控制寄存器 -> 主循环喂狗

c 复制代码
#include "stm32f10x.h"                  // Device header
#include "OLED_Software.h"
#include "Delay.h"
#include "Button.h"

int main(void)
{
	
	OLED_Init();
	Button_Init();
	
	OLED_ShowString(1, 1, "WWDG TEST");
	
	if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET) {
		// 窗口看门狗引起的复位
		OLED_ShowString(2, 1, "WWDGRST");
		Delay_ms(500);
		OLED_ShowString(2, 1, "       ");
		Delay_ms(100);
		
		RCC_ClearFlag();
	} else {
		OLED_ShowString(3, 1, "RST");
		Delay_ms(500);  
		OLED_ShowString(3, 1, "   ");
		Delay_ms(100);
	}
	
	// 开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
	
	// 设置预分频和窗口值
	WWDG_SetPrescaler(WWDG_Prescaler_8);	// 分频系数8,分频系数55 -> 超时时间50ms
	WWDG_SetWindowValue(21 | 0x40);		// 窗口值21 -> 30ms以后才可喂狗
	
	// 使能WWDG并写入控制寄存器
	WWDG_Enable(54 | 0x40);

	while(1)
	{
		Button_Read(Pin_11);
			
		OLED_ShowString(4, 1, "FEED");
		Delay_ms(20);  
		OLED_ShowString(4, 1, "    ");
		Delay_ms(20);
		
		// 喂狗,放在下面避免喂狗过早
		WWDG_SetCounter(54 | 0x40);
	}
}
相关推荐
不悔哥17 小时前
开源OV-Watch:怎么做一个智能手表
单片机·开源·嵌入式
XiHongShi201617 小时前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
优信电子19 小时前
AIT1001 非接触式红外测温模块 STM32 驱动开发实战:从引脚到代码全解析
stm32·嵌入式·温度传感器·红外测温·非接触式测温·ait1001
深圳老胡19 小时前
STM32F407 控制 L6470 步进电机驱动 —— 控制过程简介
笔记·stm32·单片机·嵌入式硬件·代码规范
wuyk55520 小时前
《WiFi 嵌入式物联网开发全套实战》| 第 16 章 ESP32 AP+STA 双模共存原理与工程坑点
网络·stm32·物联网
女神下凡20 小时前
嵌入式设计的各种存储芯片的硬件/软件设计规范,非常全面。
arm开发·单片机·嵌入式硬件
梅梅96621 小时前
一款mipi转lvds的lcd调试(LT8912B)
单片机·计算机外设·电脑·显示器·pd芯片
开发笔记-阿牛1 天前
蓝牙音乐灯拆解,又一次拆到蓝牙音乐灯芯片CK6865L
人工智能·单片机·嵌入式硬件·音视频·音频
从零开始的嵌入式之旅1 天前
day47
arm开发·经验分享·笔记·嵌入式硬件
恒锐丰科技林技术员1 天前
EG1164 高压大电流升压同步整流芯片解析
经验分享·嵌入式硬件·硬件工程