WDG

WDG简介

  • 英文名称:Watchdog(WDG)
  • 本质功能
    • 硬件级程序运行监控机制,通过 “喂狗”(重置计数器)避免程序卡死 / 跑飞。
    • 类比 “自动重启按钮”,在程序异常时强制复位,保障系统可用性。
  • 应用场景
    • 嵌入式系统(如 STM32)中防止软件漏洞、硬件故障(如传感器卡死)、电磁干扰导致的系统崩溃。
    • 尤其适用于无人值守设备、工业控制等高可靠性场景。

IWDG框图

1. 硬件架构与组件(对应框图)
  • 时钟源(LSI)
    • 框图左侧输入为 LSI(40kHz),会议强调其独立于主时钟,确保主时钟故障时仍能工作,频率范围 30~60kHz(计算超时需留余量)。
  • 预分频器(8 位 + IWDG_PR)
    • 8 位预分频器连接 IWDG_PR 寄存器,提供 6 种分频比(4、8、16、32、64、256)(2n,n=0~5),调整计数器递减速度。
  • 12 位递减计数器
    • 框图中间的 12 位计数器(最大值 4095),未喂狗时减至 0 触发复位,会议通过程序模拟(按键卡死)验证此机制。
  • 重装载寄存器(IWDG_RLR)
    • 存储喂狗重置值,通过 IWDG_KR(键寄存器)写入 0xAAAA 实现重装(喂狗操作),框图中显示其输出连接计数器。
  • 键寄存器(IWDG_KR)
    • 框图右侧的16 位键寄存器,会议详细说明:
      • 0xAAAA:喂狗(重装 RLR 到计数器);
      • 0xCCCC:启用看门狗(不可关闭);
      • 0x5555:解除 PR/RLR 写保护(抗干扰设计,多比特操作避免误触发)。
  • 状态寄存器(IWDG_SR)
    • 框图中的状态寄存器,用于指示看门狗运行状态(如是否使能、复位标志等)。
  • 供电与工作模式
    • 框图底部标注 VDD 供电区, IWDG 在 停机 / 待机模式下仍工作,确保低功耗场景的监控可靠性。
2. 工作流程与原理
  • 初始化
    • 0x5555 解除写保护,配置 PR(分频比)RLR(重装载值)
    • 0xCCCC 启用看门狗,计数器从 RLR 值开始递减。
  • 喂狗操作
    • 主循环定期写 0xAAAA,将 RLR 值重装到计数器,重置递减过程(框图中箭头显示重装路径)。
  • 复位触发
    • 未喂狗时,计数器减至 0,触发 IWDG 复位(框图右侧输出),可以通过 OLED 显示 “独立看门狗 RST” 验证。
3. 特性与应用
  • 抗干扰设计:键寄存器的 16 位操作(非单比特),降低电磁干扰导致的误配置 / 误喂狗,提升可靠性(框图中键寄存器的特殊位置体现此设计)。
  • 独立运行:依赖 LSI 时钟,主时钟故障时仍工作,适用于 对时间精度要求低、需高可靠性的场景(如工业控制、无人值守设备)。
  • 不可关闭性:启用后(0xCCCC)无法关闭,确保系统持续受监控(框图中无关闭路径,会议强调此硬件特性)。

总结:LSI时钟信号 -> 8位预分频器(最多256分频) 预分频寄存器 可以配置分频器的系数(和定时器的PSC相似)->递减计数器 (递减计数器减到0,就触发复位) 为了让其减到0进行复位,就每个一段时间进行值的重装 (重装值寄存器可以设置重载值 与定时器中的ARR相似) -> 键寄存器 (可以写入命令,通过命令将值写入计数器等操作) -> 状态寄存器 有两个状态标志位,一般不看。

IWDG键寄存器

IWDG超时时间

  1. 计数器递减机制
  • IWDG 的 12 位计数器 初始值为 RLR 寄存器的值(范围 0~4095),每次时钟脉冲(经预分频后的 LSI 时钟)递减 1,直到减至 0 时触发复位。
  • 例如:
    • RLR = 0,计数器从 0 开始,立即触发复位(最短超时,对应公式中 0+1=1 次计数)。
    • RLR = 4095,计数器从 4095 递减到 0,共 4096 次计数4095+1),对应最长超时时间。
  1. 公式物理意义

