STM32 IWDG(独立看门狗)

1 IWDG简介

STM32有两个看门狗:一个是独立看门狗(IWDG),另外一个是窗口看门狗。独立看门狗也称宠物狗,窗口看门狗也称警犬。本文主要分析独立看门狗的功能和它的应用。

独立看门狗用通俗一点的话来解释就是一个12位的递减计数器,当计数器的值从某个值一直减到0的时候,系统就会产生一个复位信号,即IWDG_RESET。如果在计数器没减到0之前,刷新了计数器的值的话,那么就不会产生复位信号,这个动作就是我们经常说的"喂狗"。看门狗功能由VDD供电,在停止模式和待机模式下仍能工作。

2 IWDG功能框图剖析

IWDG功能框图如下图所示:

2.1 独立看门狗时钟

独立看门狗的时钟由独立的RC震荡器LSI提供,即使主时钟发生故障它仍然有效,非常独立。LSI的频率一般为30~60kHz,根据温度和工作场合情况有一定的漂移。我们一般取40kHz,所以独立看门狗的定时时间不是非常精确,只适用于对时间精度要求比较低的场合。

2.2 计数器时钟

递减计数器的时钟由LSI经过一个8位的预分频器得到,我们可以操作预分频器寄存器IWDG_PR来设置分频因子,分频因子可以是:4,8,16,32,64,128,256,计数器时钟CK_CNT=40/4×2^PRV,一个计数器时钟周期计数器就减一。

2.3 计数器

独立看门狗的计数器是一个12位的递减计数器,最大值为0XFFF。当计数器减到0时,会产生一个复位信号IWDG_RESET,让程序重新启动运行。如果在计数器减到0之前刷新了计数器的值的话,就不会产生复位信号,重新刷新计数器值的这个动作俗称"喂狗"。

2.4 重装载寄存器

重装载寄存器是一个12位的寄存器,里面装着要刷新到计数器的值,这个值的大小决定独立看门狗的溢出时间。超时时间Tout=(4×2^prv)/40×rlv(s),prv是预分频器寄存器的值,rlv是重装载寄存器的值。

2.5键寄存器

键寄存器IWDG_KR可以说是独立看门狗的一个控制寄存器,主要有三种控制方式,往这个寄存器写入下面3个不同的值有不同的效果。

|--------|----------------|
| 键值 | 键值作用 |
| 0XAAAA | 把RLR的值重装载到CNT |
| 0X5555 | PR和RLR这两个寄存器可写 |
| 0XCCCC | 启动 IWDG |
[键寄存器取值枚举]

通过写往键寄存器写0XCCCC来启动看门狗属于软件启动的方式,一旦独立看门狗启动,它就关不掉,只有复位才能关掉它。

2.6 状态寄存器

状态寄存器SR只有位0,PVU和位1:RVU有效,这两位只能由硬件操作,软件操作不了。

RVU:看门狗计数器重装载值更新,硬件置1表示重装载值的更新正在进行中,更新完毕之后由硬件清0.

PVU:看门狗预分频值更新,硬件置1指示预分频值的更新正在进行中,当更新完成后,由硬件清0。

所以只有当RVU、PVU都等于0的时候,才可以更新重装载寄存器和预分频寄存器。

3 如何使用IWDG

独立看门狗一般用来检测和解决由程序引起的故障,比如一个程序正常运行的时间是50ms,在运行完这段程序之后紧接着进行喂狗,我们设置独立看门狗的定时溢出时间为60ms,比我们需要监控的程序50ms多一点。如果超过60ms还没有喂狗,那就说明我们的监控程序出故障了,运行出意外了,那么就会产生系统复位,让程序重新运行。

3.1 IWDG 配置函数

cpp 复制代码
void IWDG_Config(uint8_t prv,uint16_t rlv)
{
    //使能预分频寄存器PR和重装载寄存器RLR可写
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);

    //设置预分频器值
    IWDG_SetPrescaler(prv);

    //设置重装载寄存器值
    IWDG_RetReload(rlv);

    //把重装载寄存器的值放到计数器中
    IWDG_ReloadCounter();

    //使能IWDG
    IWDG_Enable();

}

IWDG配置函数有两个形参,prv用来设置预分频的值,可取值如下:

