☰
STM32F103 窗口看门狗 WWDG 实战:窗口期计算、喂狗时机与复位周期实测
2026/9/27 11:57:49 网站建设 项目流程

文章目录

    • 摘要
    • 前言
    • WWDG 工作原理:一个带"时间笼子"的看门狗
    • 窗口期数学推导:先把时间算明白
    • 方案决策:为什么是 WWDG 而不是 IWDG
    • 硬件准备与测试环境
    • CubeMX 配置与寄存器级解释
    • 容易遗漏的步骤:调试冻结与中断使能
    • 核心代码实现
      • 初始化(CubeMX 生成 + 返回值检查)
      • EWI 中断里喂狗(推荐策略)
      • 主循环喂狗策略(验证窗口机制用)
      • 复位原因检测
    • 测试验证:四组实验对照理论
      • 实验一:不喂狗,测完整超时周期(理论 vs 实测对照 1)
      • 实验二:窗口外提前喂狗(量化参数对比)
      • 实验三:EWI 喂狗 vs 主循环喂狗
      • 实验四:复位标志验证
    • 故障排查:6 类高频问题与完整排查链
      • 问题 1:一上电就不断复位,LED 疯狂闪烁
      • 问题 2:程序跑一段时间后偶发复位
      • 问题 3:调试模式下反复复位,断点停不住
      • 问题 4:EWI 中断从不触发
      • 问题 5:低功耗 STOP 模式下异常复位
      • 问题 6:复位标志永远读不到 WWDG
    • 总结

摘要

独立看门狗(IWDG)只能兜底"死机不复位",却挡不住"程序跑飞后仍能按期喂狗"的软故障。窗口看门狗(WWDG)用"喂狗必须落在指定时间窗口内"的机制补上这个缺口:喂早了复位,喂晚了也复位。本文基于 STM32F103C8T6 最小系统板,从 7 位递减计数器的寄存器级原理讲起,推导窗口期与超时周期的计算公式,再落地 CubeMX 配置、EWI 中断喂狗与主循环喂狗两种策略。实测数据:T[6:0]=0x7F、WDGTB=3 时理论超时 58.25ms,示波器实测 58.3ms,偏差 0.09%;四档预分频下超时周期 7.28ms~58.25ms 全部吻合公式;窗口边界实测与理论开启时刻 31.87ms 吻合在 1ms 以内。文末附 6 类高频故障的完整排查链,覆盖上电即复位、调试反复复位、STOP 唤醒复位等经典陷阱。

前言

做产品时遇到过一种很难查的故障:设备在恶劣电磁环境下偶发逻辑错乱,但 IWDG 形同虚设——因为跑飞后的程序恰好还在按原周期喂狗。独立看门狗只检查"喂没喂",不检查"喂得对不对"。窗口看门狗强制喂狗动作必须落在启动后的某段特定时间区间内,喂早了算故障,喂晚了也算故障,把"程序乱跑但定时器还活着"这类软故障也纳入监控。

本文目标是让你在 30 分钟内完成 WWDG 的选型判断、窗口参数计算、工程落地和复位现象验证。前置条件:熟悉 CubeMX 基本操作,跑通过 STM32F103 的 GPIO 点灯工程,手头有一块 F103 核心板、一个 USB 转 TTL 和一个示波器或逻辑分析仪(没有示波器也可以用 LED 闪烁频率粗测复位周期)。完整工程代码可在 CSDN 下载频道 获取(VIP 免费)。

WWDG 工作原理:一个带"时间笼子"的看门狗

WWDG 与 IWDG 最大的区别在于时钟域和监控逻辑。IWDG 使用独立的 40kHz LSI 低速时钟,掉进 STOP/STANDBY 模式也不停;WWDG 挂在 PCLK1(APB1 总线时钟)上,由 7 位递减计数器驱动,主时钟停它就停。更关键的是,WWDG 的喂狗不是"随时可喂",而是被窗口值和下限值框在了一个固定的时间区间里。

写WWDG_CR启动(WDGA=1)

每(4096×2^WDGTB)个PCLK1周期-1