超时时间等于 单次计数周期 × 预分频系数 × 总计数次数

  • 单次周期TLSI=1/FLSI(如 40kHz 时为 25μs)。
  • 预分频系数:调整时钟频率(如 / 16 分频,延长单次计数周期)。
  • 总计数次数RLR + 1(从 RLR 到 0 的所有递减步骤,含初始值)。

总结:TSI是时钟信号的周期 * 预分频系数(可以这样理解,分频之后的周期 就是 时钟信号频率 / 分频系数 在进行整体取倒数,所以这里是 * 预分频系数)得的的时间是 一次的时间 然后再* 次数,因为触发的时机为减到0立刻触发看门狗,所以会对 RL+1 (比如RL = 0 那么溢出就会是1)。RL+1 为从初始化减到0的计数总次数。

WWDG框图

1. 硬件架构与工作原理(框图解析)
  • 时钟源:采用 PCLK1(36MHz,主时钟分支),经固定 4096 分频后驱动 预分频器(WDGTB,4 种分频比:1、2、4、8),控制计数器递减速度。
  • 计数器与寄存器
    • 6 位递减计数器(CNT,T5~T0):位于 WWDG_CR 寄存器,T6 为溢出标志(T6=1:未溢出,可喂狗;T6=0:溢出,触发复位)。
    • 窗口寄存器(WWDG_CFR,W6~W0):存储最早喂狗阈值,比较器检测 CNT > 窗口值(T6:0 > W6:0) 时,判定为 “过早喂狗”,触发复位(框图中与门逻辑)。
    • 控制寄存器(WWDG_CR,WDGA 位):置 1 启用看门狗,启用后不可关闭,且首次配置需确保 T6=1(CNT≥0x40),避免立即复位。
2. 时间窗口与复位机制
  • 复位条件
    • 过晚喂狗:CNT 减至 <0x40(T6=0),计数器溢出,触发复位(框图中 T6=0 时的复位路径)。
    • 过早喂狗:CNT > 窗口值(W6~W0),比较器输出 1,通过与门触发复位(对应 “窗口外喂狗”)。
  • 喂狗要求:必须在 窗口值 < CNT < 0x40(T6=1 时) 内进行,确保喂狗时间既不早于窗口下限,也不晚于溢出上限(会议中窗口 30~50ms 即此逻辑的简化应用)。

总结:PCLK1时钟信号 -> 预分频器(进行预分频处理 预分频参数 有 1 2 4 8)这样可以控制递减的速度 -> 6位递减计数器用来递减计数 T6位 也就是第7位 这里用做的溢出位 也就是最开始配置 计数器时最小值为 0x40 因为当T6位从 1 跳变到 0 的时机就是 窗口看门狗的超时喂狗的复位触发时机,WDGA为开启看门狗的控制位 给1开启并且开启后不可关闭 与另一条线路 进行与操作 ,输出信号由另一条路决定,T6溢出会写0,在或门进行非 写一 所以会产生复位 。框图的上面为配置寄存器可以设置看门狗的窗口值 当 当前计数值 CNT 大于 窗口值时,为过早喂狗 会触发 复位。

WWDG工作特性

1. 复位触发机制
  • 过晚喂狗(T<0x40):当 7 位计数器(T6:0)减至小于 0x40(即 T6=0,如 0x3F~0x00),立即触发复位(图 159 中计数器下降到 3Fh 时 T6 位清零,随后产生复位信号)。
  • 窗口外喂狗(T>W):若喂狗操作(重装计数器)发生在计数器值大于窗口值 W [6:0](图中 “不允许刷新” 区域),视为 “过早喂狗”,直接触发复位(比较器检测 T>W,通过逻辑门复位)。
2. 早期唤醒中断(EWI)
  • 触发条件:计数器等于 0x40(T6=1,T5~T0=0)时,产生 EWI 中断(图中 T6 位在 0x40 时仍为高电平,未到 3Fh)。
  • 功能:用于紧急操作(如数据保存) 或 提前喂狗(在 T<0x40 前重装计数器,避免复位),是 WWDG 的 “预警机制”,提升系统容错能力。
