独立看门狗IWDG:
12位递减计数器,递减到0产生复位,如果到0前刷新了计数值,系统不会产生复位也就是喂狗

1:时钟源:来自内部时钟LSI;对时间精度低的场合
2:预分频器:---PR操控预分频因子
3:计数器
4:重装载值 设置溢出时间
5:键寄存器:控制寄存器 0x5555-关闭写保护;0xAAAA-计数递减重装载值给递减计数器;0xCCCC-启动功能
6:状态寄存器:硬件相关;
软件设计流程
- 开启寄存器访问(关闭写保护)
cs
/**
* @brief 配置独立看门狗(IWDG)的写访问权限
* @param IWDG_WriteAccess: 指定写访问模式
* 该参数可以是以下值之一:
* - IWDG_WriteAccess_Enable: 使能对IWDG_PR和IWDG_RLR寄存器的写访问
* - IWDG_WriteAccess_Disable: 禁止对IWDG_PR和IWDG_RLR寄存器的写访问(保护配置)
* @retval 无
*/
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess)
- 设置IWDG预分频系数和重转载值
cs
/**
* @brief 设置独立看门狗(IWDG)的预分频器值
* @param IWDG_Prescaler: 指定预分频系数
* 该参数可以是以下值之一:
* - IWDG_Prescaler_4: 预分频系数为4
* - IWDG_Prescaler_8: 预分频系数为8
* - IWDG_Prescaler_16: 预分频系数为16
* - IWDG_Prescaler_32: 预分频系数为32
* - IWDG_Prescaler_64: 预分频系数为64
* - IWDG_Prescaler_128: 预分频系数为128
* - IWDG_Prescaler_256: 预分频系数为256
* @retval 无
* @note 修改预分频器会影响看门狗的计时频率
*/
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler)
cs
/**
* @brief 设置独立看门狗(IWDG)的重装载值
* @param Reload: 指定重装载寄存器值(范围: 0x0000-0x0FFF)
* @retval 无
* @note 看门狗计数器会在达到0时复位系统
* 实际超时时间 = (重装载值 + 1) × 预分频时间周期
*/
void IWDG_SetReload(uint16_t Reload)
- 重装载计数器喂狗(0xAAAA)
cs
/**
* @brief 重载独立看门狗(IWDG)计数器
* @details 向IWDG_KR寄存器写入0xAAAA,触发计数器重装载操作
* 该操作会将IWDG_RLR寄存器的值重新加载到计数器中
* 从而避免看门狗超时复位
* @retval 无
* @note 必须在看门狗超时前定期调用此函数(喂狗)
*/
void IWDG_ReloadCounter(void)
- 开启
cs
/**
* @brief 使能独立看门狗(IWDG)
* @details 向IWDG_KR寄存器写入0xCCCC,启动独立看门狗计数器
* 一旦启用,看门狗将持续运行,无法通过软件禁用(除非复位)
* @retval 无
* @note 启用前必须配置好预分频器和重装载值
*/
void IWDG_Enable(void)
一旦开启无法关闭,复位后才能关闭
代码如下
cs
#include "iwdg.h"
/*******************************************************************************
* 函 数 名 : IWDG_Init
* 函数功能 : IWDG初始化
* 输 入 : pre:预分频系数(0-6)
rlr:重装载值(12位范围0xfff)
独立看门狗复位时间计算公式:t=(4*2^pre*rlr)/40
* 输 出 : 无
*******************************************************************************/
void IWDG_Init(u8 pre,u16 rlr)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //取消寄存器写保护
IWDG_SetPrescaler(pre);//设置预分频系数 0-6
IWDG_SetReload(rlr);//设置重装载值
IWDG_ReloadCounter(); //重装载初值
IWDG_Enable(); //打开独立看门狗
}
/*******************************************************************************
* 函 数 名 : IWDG_FeedDog
* 函数功能 : 喂狗
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void IWDG_FeedDog(void) //喂狗
{
IWDG_ReloadCounter(); //重装载初值
}
主函数代码(按键按下进行喂狗点亮灯)
cs
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include "key.h"
#include "iwdg.h"
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
u8 i=0;
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
LED_Init();
USART1_Init(115200);
KEY_Init();
IWDG_Init(4,800); //只要在1280ms内进行喂狗就不会复位系统
LED2=1;
printf("复位系统\r\n");
while(1)
{
if(KEY_Scan(0)==KEY_UP_PRESS)
{
IWDG_FeedDog();//喂狗
LED2=0;
printf("喂狗\r\n");
}
i++;
if(i%20==0)
{
LED1=!LED1;
}
delay_ms(10);
}
}
窗口看门狗WWDG:
挂载在APB1总线上,7位递减计数器;
- 减到固定值0x40复位;在上限值和下限值中间进行喂狗
- 0x40的时候会唤醒中断,此时喂狗也不会进行复位


设计流程:
- 使能WWDG时钟
cs
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); //开启窗口看门狗的时钟
- 设置WWDG窗口值;分频数
cs
/**
* @brief 设置窗口看门狗(WWDG)的窗口值
* @param WindowValue: 指定窗口值(范围: 0x40-0x7F)
* @details 窗口值定义了喂狗操作的上限时间点
* 只有当计数器值小于WindowValue且大于0x40时喂狗才有效
* @retval 无
* @note 窗口值必须大于0x40,否则将导致无法正确喂狗
*/
void WWDG_SetWindowValue(uint8_t WindowValue)
cs
/**
* @brief 设置窗口看门狗(WWDG)的预分频器值
* @param WWDG_Prescaler: 指定预分频系数
* 该参数可以是以下值之一:
* - WWDG_Prescaler_1: 预分频系数为1 (PCLK1/4096)
* - WWDG_Prescaler_2: 预分频系数为2 (PCLK1/4096/2)
* - WWDG_Prescaler_4: 预分频系数为4 (PCLK1/4096/4)
* - WWDG_Prescaler_8: 预分频系数为8 (PCLK1/4096/8)
* @retval 无
* @note 修改预分频器会影响看门狗的计时频率
*/
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler)
- 开启WWDG中断并分组
cs
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;//窗口中断通道
- 设置计数器初始值;并使能WWDG
cs
/**
* @brief 使能窗口看门狗(WWDG)并设置初始计数器值
* @param Counter: 指定初始计数器值(范围: 0x40-0x7F)
* @details 向WWDG_CR寄存器写入Counter值并置位WDGA位,启动窗口看门狗
* 计数器从指定值开始递减,当计数器值小于0x40时将触发复位
* @retval 无
* @note 初始值必须在0x40-0x7F范围内,否则将导致无法正确启动看门狗
*/
void WWDG_Enable(uint8_t Counter)
cs
/**
* @brief 清除窗口看门狗(WWDG)早期唤醒中断标志
* @details 向WWDG_SR寄存器写入0,清除EWIF标志位
* 该标志在计数器值达到0x41时被置位,触发早期唤醒中断(如果使能)
* @retval 无
* @note 必须在中断处理函数中调用此函数以清除中断标志
*/
void WWDG_ClearFlag(void)
cs
//开启中断
void WWDG_EnableIT(void)
- 编写WWDG中断服务函数(进入中断就要喂狗,时间要短)
cs
void WWDG_IRQHandler(void)
代码如下:
cs
#include "wwdg.h"
#include "led.h"
#include "SysTick.h"
/*******************************************************************************
* 函 数 名 : WWDG_Init
* 函数功能 : WWDG初始化
窗口值是:0x5f
定时器计数值是:0x7f
预分频值是:8
窗口看门狗进入中断的频率计算公式是:PCLK1/(4096*2^pre)
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void WWDG_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); //开启窗口看门狗的时钟
WWDG_SetWindowValue(0x5f);//设置窗口值
WWDG_SetPrescaler(WWDG_Prescaler_8);//设置分频值
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;//窗口中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器
WWDG_Enable(0x7f); //使能窗口看门狗并初始化计数器值
WWDG_ClearFlag(); //清除窗口看门狗状态标志(这一句必须加上,否则进入不了中断)
WWDG_EnableIT(); //开启中断
}
/*******************************************************************************
* 函 数 名 : WWDG_IRQHandler
* 函数功能 : WWDG中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void WWDG_IRQHandler(void)
{
WWDG_SetCounter(0x7f); //重新赋值
WWDG_ClearFlag(); //清除窗口看门狗状态标志
LED2=!LED2;
}