CNT > 窗口W, 此时喂狗→复位

CNT ≤ 窗口W 且 CNT > 0x40

喂狗成功(写CR, 重载装载值T)

CNT == 0x40, 产生早期唤醒中断

1个tick内未喂狗, CNT减到0x3F

装载值T

递减中

窗口内

重载

EWI触发

复位

整个计数过程可以理解为:计数器从装载值 T[6:0] 出发一路递减,递减到 0x3F 的那一刻硬件强制复位;与此同时,窗口值 W[6:0] 划了一条警戒线——如果计数器的值还大于 W(也就是时间还没到窗口),此时去喂狗会立刻复位;只有计数器落在0x40 ≤ CNT ≤ W这段"窗口内"时喂狗才被接受,并把计数器重新装回装载值,开启下一轮循环。

这个"喂早了复位、喂晚了复位"的设计,恰好把看门狗从"检测程序是否活着"升级成了"检测程序是否按预期节奏活着"。我最初只用 IWDG 做产品保护,后来在电机驱动板的现场故障里才体会到 WWDG 的价值,两种看门狗的分工和取舍后面会单独对比。

窗口期数学推导:先把时间算明白

WWDG 的所有时间参数都从一个基准 tick 出发:tick = 4096 × 2^WDGTB / Fpclk1。4096 是芯片内部固定的分频系数,WDGTB 是 CFR 寄存器里的预分频档位(00~11),Fpclk1 在 F103 跑 72MHz 主频时固定为 36MHz(APB1 最高频率)。

从装载到复位经历(T[6:0] − 0x3F)个 tick,所以完整超时周期为:

Tout = 4096 × 2^WDGTB × (T[6:0] − 0x3F) / Fpclk1

窗口开启到复位的可喂狗区间宽度为(W[6:0] − 0x40 + 1)个 tick,窗口开启时刻(从启动算起)为(T[6:0] − W[6:0])个 tick。注意这里的下限 0x40 就是 EWI 中断触发点——计数器减到 0x40 时中断标志置位,之后只剩 1 个 tick 的抢救时间。

以本文实验参数为例:Fpclk1 = 36MHz,T[6:0] = 0x7F(127),W[6:0] = 0x5C(92),WDGTB = 3(÷8)。

时间参数公式代入计算值
基准 tick4096 × 8 / 36MHz910.2 μs
完整超时周期4096×8×(127−63) / 36MHz58.25 ms
窗口开启时刻(127−92) × 910.2μs31.87 ms
可喂狗窗口宽度(92−64+1) × 910.2μs26.40 ms
EWI 触发后剩余时间1 × 910.2μs0.91 ms

这里有个容易踩的认知坑:很多人套网上流传的Tout = (T[6:0]+1) × tick公式,算出 128 个 tick,但那是把复位点当成"递减到 0"的算法。F103 的实际复位点是 0x3F(63),所以严格计算应该用T[6:0] − 0x3F,也就是 64 个 tick——这个差别在手册的超时时间表里可以直接验证(WDGTB=0 时最大超时 7.28ms = 64 × 113.8μs,而不是 128 × 113.8μs = 14.56ms)。

方案决策:为什么是 WWDG 而不是 IWDG

选看门狗方案时,先明确要防什么故障,再选器件,这个顺序不能反。IWDG 防"彻底死机"(中断全挂、主循环卡死),WWDG 防"逻辑跑偏但定时器还在跳"(死循环里恰好带着喂狗、中断风暴抢走主循环执行权但喂狗代码被执行等场景)。

对比维度IWDG 独立看门狗WWDG 窗口看门狗
时钟源独立 LSI(约 40kHz)PCLK1(APB1 总线时钟)
计数器12 位递减,喂狗重载初值7 位递减,窗口内喂狗重载
喂狗条件任意时刻仅0x40 ≤ CNT ≤ W区间内
复位条件计数到 0 未喂减到 0x3F 未喂 / 窗口外提前喂
STOP 模式继续计数,会复位PCLK1 停止,计数暂停
中断辅助无EWI 早期唤醒中断(复位前抢救)
典型超时约 0.1ms ~ 26.2s约 0.1ms ~ 58.2ms(F103@36MHz APB1)

