四、看门狗

一、独立看门狗

1、独立看门狗

        独立看门狗本质上是一个定时器,这个定时器有一个输出端,可以输出复位信号。

        该定时器是一个 12 位的递减计数器,当计数器的值减到 0 的时候,就会产生一个复位信号。如果在计数没减到 0 之前,重置计数器的值的话,那么就不会产生复位信号,这个动作我们称为喂狗

        看门狗功能由 VDD 电压域供电,在停止模式和待机模式下仍然可以工作。

 2、程序

/**
* @brief 初始化独立看门狗
* @param prer: IWDG_PRESCALER_4~IWDG_PRESCALER_256,对应 4~256 分频
* @arg 分频因子 = 4 * 2^prer. 但最大值只能是 256!
* @param rlr: 自动重装载值,0~0XFFF. 
* @note 时间计算(大概):Tout=((4 * 2^prer) * rlr) / 40 (ms). 
* @retval 无
*/
void iwdg_init(uint8_t prer, uint16_t rlr)
{
    g_iwdg_handle.Instance = IWDG;
    g_iwdg_handle.Init.Prescaler = prer; /* 设置 IWDG 分频系数 */
    g_iwdg_handle.Init.Reload = rlr; /* 重装载值 */
    HAL_IWDG_Init(&g_iwdg_handle);
}



/**
* @brief 喂独立看门狗
* @param 无
* @retval 无
*/
void iwdg_feed(void)
{ 
    HAL_IWDG_Refresh(&g_iwdg_handle); /* 重装载计数器 */
}



int main(void)
{
    HAL_Init(); /* 初始化 HAL 库 */
    sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
    delay_init(168); /* 延时初始化 */
    led_init(); /* 初始化 LED */
    key_init(); /* 初始化按键 */
    delay_ms(100); /* 延时 100ms 再初始化看门狗,LED0 的变化可见 */
    iwdg_init(IWDG_PRESCALER_64, 500); /* 预分频数为 64,重载值为 500,溢出时间约为 1s*/
    LED0(0); /* 点亮 LED0(红灯) */

    while(1)
    {
        if (key_scan(1) == WKUP_PRES) /* 如果 KEY_UP 按下,则喂狗,支持连按 */
        {
            iwdg_feed(); /* 喂狗 */
        }
        delay_ms(10);
    }
}

 二、窗口看门狗

1、窗口看门狗
        窗口看门狗通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。
        窗口看门狗跟独立看门狗一样,也是一个递减计数器,不同的是它们的复位条件不一样。窗口看门狗产生复位信号有两个条件:
        1) 当递减计数器的数值从 0x40 减到 0x3F 时( T6 位跳变到 0 )。
        2) 当喂狗的时候如果计数器的值大于 W[6:0] 时,此数值在 WWDG_CFR 寄存器定义。
        上述的两个条件详细解释是,当计数器的值减到 0x40 时还不喂狗的话,到下一个计数就会 产生复位,这个值称为窗口的下限值,是固定的值,不能改变。这个跟独立看门狗类似,不同的是窗口看门狗的计数器的值在减到某一个数之前喂狗的话也会产生复位,这个值叫窗口的上限,上限值 W[6:0]由用户设置。窗口看门狗计数器的上限值和下限值就是窗口的含义,喂狗也必须在窗口之内,否则就会复位。

2、程序
/**
* @brief 初始化窗口看门狗
* @param tr: T[6:0],计数器值
* @param tw: W[6:0],窗口值
* @param fprer: 分频系数(WDGTB),范围:WWDG_PRESCALER_1~WWDG_PRESCALER_8,
* 表示 2^WDGTB 分频, Fwwdg=PCLK1/(4096*2^fprer). 一般 PCLK1=42Mhz
* @retval 无
*/
void wwdg_init(uint8_t tr, uint8_t wr, uint32_t fprer)
{
    wwdg_handle.Instance = WWDG;
    wwdg_handle.Init.Prescaler = fprer; /* 设置分频系数 */
    wwdg_handle.Init.Window = wr; /* 设置窗口值 */
    wwdg_handle.Init.Counter = tr; /* 设置计数器值 */
    wwdg_handle.Init.EWIMode = WWDG_EWI_ENABLE; /* 使能窗口看门狗提前唤醒中断 */
    HAL_WWDG_Init(&wwdg_handle); /* 初始化 WWDG */
}

void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
{
    __HAL_RCC_WWDG1_CLK_ENABLE(); /* 使能窗口看门狗时钟 */
 
    HAL_NVIC_SetPriority(WWDG_IRQn, 2, 3); /* 抢占优先级 2,子优先级为 3 */
    HAL_NVIC_EnableIRQ(WWDG_IRQn); /* 使能窗口看门狗中断 */
}



/**
* @brief 窗口看门狗中断服务程序
* @param 无
* @retval 无
*/
void WWDG_IRQHandler(void)
{
    HAL_WWDG_IRQHandler(&g_wwdg_handle);
}

void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
{
    HAL_WWDG_Refresh(&g_wwdg_handle);/* 更新窗口看门狗值 */
    LED1_TOGGLE(); /* LED1 闪烁 */
}



// 主函数
int main(void)
{
    HAL_Init(); /* 初始化 HAL 库 */
    sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
    delay_init(168); /* 延时初始化 */
    usart_init(115200); /* 串口初始化为 115200 */
    led_init(); /* 初始化 LED */
    LED0(0); /* 点亮 LED0(红灯) */ 
    delay_ms(300); /* 延时 100ms 再初始化看门狗,LED0 的变化可见 */

    /* 计数器值为 7f,窗口寄存器为 5f,分频数为 8 */
    wwdg_init(0X7F, 0X5F, WWDG_PRESCALER_8);
    
    while(1)
    {
        LED0(1); /* 关闭 LED0(红灯) */
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌暴龙战士朵拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值