3. 时间窗口与喂狗逻辑(时序图解析)
  • 窗口划分
    • 禁止区(T>W):过早喂狗→ 复位;
    • 允许区(W≥T≥0x40):可喂狗(重装计数器,图中斜线下降到 W 以下进入窗口,此时操作有效);
    • 危险区(T<0x40):过晚喂狗→ 复位(T6=0 时触发)。
  • 喂狗操作:必须在 允许区(W~0x40) 内定期写入 WWDG_CR 寄存器(重装计数器),确保喂狗时间合法(窗口 30~50ms 即此逻辑的具体应用,40ms 位于窗口内,验证正常喂狗)。

总结:计数器当前计数大于 窗口值,视为提前喂狗 产生复位 ,在设置的 窗口内喂狗 操作有效 当 T6为 = 0 就触发 复位 但是在 T6 = 1 的最后一个计数 就是 要产生计数的前一个计数 可以设置 EWI 操作 可以进行 一系列的操作(如保存数据等等,防止数据丢失等)。

WWDG超时时间

image-20250529214219333

总结:时间的计算方式与 独立看门狗的计算方式相同 这里 * 4096 是因为 进来之后会先进行 默认的4096 分频 所以要 * 4096.

IWDG和WWDG对比

独立看门狗(小实验)

核心配置流程(分步详解)

1. 解除写保护(关键前提)
  • 目的:默认情况下,预分频器(PR)和重装值寄存器(RLR)被写保护,需先解锁才能修改。
  • 操作
    • IWDG_KR 寄存器 写入 键值 0X5555(对应库函数:IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable))。
    • 作用:允许后续操作修改 PR 和 RLR 寄存器。
2. 计算并设置预分频系数(PR)和重装值(RLR)
  • 公式:超时时间(ms)=LSI频率(kHz)(PR+1)×(RLR+1)×1000

    • LSI 频率:取 40kHz(默认值,实际以芯片手册为准)。
    • 参数选择原则
      • 优先选择 较小的预分频系数(如 16、32 等),减少因整数取整导致的时间误差。
      • 确保 PRRLR 的值在允许范围内(PR:07;`RLR`:00xFFF,即 0~4095)。
  • 示例计算(以超时时间 1000ms 为例):

    • 选择 PR=16 分频(对应库函数参数IWDG_Prescaler_16),则:RLR=(161000×40)−1=2500−1=2499

    • 库函数调用

      IWDG_SetPrescaler(IWDG_Prescaler_16);  // 设置预分频系数
      IWDG_SetReload(2499);                  // 设置重装值
      
3. 启动独立看门狗
  • 操作:向 IWDG_KR 寄存器 写入 键值 0XCCCC(对应库函数:IWDG_Enable())。
  • 效果:看门狗开始倒计时,从RLR值(如 2499)递减至 0 时触发复位。
4. 喂狗操作(主循环中持续执行)
  • 目的:防止看门狗超时复位,需在超时时间内定期 “喂狗”(重置计数器)。

  • 操作:向 IWDG_KR 寄存器 写入 键值 0XAAAA(对应库函数:IWDG_ReloadCounter())。

  • 示例代码

    while (1) {
        IWDG_ReloadCounter();  // 喂狗
        delay_ms(800);         // 确保间隔小于超时时间(1000ms)
    }
    

三、辅助配置:复位原因判断(可选)

  • 功能:通过 RCC 寄存器 判断复位是否由看门狗触发。

  • 步骤

    1. 查看标志位:调用 RCC_GetFlagStatus(RCC_FLAG_IWDGRST) 检测独立看门狗复位标志。
    2. 清除标志位:调用 RCC_ClearFlag() 清除标志,避免误判后续复位。
  • 代码示例

    if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET) {
        // 处理看门狗复位逻辑(如显示提示)
        RCC_ClearFlag();  // 必须清除标志位
    } else {
        // 处理普通复位逻辑
    }
    