我的选型习惯:只需要"兜底重启"就上 IWDG;如果程序对执行时序有要求、想顺带检测"任务是否在预期窗口内推进",就用 WWDG,或者两个叠加(WWDG 盯主流程节奏,IWDG 兜底深度休眠等 LSI 场景)。WWDG 的 58ms 量级上限决定了它不适合直接替代 IWDG 做长周期监控,这是硬件能力边界,靠软件绕不过去。关于两者的更多差异,可以参考这篇对比文章:《STM32独立看门狗(IWDG)和窗口看门狗(WWDG)的区别》。

硬件准备与测试环境

WWDG 本身不占任何引脚,实验硬件极简:STM32F103C8T6 最小系统板一块,串口(PA9/PA10)接 USB 转 TTL 用于打印复位原因和计数,示波器探头接 NRST 引脚(3 号引脚)观察复位脉冲。板载 LED 接 PC13,作为"复位了几次"的视觉指示——每复位一次就在 main 开头翻转一次 LED,人眼能直接看出是否在反复复位。

测量原理:NRST 是开漏输出,复位时被拉低,示波器上升沿之间的间隔就是"从复位到下一次复位"的完整周期。不喂狗时这个周期就等于 WWDG 超时时间,正好用来做理论值和实测值的对照。

CubeMX 配置与寄存器级解释

在 CubeMX 左侧 Connectivity 里找到 WWDG,勾选 Activated 后出现三个参数。这三个参数分别对应两个寄存器的三个字段,逐个说清楚它们的本质:

  • Prescaler(预分频):对应WWDG_CFR寄存器的WDGTB[1:0]位(bit8:7),选择 2^WDGTB 倍分频,可选 1/2/4/8。它决定基准 tick 长度,是时间尺度的总开关。
  • Window(窗口值):对应WWDG_CFR的W[6:0]位(bit6:0),计数器值大于它时喂狗即复位。窗口值越小,窗口开启越晚、可喂狗区间越窄。
  • Counter(装载值):对应WWDG_CR的T[6:0]位(bit6:0),同时是启动初值和每次喂狗的重载值。装载值越大,单轮超时周期越长。

另外还有一个必须手动确认的选项:Early Wakeup Interrupt(EWI),对应WWDG_SR寄存器的EWIF标志位(bit0)和 NVIC 中断使能。计数器减到 0x40 时 EWIF 置位并触发中断,这是"复位前最后抢救窗口",后面代码策略部分会详细用。

我实验用的参数组合:Prescaler = 8(WDGTB=3)、Window = 0x5C、Counter = 0x7F、EWI 使能。按前面公式,完整超时 58.25ms,窗口开启于 31.87ms,可喂狗窗口约 26.4ms——给主循环留下了非常宽裕的喂狗区间。CubeMX 配置界面的其他细节可以对照这篇:《STM32CubeMX学习笔记(12)——WWDG窗口看门狗使用》。

容易遗漏的步骤:调试冻结与中断使能

WWDG 有两个"工具不会自动帮你做"的关键步骤,漏掉任何一个,调试体验都会非常折磨。

第一,调试模式下的 WWDG 冻结。WWDG 挂在 PCLK1 上,正常调试时你停在断点处,PCLK1 还在跑,WWDG 照常递减,很快就把芯片复位了——表现就是"一进调试模式就反复重启,断点根本停不住"。CubeMX 在 SYS 页里有个 Debug 选项(Serial Wire 之类),但WWDG 冻结不归 CubeMX 管,需要手动设置DBGMCU_CR寄存器的DBG_WWDG_STOP位(bit10),代码写法:

/* DBGMCU_CR bit10: DBG_WWDG_STOP,调试时冻结 WWDG 计数器,否则一进调试就复位 */DBGMCU->CR|=DBGMCU_CR_DBG_WWDG_STOP;

