第四讲:STM32平台看门狗实战

STM32 IWDG配置步骤

好,咱们直接进入正题。STM32的独立看门狗,简称IWDG,说白了就是一个独立于主系统之外的定时器。它自己跑自己的,就算主程序死机了,它照样计时。一旦超时没被喂狗,它就强制复位整个芯片。

我刚开始用STM32时,总觉得看门狗配置挺麻烦的。后来发现,其实就那么几个步骤,走一遍就熟了。

第一步:开启LSI时钟

IWDG的时钟源是LSI,也就是低速内部振荡器。这个时钟大概40kHz,但不同芯片有差异。你需要先把它使能起来。

RCC_LSICmd(ENABLE);  // 开启LSI时钟
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); // 等待稳定

第二步:取消写保护

IWDG的寄存器默认是写保护的。你得先解锁,才能配置预分频器和重装载值。

IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);  // 取消写保护

第三步:配置预分频器和重装载值

这一步是关键。预分频器决定时钟分频倍数,重装载值决定计数时长。两者配合,算出你想要的超时时间。

IWDG_SetPrescaler(IWDG_Prescaler_64);   // 预分频64
IWDG_SetReload(0xFFF);                  // 重装载值4095

第四步:重装载计数器并启动

配置完成后,把重装载值写入计数器,然后启动看门狗。

IWDG_ReloadCounter();   // 喂一次狗,把重装载值写入计数器
IWDG_Enable();          // 启动看门狗

嗯,这里要注意:一旦使能IWDG,就无法再关闭了。除非你复位芯片。所以调试阶段,我建议先别急着开狗,等程序稳定了再打开。

预分频器与重装载值计算

这个计算其实不复杂,但很多人容易搞混。我给大家拆开讲。

超时时间的公式是这样的:

Tout = (4 × 2^预分频系数) × 重装载值 / LSI频率

其中预分频系数可以取0、1、2、3、4、5、6,对应分频倍数4、8、16、32、64、128、256。

举个例子,假设LSI频率是40kHz,我选预分频64,重装载值4095:

Tout = (4 × 2^4) × 4095 / 40000
     = 64 × 4095 / 40000
     ≈ 6.55秒

也就是说,大约6.55秒内必须喂一次狗,否则芯片复位。

我在项目中遇到过一个问题:LSI频率其实不太准,不同芯片之间可能有±10%的偏差。所以计算出来的时间只是个参考值。实际使用时,我一般会留出30%的余量。比如我需要5秒超时,我会按3.5秒来配置。

常用配置参考表(LSI=40kHz)

预分频系数 分频倍数 重装载值 超时时间
0 4 0xFFF 0.41秒
2 16 0xFFF 1.64秒
4 64 0xFFF 6.55秒
6 256 0xFFF 26.21秒

你想想看,如果我要一个2秒左右的超时,选预分频16、重装载值2000,算出来大概1.28秒。嗯,留点余量,实际用起来刚好。

喂狗函数编写

喂狗函数其实就一句话:

void IWDG_Feed(void)
{
    IWDG_ReloadCounter();  // 把重装载值重新写入计数器
}

就这么简单。但关键是——在哪里喂狗

我见过不少新手把喂狗放在主循环里:

while(1)
{
    IWDG_Feed();
    // 其他任务...
}

这样做有个问题:就算其他任务卡死了,主循环还在跑,喂狗照常执行。看门狗根本起不到作用。

我个人习惯的做法是:在关键任务完成后喂狗。比如传感器采集、数据处理、显示刷新,每个大任务完成后喂一次。这样如果某个任务卡住,看门狗就会复位。

void main_task(void)
{
    while(1)
    {
        if(sensor_read() == SUCCESS)
        {
            IWDG_Feed();  // 传感器读取成功,喂狗
        }
        
        if(data_process() == SUCCESS)
        {
            IWDG_Feed();  // 数据处理完成,喂狗
        }
        
        display_update();  // 显示刷新
        IWDG_Feed();       // 刷新完成,喂狗
    }
}

小技巧:在调试阶段,可以用一个全局变量记录喂狗次数。如果发现喂狗次数异常,说明某个任务执行时间过长。我曾经用这个方法抓到一个传感器驱动里的死循环bug。

警告:不要在中断服务函数里喂狗!如果主程序死机但中断还能响应,看门狗会被中断一直喂着,永远不复位。这是很多嵌入式工程师踩过的坑,包括我。

好了,这一讲的内容就这些。配置步骤、预分频器计算、喂狗函数,三个知识点串起来,你就能在STM32上用好独立看门狗了。下一讲我们聊聊窗口看门狗,那个玩法又不一样了。