四、注意事项与调试建议

  1. 写保护机制
    • 配置完 PR 和 RLR 后,无需手动重新启用写保护(启动看门狗或写入非 0X5555 值会自动恢复保护)。
  2. 时间误差
    • LSI 时钟精度较低(±10%),实际超时时间可能与计算值有偏差,建议预留 20%~30% 余量(如设置超时 1000ms 时,喂狗间隔控制在 800ms 以内)。
  3. 测试方法
    • 故意延长喂狗间隔(如超过 1000ms),观察是否触发复位,验证看门狗功能是否正常。
    • 通过按键阻塞主循环,模拟程序卡死场景,测试看门狗复位逻辑。
函数名称 功能描述 参数 对应寄存器操作 返回值
IWDG_WriteAccessCmd 解除或启用独立看门狗寄存器的写保护 NewStateIWDG_WriteAccess_Enable(0X5555) IWDG_WriteAccess_Disable(0X0000) IWDG_KR写入键值
IWDG_SetPrescaler 设置独立看门狗的预分频系数 Prescaler:预分频系数(如IWDG_Prescaler_16IWDG_Prescaler_32等) IWDG_PR写入预分频值
IWDG_SetReload 设置独立看门狗的重装值(计数器初始值) Reload:重装值(0~0xFFF,即 0~4095) IWDG_RLR写入重装值
IWDG_ReloadCounter 重新装载计数器(喂狗操作) IWDG_KR写入0XAAAA
IWDG_Enable 启动独立看门狗 IWDG_KR写入0XCCCC
IWDG_GetFlagStatus 获取独立看门狗的标志位状态(如超时标志) FlagIWDG_FLAG_RLRF(.reload 标志) 读取IWDG_SR寄存器 SETRESET
RCC_GetFlagStatus 检测并返回 RCC 复位标志位状态(判断复位原因) RCC_FLAG: 如RCC_FLAG_IWDGRST(独立看门狗复位) RCC_FLAG_WWDGRST(窗口看门狗复位) 读取 RCC 控制寄存器的标志位 SETRESET
RCC_ClearFlag 清除 RCC 的复位标志位(避免后续误判) 清除 RCC 控制寄存器的标志位

总结

不需要手动开器LSI时钟,如果开启看门狗 就自动开启 LSI时钟 ,下面需要输入 指令 关闭写保护(不用手动开启写保护 当开启看门狗 或者写入 非 0x55时,会自动开启写保护) ,然后再写入 预分频 写入 重装载寄存器 ,然后开启看门狗 装置,可以在主程序中加入 判断是否是 看门狗产生的复位等操作 来跟直观的看到 看门狗复位的程序现象。

独立看门狗主要代码

//main.c


#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "key.h"

int main(void)
{
	OLED_Init();
	Key_Init();
	OLED_ShowString(1, 1, "IWDG_RET or RET");
	
	//判断是否是通过什么方式产生的复位
	if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET)
	{
		OLED_ShowString(2, 1, "IWDG_SET");
		Delay_ms(200);
		OLED_ShowString(2, 1, "        ");
		Delay_ms(100);
		
		//要手动清除标志位 
		RCC_ClearFlag();
	}
	else
	{
		OLED_ShowString(3, 1, "SET");
		Delay_ms(200);
		OLED_ShowString(3, 1, "   ");
		Delay_ms(100);
	}
	
	//下面为开启看门狗的操作
	//先写使能
	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
	//写入 重装值 预分频器值
	//查看表格 看要设置的分频器的计数范围 是否 包含要计数的计数次数
	IWDG_SetPrescaler(IWDG_Prescaler_16);
	//计算重装值 1000 ms = 1 / 40khz * 16 * (RL + 1)  ---》 RL =  2499 注意单位换算
	IWDG_SetReload(2499);
	
	IWDG_Enable();
	while(1)
   {
	   
	   //按下按键 阻塞程序
	   Key_GetNum();
	   
	   //在循环中设置时间 执行喂狗操作
	   IWDG_ReloadCounter();
	   
	   OLED_ShowString(4, 1, "FEED");
	   Delay_ms(200);
	   OLED_ShowString(4, 1, "    ");
	   Delay_ms(600);
   }
}

