STM32-看门狗
独立看门狗IWDG:
12位递减计数器,递减到0产生复位,如果到0前刷新了计数值,系统不会产生复位也就是喂狗
1:时钟源:来自内部时钟LSI;对时间精度低的场合
2:预分频器:—PR操控预分频因子
3:计数器
4:重装载值 设置溢出时间
5:键寄存器:控制寄存器 0x5555-关闭写保护;0xAAAA-计数递减重装载值给递减计数器;0xCCCC-启动功能
6:状态寄存器:硬件相关;
软件设计流程
- 开启寄存器访问(关闭写保护)
/*** @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预分频系数和重转载值
/*** @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)
/*** @brief 设置独立看门狗(IWDG)的重装载值* @param Reload: 指定重装载寄存器值(范围: 0x0000-0x0FFF)* @retval 无* @note 看门狗计数器会在达到0时复位系统* 实际超时时间 = (重装载值 + 1) × 预分频时间周期*/
void IWDG_SetReload(uint16_t Reload)
- 重装载计数器喂狗(0xAAAA)
/*** @brief 重载独立看门狗(IWDG)计数器* @details 向IWDG_KR寄存器写入0xAAAA,触发计数器重装载操作* 该操作会将IWDG_RLR寄存器的值重新加载到计数器中* 从而避免看门狗超时复位* @retval 无* @note 必须在看门狗超时前定期调用此函数(喂狗)*/
void IWDG_ReloadCounter(void)
- 开启
/*** @brief 使能独立看门狗(IWDG)* @details 向IWDG_KR寄存器写入0xCCCC,启动独立看门狗计数器* 一旦启用,看门狗将持续运行,无法通过软件禁用(除非复位)* @retval 无* @note 启用前必须配置好预分频器和重装载值*/
void IWDG_Enable(void)
一旦开启无法关闭,复位后才能关闭
代码如下
#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-6IWDG_SetReload(rlr);//设置重装载值IWDG_ReloadCounter(); //重装载初值IWDG_Enable(); //打开独立看门狗
}
/*******************************************************************************
* 函 数 名 : IWDG_FeedDog
* 函数功能 : 喂狗
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void IWDG_FeedDog(void) //喂狗
{IWDG_ReloadCounter(); //重装载初值
}
主函数代码(按键按下进行喂狗点亮灯)
#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时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE); //开启窗口看门狗的时钟
- 设置WWDG窗口值;分频数
/*** @brief 设置窗口看门狗(WWDG)的窗口值* @param WindowValue: 指定窗口值(范围: 0x40-0x7F)* @details 窗口值定义了喂狗操作的上限时间点* 只有当计数器值小于WindowValue且大于0x40时喂狗才有效* @retval 无* @note 窗口值必须大于0x40,否则将导致无法正确喂狗*/
void WWDG_SetWindowValue(uint8_t WindowValue)
/*** @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中断并分组
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;//窗口中断通道
- 设置计数器初始值;并使能WWDG
/*** @brief 使能窗口看门狗(WWDG)并设置初始计数器值* @param Counter: 指定初始计数器值(范围: 0x40-0x7F)* @details 向WWDG_CR寄存器写入Counter值并置位WDGA位,启动窗口看门狗* 计数器从指定值开始递减,当计数器值小于0x40时将触发复位* @retval 无* @note 初始值必须在0x40-0x7F范围内,否则将导致无法正确启动看门狗*/
void WWDG_Enable(uint8_t Counter)
/*** @brief 清除窗口看门狗(WWDG)早期唤醒中断标志* @details 向WWDG_SR寄存器写入0,清除EWIF标志位* 该标志在计数器值达到0x41时被置位,触发早期唤醒中断(如果使能)* @retval 无* @note 必须在中断处理函数中调用此函数以清除中断标志*/
void WWDG_ClearFlag(void)
//开启中断
void WWDG_EnableIT(void)
- 编写WWDG中断服务函数(进入中断就要喂狗,时间要短)
void WWDG_IRQHandler(void)
代码如下:
#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;
}