我在第一次调 WWDG 时就栽在这上面:断点打不进去,全速跑又看不出问题,最后用串口打印定位到是 WWDG 抢先复位。这个位在 F1 系列叫 DBG_WWDG_STOP,F4 系列同名,H7 系列位置不同(在 DBGMCU_APB1FZR),跨系列移植要重新查手册。

第二,EWI 中断的 NVIC 使能。CubeMX 里勾选了 Early Wakeup Interrupt 之后,还要到 NVIC 设置里把 WWDG 的中断优先级打开,否则 EWIF 标志会置位但中断不进来,等于没有抢救窗口,主循环喂狗节奏稍有波动就直接复位。这个"勾了选项还要配 NVIC"的步骤很容易被漏掉,症状是"喂狗逻辑明明写了,但偶尔还是复位"。

核心代码实现

初始化(CubeMX 生成 + 返回值检查)

CubeMX 生成的MX_WWDG_Init()已经包含初始化调用,但默认不检查返回值,产品代码里务必补上:

WWDG_HandleTypeDef hwwdg;voidMX_WWDG_Init(void){hwwdg.Instance=WWDG;hwwdg.Init.Prescaler=WWDG_PRESCALER_8;/* WDGTB=3, tick=910.2us */hwwdg.Init.Window=0x5C;/* W[6:0]=92, 窗口值 */hwwdg.Init.Counter=0x7F;/* T[6:0]=127, 装载值 */hwwdg.Init.EWIMode=WWDG_EWI_ENABLE;/* 使能早期唤醒中断 */if(HAL_WWDG_Init(&hwwdg)!=HAL_OK){Error_Handler();/* 初始化失败必须暴露,不能静默继续 */}}

EWI 中断里喂狗(推荐策略)

把喂狗放在 EWI 中断回调里是最稳的做法:计数器减到 0x40 触发中断,此时必然处于窗口内(0x40 ≤ W),喂狗一定合法,不存在"喂早了"的风险。主循环被高优先级任务阻塞多久都没关系,只要中断能响应就行。

volatileuint32_tg_wwdg_feed_count=0;/* 中断与主循环共享,必须 volatile *//* WWDG 中断服务函数,CubeMX 已生成 */voidWWDG_IRQHandler(void){HAL_WWDG_IRQHandler(&hwwdg);}/* 早期唤醒回调:CNT 减到 0x40 时进入,距复位仅剩 1 个 tick */voidHAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef*hwwdg){/* 先清标志再喂狗;喂狗动作=写 CR,计数器重载回装载值 0x7F */__HAL_WWDG_CLEAR_FLAG(hwwdg,WWDG_FLAG_EWIF);HAL_WWDG_Refresh(hwwdg);g_wwdg_feed_count++;/* 喂狗计数,供主循环观测 */}

主循环喂狗策略(验证窗口机制用)

为了演示"喂早了会复位",我另外写了一个主循环喂狗版本,把喂狗时机人为拨到窗口之外,观察复位现象(见测试验证一节):

uint32_ttick_ms=0;/* 简单毫秒计数,由 SysTick 累加 */voidloop_feed_strategy(void){/* 第 5ms 时喂狗:此时 CNT 还远大于窗口值 0x5C,属于"提前喂狗", 硬件会立即产生复位——故意用来演示窗口下限(上限)保护 */if(tick_ms==5){HAL_WWDG_Refresh(&hwwdg);/* 此行执行后芯片立刻复位 */}/* 第 35ms 时喂狗:CNT 已减到窗口内(0x40~0x5C),喂狗合法 */if(tick_ms==35){HAL_WWDG_Refresh(&hwwdg);}}

复位原因检测

每次复位后先查复位标志,判断是不是 WWDG 干的,这是排查一切复位问题的基础工具:

voidcheck_reset_cause(void){if(__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST)){printf("[RST] WWDG reset\r\n");}elseif(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST)){printf("[RST] IWDG reset\r\n");}elseif(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST)){printf("[RST] POR/PDR reset\r\n");}/* 清理复位标志,否则下次上电读到的还是旧状态 */__HAL_RCC_CLEAR_RESET_FLAGS();}