cpp 复制代码
/*
*    @arg IWDG_Prescaler_4:      IWDG 预分频值设置为4
*    @arg IWDG_Prescaler_8:      IWDG 预分频值设置为8
*    @arg IWDG_Prescaler_16:     IWDG 预分频值设置为16
*    @arg IWDG_Prescaler_32:     IWDG 预分频值设置为32
*    @arg IWDG_Prescaler_64:     IWDG 预分频值设置为64
*    @arg IWDG_Prescaler_128:    IWDG 预分频值设置为128
*    @arg IWDG_Prescaler_256:    IWDG 预分频值设置为256
*/

如果我们需要设置1s的超时溢出,prv可以取IWDG_Prescaler_64,rlv取625,即调用IWDG使得Tout=64/40*625=1s。

3.2 喂狗函数

cpp 复制代码
void IWDG_Feed(void)
(
    //把重装载寄存器的值放到计数器中,喂狗,防止IWDG复位
    //当计数器的值减到0的时候会产生系统复位
    IWDG_ReloadCounter();
)

3.3 main函数

cpp 复制代码
int main(void)
{
    //配置LED GPIO,并关闭LED
    LED_GPIO_Config();

    Delay(0X8FFFFF);
    //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    //检查是否为独立看门狗复位
    if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST)!=RESET)
    {
        //独立看门狗复位
        //亮红灯
        LED_RED;

        //清除标志
        RCC_ClearFlag();

        //如果一直不能喂狗,会一直复位,加上前面的延时,会看到红灯闪烁
        //在1s时间内喂狗的话,则会持续亮绿灯
    }
    else
    {
        //不是看门狗复位(可能为上电复位或者手动按键复位之类的操作)
        //亮蓝灯
        LED_BLUE;
    }
    //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    //配置按键GPIO
    Key_GPIO_Config();
    //IWDG 1s超时溢出
    IWDG_Config(IWDG_Prescaler_64,625);

    //while部分是我们在项目中具体要写的代码,这部分的程序可以用独立看门狗来监控
    //如果我们知道这部分代码执行的时间,比如500ms,那么我们可以设置独立看门狗的溢出时间是600ms
    //比500ms多一点,如果要被监控的程序没出意外,正常执行的话,那么执行完毕之后就会执行喂狗程序
    //如果程序出意外了那程序就会超时,到达不了喂狗的程序,此时就会产生系统复位。
    //但是也不排除程序出意外了又恢复正常了,刚好喂狗了,歪打正着。所以要想更精确得监控程序
    //可以使用窗口看门狗,窗口看门狗规定必须在规定的窗口时间内喂狗
    while(1)
    {
    //这里添加需要被监控的代码,如果有就去掉按键模拟喂狗,把按键扫描程序去掉
    //------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        if(Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==KEY_ON)
        {
            //喂狗,如果不喂狗,系统就会复位,LED1就会灭一次
            //如果在1s时间内准时喂狗的话,则绿灯会亮,否则红灯闪烁
            IWDG_Feed();
            //喂狗后亮绿灯
            LED_GREEN;
        }
    }
    //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
}
相关推荐
熙芯XiChip5 分钟前
硬实时与软实时RTOS核心区别
嵌入式硬件
伟大的前程20 分钟前
unsigned int 定义的变量 在 电脑的 64 位系统中 和 32 位 cortex-m0 和 8 位的 51 单片机
单片机·嵌入式硬件
小渔村的拉线工38 分钟前
1.HPM6E80 解析芯片整体工作原理和存储架构
单片机·嵌入式硬件·mcu·架构·hpm6e80
熙芯XiChip2 小时前
CAN与CANopen的本质区别
单片机
lilihewo2 小时前
Altium Designer 封装库的创建(分享pcb 3D封装库)
嵌入式硬件·51单片机
神罚天下ET3 小时前
典型arm位单片机启动流程(从上电到main.c)
c语言·arm开发·单片机
碧海银沙音频科技研究院4 小时前
蓝牙耳机使用WSDF5361锂保芯片进入船运模式实现方法
嵌入式硬件·算法
Zevalin爱灰灰4 小时前
模拟信号链电路——基于TL431的电压基准电路
单片机·嵌入式硬件
csdn杰哥5 小时前
瑞萨单片机开发教程[二十七] DTC 外部中断触发传输实验
单片机·嵌入式硬件·mongodb·瑞萨·ra6m5
zcmodeltech5 小时前
农业教学实训沙盘物联网控制系统设计:基于STM32与Modbus RTU的“感知-控制-实训”一体化方案
分布式·stm32·嵌入式硬件·物联网