窗口看门狗(小实验)

窗口看门狗(WWDG)操作流程

  1. 第一步:开启时钟
    • 时钟来源:WWDG 时钟来自 PCLK1(需手动开启,不同于 IWDG 的自动时钟开启)。
    • 函数调用:通过RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE)开启 WWDG 的 APB1 时钟。
  2. 第二步:配置寄存器
    • 预分频系数(Prescaler):通过WWDG_SetPrescaler(WWDG_Prescaler_8)设置分频比(例:选择 8 分频,即 2^3=8)。
    • 窗口值(Window Value):通过WWDG_SetWindowValue(0x21)设置窗口上限值(需结合计算,见下文)。
    • 特点:WWDG 无写保护,可直接写入寄存器配置。
  3. 第三步:使能看门狗并初始化计数器
    • 调用WWDG_Enable(0x54 | 0x40)使能 WWDG,同时设置初始计数器值(需包含 T6 位,见参数计算部分),使能要先进行一次喂狗 ,注意 使能与 循环函数中的喂狗操作不能间隔太近,否则会提前喂狗导致复位。
    • 控制寄存器(CR):需设置使能位(WDGA,最高位)、计数器值(T6~T0)和溢出标志位等。
  4. 主循环喂狗
    • 调用WWDG_SetCounter(0x54 | 0x40)定期向计数器写入值,确保计数器值在窗口范围内(即大于窗口值且未超时)。

参数计算

超时时间

窗口时间

在这里插入图片描述

注意与解决

  1. 问题现象

    • 编译下载后程序持续复位,原因:
      • 初始化时首次喂狗与主循环中第二次喂狗间隔过短(<30ms),触发 “喂狗过快” 复位。
  2. 解决方案

    • 方案 1:将喂狗代码移至延时之后,确保两次喂狗间隔≥窗口时间(30ms)。

    • 方案 2:通过标志位判断首次执行,首次使能时同步喂狗,后续循环单独喂狗:

      static uint8_t isFirstRun = 1;
      if (isFirstRun) {
          WWDG_Enable(0x94); // 首次使能并喂狗
          isFirstRun = 0;
      } else {
          WWDG_SetCounter(0x54); // 后续喂狗
      }
      

窗口看门狗主要程序

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "key.h"

int main(void)
{
	OLED_Init();
	Key_Init();
	OLED_ShowString(1, 1, "WWDG_RET or RET");
	

	//判断是否是通过什么方式产生的复位
	if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET)
	{
		OLED_ShowString(2, 1, "WWDG_SET");
		Delay_ms(200);
		OLED_ShowString(2, 1, "        ");
		Delay_ms(100);
		
		//要手动清除标志位 
		RCC_ClearFlag();
	}
	else
	{
		OLED_ShowString(3, 1, "SET");
		Delay_ms(200);
		OLED_ShowString(3, 1, "   ");
		Delay_ms(100);
	}
	
	//下面为开启看门狗的操作
	//开启看门狗时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
	//看表格 要想 超时时间为50ms 窗口时间为 30ms 分频系数的选择只有8分频
	WWDG_SetPrescaler(WWDG_Prescaler_8);
	//设置窗口值 30ms T[5:0] - W[5:0] = 30 / ((1/ 36MHZ)*1000 * 4096 * 8) = 33
	WWDG_SetWindowValue(0x40 | 21);
	//使能窗口看门狗要先进行一次喂狗  设置超时时间 50ms
	// T[5:0] + 1 = 50 / ((1/ 36MHZ)*1000 * 4096 * 8) = 55
	WWDG_Enable(0x40 | 54);
	
	while(1)
   {
	   
	   //按下按键 阻塞程序
	   Key_GetNum();
	   
	   OLED_ShowString(4, 1, "FEED");
	   Delay_ms(20);
	   OLED_ShowString(4, 1, "    ");
	   Delay_ms(15);
	   
	   //在循环中设置时间 执行喂狗操作 喂狗 50ms
	   WWDG_SetCounter(0x40 | 54);
   }
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