CH32V203/208-看门狗的学习

1.什么是看门狗

由单片机构成的微型计算机系统中,单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞而陷入死循环;或者因为用户配置代码出现错误,导致芯片无法正常工作。出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”(watchdog)。简单说:看门狗的本质就是定时计数器,计数器使能之后一直在累加;而“喂狗”就是重新写入计数器的值,使得计数器重新累加;如果在一定时间内没有接收到“喂狗”信号(表示MCU已经停止工作),便进行处理器的自动复位重启(发送复位信号)。

CH32V103系列内置两个看门狗,提供了更高的安全性和时间的精确性以及使用的灵活性。两个看门狗设备(独立看门狗、窗口看门狗)可以用来检测和解决由外界电磁干扰、软件错误引起的故障。当计数器达到给定的超时值时,触发一个中断(仅适用于窗口看门狗)或者产生系统复位。

独立看门狗用来检测逻辑错误和外部环境干扰引起的软件故障。独立看门狗时钟源来自LSI,可独立于主程序运行,适用于对精度要求较低的场合。

窗口看门狗一般用来监测系统运行的软件故障,例如外部干扰、不可预见的逻辑错误等。它需要在一个特定的窗口时间(有上下限)内进行计数器刷新(喂狗),早于或者晚于这个窗口时间,看门狗电路都会产生系统复位信号。

2.相关的函数及说明:

序 号

函数名称

功能描述

1

IWDG_ WriteAccessCmd

使能或者失能操作键值锁

2

IWDG_SetPrescaler

设置IWDG预分频值

3

IWDG_SetReload

设置IWDG重装载值

4

IWDG_ReloadCounter

将IWDG重载寄存器的值重新装载到 IWDG 计数值

5

IWDG_Enable

使能IWDG

6

IWDG_GetFlagStatus

检查指定的IWDG标志位

7

WWDG_DeInit

将WWDG外设寄存器配置为默认值

8

WWDG_SetPrescaler

设置 WWDG预分频值

9

WWDG_SetWindowValue

设置 WWDG窗口值

10

WWDG_EnableIT

使能 WWDG早期唤醒中断

11

WWDG_SetCounter

设置 WWDG计数器值

12

WWDG_Enable

使能WWDG并装入计数值

13

WWDG_GetFlagStatus

检查早期唤醒中断标志位是否置位

14

WWDG_ClearFlag

清除 WWDG 早期唤醒中断标志位

3.官方例程的学习:

/*
 * Userpinmux.c
 *
 *  Created on: 2023年7月5日
 *      Author: 86195
 */

#ifndef USER_USERPINMUX_C_
#define USER_USERPINMUX_C_
#include "Userpinmux.h"
#include "debug.h"
Void WWDG_IROHandler(void)__attribute((interrupt("WCH- Interrupt-fast")));
void WWDG_ IROHandler(void)
{
WWDG_Feed();//窗口看门狗喂狗
printf("wwDG_Feed\r\n");
WWDG_ClearFlag();//清除WWDG标志位
}
void WWDG_ NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;//配置WWDG中断向量
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//设置抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;//设置响应优先级为2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能 WWDG中断向量
NVIC_Init(&NVIC_InitStructure);//初始化wwDG中断
}
void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv)
{
RCC_APBI PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);//使能WWDG时钟
WWDG_SetCounter( tr );//更新WWDG计数器
WWDG_SetPrescaler( prv );//设置WWDG预分频值
WWDG_SetWindowValue( wr );//设置窗口值
WWDG_Enable(WWDG_CNT);//使能 WWDG计数
WWDG_ClearFlag();//清除标志
WWDG_NVIC_Config();//配置WWDG中断
WWDG_EnableIT();//使能WWDG中断
}
void WWDG_Feed(void)
{
WWDG_SetCounter( WWDG_CNT);//更新WWDG计数器
}
int main(void)
{
    u8 wwdg_tr, wwdg_wr;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n", SystemCoreClock);

    printf("WWDG Test\r\n");
    WWDG_Config(0x7f, 0x5f, WWDG_Prescaler_8); /* 48M/8/4096 */
    wwdg_wr = WWDG->CFGR & 0x7F;
    while(1)
    {
        Delay_Ms(10);

        printf("**********\r\n");
        wwdg_tr = WWDG->CTLR & 0x7F;
        if(wwdg_tr < wwdg_wr)
        {
            WWDG_Feed();
        }
        printf("##########\r\n");
    }
}

4.对官方例程的修改:

/*
 * Userpinmux.c
 *
 *  Created on: 2023年7月5日
 *      Author: 86195
 */

#ifndef USER_USERPINMUX_C_
#define USER_USERPINMUX_C_
#include "Userpinmux.h"
#include "debug.h"
Void WWDG_IROHandler(void)__attribute((interrupt("WCH- Interrupt-fast")));
void WWDG_ IROHandler(void)
{
WWDG_Feed();//窗口看门狗喂狗
printf("wwDG_Feed\r\n");
WWDG_ClearFlag();//清除WWDG标志位
}
void WWDG_ NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;//配置WWDG中断向量
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//设置抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;//设置响应优先级为2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能 WWDG中断向量
NVIC_Init(&NVIC_InitStructure);//初始化wwDG中断
}
void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv)
{
RCC_APBI PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);//使能WWDG时钟
WWDG_SetCounter( tr );//更新WWDG计数器
WWDG_SetPrescaler( prv );//设置WWDG预分频值
WWDG_SetWindowValue( wr );//设置窗口值
WWDG_Enable(WWDG_CNT);//使能 WWDG计数
WWDG_ClearFlag();//清除标志
WWDG_NVIC_Config();//配置WWDG中断
WWDG_EnableIT();//使能WWDG中断
}
void WWDG_Feed(void)
{
WWDG_SetCounter( WWDG_CNT);//更新WWDG计数器
}

void EXTI15_10_IROHandler(void)_attribute__((interrupt("wCH- Interrupt-fast")));
void EXTI15_10_IROHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line15)! =RESET){
printf("EXTI15\r\n");
EXTI_ClearITPendingBit(EXTI_Line15);
while(1);//进入死循环
}
}
void EXTI15_10_INT_INIT(void)
{
GPIO_InitTypeDef  GPIO_InitStructure;
EXTI_InitTypeDef   EXTI_InitStructure;
NVIC_InitTypeDef  NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ AFIO|RCC_APB2Periph_ GPIOA,ENABLE);
GPIO_InitStructure. GPIO Pin = GPIO_ Pin 15;
GPIO_InitStructure. GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSourcel);
EXTI_InitStructure. EXTI Line = EXTI_Line15;
EXTI_InitStructure. EXTI_Mode = EXTI_Mode_Interrupt;
EXTI InitStructure. EXTI_Trigger = EXTI Trigger Falling;
EXTI_InitStructure. EXTI _LineCmd = ENABLE,
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure. NVIC_IRQChannel = EXTI15_10_IROn;
NVIC_InitStructure. NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure, NVIC_IRQChannelSubPriority =0;
NVIC_InitStructure. NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
    u8 wwdg_tr, wwdg_wr;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n", SystemCoreClock);
    EXTI15_10_INT_INIT();
    printf("WWDG Test\r\n");
    WWDG_Config(0x7f, 0x5f, WWDG_Prescaler_8); /* 48M/8/4096 */
    wwdg_wr = WWDG->CFGR & 0x7F;
    while(1)
    {

    }
}

需要注意:  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值