2. 看门狗工作原理:定时器基础、喂狗机制、超时复位流程、窗口看门狗与独立看门狗的区别

看门狗这东西,说白了就是一个会咬人的定时器。你如果不按时去喂它,它就咬你——把整个系统复位。听起来有点暴力,但嵌入式系统里,这反而是最温柔的守护者。

我刚开始做嵌入式那几年,总觉得看门狗是个累赘。直到有一次,一个工业控制项目在现场跑着跑着就死机了,客户半夜打电话过来骂人。从那以后,我设计的每一块板子,看门狗都是标配。

2.1 定时器基础:看门狗的“心脏”

看门狗的核心就是一个递减计数器。它从某个初始值开始,每个时钟周期减1。减到0的时候,就触发复位信号。

关键参数:

  • 计数初值:决定超时时间的长短
  • 时钟源:独立看门狗用内部RC振荡器,窗口看门狗用系统时钟
  • 分频系数:调整计数速度,扩展超时范围

举个例子,STM32的独立看门狗(IWDG),时钟源是40kHz的内部RC振荡器。如果设置分频系数为64,那么计数频率就是40kHz / 64 = 625Hz。再设置计数初值为1000,超时时间就是1000 / 625 = 1.6秒。

// STM32 IWDG 初始化示例
void IWDG_Init(void)
{
    // 使能写访问
    IWDG->KR = 0x5555;
    
    // 设置分频系数为64
    IWDG->PR = IWDG_Prescaler_64;
    
    // 设置计数初值为1000
    IWDG->RLR = 1000;
    
    // 启动看门狗
    IWDG->KR = 0xCCCC;
}

我的经验:独立看门狗的时钟精度不高,一般误差在5%~10%左右。设计超时时间时,要留够余量。我习惯把超时时间设为主循环周期的3~5倍,既不会误触发,也不会让系统长时间失控。

2.2 喂狗机制:定时器“续命”操作

喂狗,就是把计数器的值重新装回初始值。这样计数器就不会减到0,系统也就不会被复位。

喂狗操作通常放在主循环里,或者放在某个周期性执行的任务中。但这里有个坑——喂狗的位置和频率,直接决定了看门狗的保护效果。

// 正确的喂狗方式
void main(void)
{
    // 系统初始化
    System_Init();
    IWDG_Init();
    
    while(1)
    {
        // 执行关键任务
        Task_Communication();
        Task_SensorRead();
        Task_ControlOutput();
        
        // 所有任务执行完毕后喂狗
        IWDG->KR = 0xAAAA;
    }
}

我曾经踩过的坑:有次我把喂狗操作放在了一个中断服务函数里。结果主程序卡死了,中断还在正常触发,看门狗一直没复位。系统死得悄无声息,现场调试了两天才发现。记住:喂狗一定要放在主循环的关键路径上,不能放在中断里。

2.3 超时复位流程:从计数到复位的完整路径

看门狗的超时复位流程,其实就三步:

  1. 计数递减:每个时钟周期,计数器减1
  2. 超时触发:计数器减到0,产生复位信号
  3. 系统复位:复位信号拉低MCU的复位引脚,系统重新启动

这里有个细节要注意——复位信号持续的时间。不同芯片的复位脉冲宽度不一样,STM32的IWDG复位脉冲大约是5个RC时钟周期。如果复位脉冲太短,某些外设可能来不及复位干净。

复位后的处理:

  • 检查复位原因寄存器,确认是否由看门狗触发
  • 记录复位次数,判断系统是否频繁复位
  • 如果是看门狗复位,不要立即喂狗,先排查问题
// 复位原因检查
void Check_ResetSource(void)
{
    if (RCC->CSR & RCC_CSR_IWDGRSTF)
    {
        // 独立看门狗复位
        printf("System reset by IWDG!\n");
        
        // 清除标志位
        RCC->CSR |= RCC_CSR_RMVF;
    }
}

2.4 窗口看门狗与独立看门狗的区别

这两种看门狗,虽然都叫看门狗,但脾气完全不同。我画了一张对比图,方便你理解。

窗口看门狗 vs 独立看门狗 独立看门狗(IWDG) 时钟源:内部RC振荡器 (独立于系统时钟) 喂狗窗口:0 ~ 超时值 (任何时候喂狗都有效) 超时范围:宽(ms ~ s) (分频系数可调) 复位方式:系统复位 (直接拉低复位引脚) 窗口看门狗(WWDG) 时钟源:系统时钟(APB) (与系统时钟同步) 喂狗窗口:上窗口 ~ 下窗口 (必须在指定时间窗口内喂狗) 超时范围:窄(us ~ ms) (精度高,适合实时系统) 复位方式:系统复位 + 早期唤醒 (可提前中断预警) 选择哪种看门狗,取决于你的系统对实时性和精度的要求

两种看门狗的核心区别,我整理成了表格:

对比项 独立看门狗(IWDG) 窗口看门狗(WWDG)
时钟源 内部RC振荡器(独立) 系统时钟(APB总线)
时钟精度 低(5%~10%误差) 高(与系统时钟一致)
喂狗窗口 0 ~ 超时值(任意时刻) 上窗口 ~ 下窗口(限定范围)
超时范围 宽(毫秒到秒级) 窄(微秒到毫秒级)
复位方式 系统复位 系统复位 + 早期唤醒中断
典型应用 系统死机保护 任务超时检测

选型建议:

  • 独立看门狗:适合对时间精度要求不高,但需要绝对可靠的场景。比如工业控制、汽车电子。
  • 窗口看门狗:适合对任务执行时间有严格要求的场景。比如通信协议栈、实时操作系统。

我个人习惯,在大多数项目里同时使用两种看门狗。独立看门狗做最后一道防线,窗口看门狗做任务级的超时检测。这样既保证了系统的可靠性,又能及时发现任务异常。

一个实用技巧:窗口看门狗的早期唤醒中断(EWI)特别好用。在计数器即将超时前,可以触发中断,记录现场信息。这样即使系统最终复位了,也能知道问题出在哪里。我在一个电机控制项目里就用这个功能抓到了好几次任务调度异常。

嗯,看门狗的工作原理其实不复杂。但真正用好它,需要理解它的脾气秉性。独立看门狗像个粗犷的保安,只要按时打卡就行;窗口看门狗像个严格的监工,必须在规定时间内完成任务。选哪个,怎么用,全看你的系统需求。