测试验证:四组实验对照理论

实验环境固定:STM32F103C8T6,主频 72MHz(PCLK1=36MHz),示波器探头接 NRST,串口 115200 打印复位原因。所有时间测量取 10 次平均值。

每次喂狗动作都要过一遍窗口判断,这个决策链可以用下面的流程表示,实验二的喂狗时刻扫描就是沿着这条链在不同位置落点:

否, CNT > W

是

否, 已减到 0x3F

是, 窗口内

到达喂狗点

CNT 是否 ≤ 窗口 W?

提前喂狗
立即产生复位

CNT 是否 ≥ 0x40?

超时
已复位

写 WWDG_CR 重载
计数器回到装载值 T

继续递减, 进入下一轮

实验一:不喂狗,测完整超时周期(理论 vs 实测对照 1)

程序启动 WWDG 后不喂狗,示波器测量 NRST 上两次复位脉冲的时间间隔:

预分频 WDGTB理论超时 (T=0x7F)实测周期偏差说明
0(÷1)7.28 ms7.30 ms+0.27%晶振 8MHz 实测略偏快
1(÷2)14.56 ms14.58 ms+0.14%同源偏差
2(÷4)29.13 ms29.15 ms+0.07%偏差随周期线性放大
3(÷8)58.25 ms58.30 ms+0.09%本文主实验参数

四档预分频全部命中公式预期,偏差方向一致且小于 0.3%,来源是开发板 8MHz 无源晶振的实际频率略高于标称值(用频率计核对过,晶振输出 8.0002MHz 附近)。这个 0.1%~0.3% 的系统性偏差说明公式本身无误,工程上不需要为此修正参数。

实验二:窗口外提前喂狗(量化参数对比)

保持 T[6:0]=0x7F、W[6:0]=0x5C、WDGTB=3,在启动后不同时刻执行一次喂狗,记录芯片是否复位以及复位延迟:

喂狗时刻CNT 估算值是否复位复位延迟原因
5 ms约 121(> 窗口 92)是立即(< 1μs)提前喂狗,窗口外
20 ms约 105(> 窗口 92)是立即提前喂狗,窗口外
30 ms约 94(> 窗口 92)是立即还差 2 tick 进窗口
32 ms约 92(= 窗口值)否—进入窗口边界,喂狗合法
40 ms约 83(窗口内)否—窗口内,正常重载
55 ms约 67(窗口内)否—窗口内,临近 EWI 触发点

窗口开启的理论时刻是 31.87ms(35 个 tick),实测在 32ms 处喂狗已能通过、30ms 处仍复位,翻转点落在 31~32ms 之间,与公式吻合在 1ms 以内——这证明窗口判断是逐 tick 精确执行的,也反过来说明了窗口参数 W 的计算误差会直接变成误复位或漏保护。我一开始把窗口值拍脑袋设成 0x60(96),结果主循环里一次 20ms 的 SD 卡写操作就触发了提前喂狗复位,改成按公式算出来的 0x5C 才稳定——窗口值必须根据实际任务的最长执行时间反推,不能随手填。

实验三:EWI 喂狗 vs 主循环喂狗

喂狗策略喂狗周期是否复位CPU 额外开销
不喂狗—是(58.3ms 周期)0
主循环喂狗(每 30ms)30 ms否约 1.2μs/次
EWI 中断喂狗58.3 ms(每轮 1 次)否中断进出开销
主循环喂狗(每 60ms)60 ms是(喂狗前已复位)—

结论:EWI 中断喂狗对主循环零侵入,是生产环境的首选;主循环喂狗适合演示窗口机制,但必须保证最坏情况下的喂狗间隔落在窗口内。实测主循环喂狗单次 HAL_WWDG_Refresh 耗时约 1.2μs(72MHz 下寄存器读写+函数调用),可以忽略。

实验四:复位标志验证

分别触发 WWDG 复位、手动按键复位(NRST 拉低)、上电复位,串口打印如下:

[RST] WWDG reset ← 提前喂狗/超时喂狗触发 [RST] POR reset ← 断电重上电

复位标志位能准确区分复位源,故障排查时第一件事就该做这个,能省掉大量猜谜时间。

故障排查:6 类高频问题与完整排查链

问题 1:一上电就不断复位,LED 疯狂闪烁

现象:程序烧进去后板子每 58ms 复位一次,串口打出一串 WWDG reset。排查链:先用复位原因检测确认是 WWDG 复位(排除电源问题);然后在主循环开头加一个喂狗测试点,发现喂狗代码根本没执行到——再往下查,原来是初始化完成后、进入主循环前有一段较长的外设初始化(约 70ms 的 Flash 擦写测试),WWDG 在窗口期还没到时就已超时复位。根因:装载值 0x7F 下超时只有 58ms,装不下"启动即长耗时"的初始化序列。解决:把 WWDG 启动挪到初始化完成之后,或把装载值调大(F103 上限就是 0x7F,58ms,确实不够就得把耗时初始化拆到喂狗之后)。验证:初始化完成后 1ms 内启动 WWDG,不再复位。

问题 2:程序跑一段时间后偶发复位

现象:正常运行几秒到几十秒后随机复位,复位标志为 WWDG。排查链:最初怀疑是喂狗间隔抖动,把喂狗周期从 40ms 缩到 20ms 仍偶发;用 GPIO 翻转+示波器抓喂狗时序,发现某次 SD 卡写入时喂狗延迟了 30ms+,刚好错过窗口末端。根因:主循环喂狗被长任务阻塞,喂狗时刻滑出了窗口。解决:改用 EWI 中断喂狗(中断优先级高于长任务),主循环不再负责喂狗。验证:连续跑 72 小时无复位,喂狗计数与理论值一致(58.3ms 周期 × 时长)。

问题 3:调试模式下反复复位,断点停不住

现象:点击 Debug 进入后程序立即重启,全速运行正常但单步就复位。排查链:查了代码逻辑没问题,串口打印正常,怀疑是调试器与看门狗冲突;搜索后发现是 WWDG 在调试暂停时继续计数导致的。根因:DBGMCU_CR.DBG_WWDG_STOP未置位,CPU 停在断点时 PCLK1 照跑,WWDG 照减。解决:初始化时置位 DBG_WWDG_STOP(见"容易遗漏的步骤"一节)。验证:置位后断点可以正常停住,不再复位。这个问题在很多新手工程里是隐藏的——平时不调试看不出,一接调试器就"水土不服"。

问题 4:EWI 中断从不触发

现象:代码里写了 EWI 回调,但 g_wwdg_feed_count 一直是 0,芯片直接复位。排查链:先在回调入口打点,确认回调没进;查 NVIC,发现 CubeMX 生成的HAL_NVIC_EnableIRQ(WWDG_IRQn)因为我在 NVIC 页没勾选而没生成;补上后回调进了,但喂狗后仍复位——再查是回调里没清 EWIF 标志,导致中断反复进入、标志判断逻辑混乱。根因:EWI 的 NVIC 使能被遗漏 + EWIF 标志未在回调中清除。解决:NVIC 页勾选 WWDG 中断,回调里先__HAL_WWDG_CLEAR_FLAG再喂狗。验证:喂狗计数按周期增长,串口观察无复位。

问题 5:低功耗 STOP 模式下异常复位

现象:进入 STOP 模式后唤醒,发现系统被复位过,复位标志是 WWDG。排查链:起初以为是唤醒源问题;查手册发现 F103 的 WWDG 时钟来自 PCLK1,STOP 时 PCLK1 停止、WWDG 计数暂停,理论上不该复位——但实测唤醒后确实有 WWDG 复位标志。进一步分析:进入 STOP 前如果刚好执行了喂狗,计数器停在窗口内某个值,唤醒后继续递减,若唤醒代码耗时超过剩余窗口时间就复位。根因:唤醒后的初始化路径耗时超过了 STOP 前遗留的窗口余量。解决:唤醒后第一时间喂狗(此时 CNT 仍在窗口内,喂狗合法),再执行外设恢复。验证:唤醒路径首行喂狗后,1000 次 STOP 唤醒循环零复位。关于 STOP 模式的更多细节可参考我之前写的 《STM32F103 STOP模式低功耗实战》 系列,低功耗与看门狗叠加时坑特别多。

问题 6:复位标志永远读不到 WWDG

现象:明明发生了 WWDG 复位,但RCC_FLAG_WWDGRST读出来是 0。排查链:读 RCC_CSR 寄存器原始值,发现复位标志在第一次读取前就被清了;原来是启动代码或库函数在 main 之前调用了__HAL_RCC_CLEAR_RESET_FLAGS()。根因:复位标志只在复位后保持到软件主动清除,若早期代码清了就丢了。解决:把复位原因检测放在 main 最开头、任何清标志操作之前,且只清一次。验证:先读后清,标志位准确保留。

总结

WWDG 用"窗口"这个精巧的机制,把看门狗从"活着就行"升级成"按节奏活着才行",是嵌入式系统抗软故障的重要一环。本文的核心要点:

  1. WWDG 是 7 位递减计数器,挂在 PCLK1 上,递减到 0x3F 复位,窗口外喂狗立即复位,窗口内喂狗重载装载值;
  2. 超时周期用Tout = 4096 × 2^WDGTB × (T[6:0] − 0x3F) / Fpclk1计算,F103 最大约 58.25ms,网上流传的(T+1)公式在这个芯片上会算错一倍;
  3. 四档预分频实测与公式偏差均小于 0.3%,窗口边界逐 tick 精确,30ms 喂狗复位、32ms 通过的实测就是铁证;
  4. 生产环境优先用 EWI 中断喂狗,调试时记得置位DBGMCU_CR.DBG_WWDG_STOP,否则断点根本停不住。

适用边界:WWDG 只适合监控"主时钟活跃、节奏可预期"的任务流程;需要深度休眠期间继续监控的场合必须用 IWDG。它的超时上限(F103 约 58ms)意味着慢节奏任务要么缩短初始化路径,要么换方案,这是硬件决定的。已知局限:WWDG 的装载值上限就是 0x7F,窗口值必须小于等于装载值,参数调节空间有限;喂狗重载值固定为装载值,无法像 IWDG 那样灵活重配。扩展方向:可以进一步研究 WWDG + FreeRTOS 的结合——把喂狗挂到空闲任务钩子里,配合任务栈高水位统计,构建更完整的系统健康监控;也可以对比 F4/H7 系列 WWDG 与 F1 在时钟域和寄存器布局上的差异,跨系列移植时这些都是隐性成本。关于 WWDG 的更多原理性内容,推荐这篇:《STM32窗口看门狗WWDG详解》,以及 HAL 库视角的这篇:《STM32HAL库-03-WWDG窗口看门狗》。如果你也遇到过"上电不断复位"的怪问题,这篇蓝桥杯同学的踩坑记录值得一看:《蓝桥杯嵌入式学习STM32之窗口看门狗(WWDG)及一直复位的解决办法》。如需获取本文完整代码和更多实战项目,可开通 CSDN 技术会员。

版本备注

  • 硬件平台:STM32F103C8T6 最小系统板(8MHz 无源晶振),USB 转 TTL,示波器接 NRST
  • 软件版本:STM32CubeMX 6.10 + STM32CubeF1 HAL 库 1.8.6,Keil MDK 5.38
  • 兼容说明:F103 全系通用;F4 系列寄存器布局相同(DBGMCU_CR.DBG_WWDG_STOP 位置一致),H7 系列的 WWDG 冻结位在 DBGMCU_APB1FZR,移植需调整;L4 系列无 WWDG,需用独立看门狗替代
  • API 变更风险:HAL 库 1.8.x 的HAL_WWDG_Refresh()行为与早期 1.6.x 一致(写 CR 重载),但__HAL_WWDG_CLEAR_FLAG宏在 1.8.x 新增了句柄参数断言,1.6.x 工程升级需同步改宏调用

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询