STM32-看门狗

独立看门狗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位递减计数器;

  1. 减到固定值0x40复位;在上限值和下限值中间进行喂狗
  2. 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;	
}
相关推荐
嵌入式-老费1 小时前
LVGL应用和部署(和物理按键交互)
嵌入式硬件
tao3556672 小时前
树莓派免密登录(vs code/cursor)
linux·嵌入式硬件·ssh
is08153 小时前
在STM32 FreeRTOS环境中使用mutex和ringbuffer实现多任务的UART同步通信
stm32·单片机·嵌入式硬件
景彡先生3 小时前
STM32中I2C协议详解
stm32·单片机·嵌入式硬件
星卯教育tony4 小时前
米思齐2.0 3.0 mixly arduino 编程软件下载安装及详情使用指南 导入库文件方法 支持8266 esp32
单片机·嵌入式硬件
削好皮的Pineapple!4 小时前
C语言模块化编程思维以及直流电机控制(第四天)
c语言·开发语言·单片机
天天爱吃肉82186 小时前
周立功汽车软件ZXDoc深度解析:新能源汽车开发新基建的破局之道
嵌入式硬件·架构·汽车
weixin_452600697 小时前
GC393低功耗双电压比较器:精准、高效的信号处理解决方案
单片机·嵌入式硬件·智能家居·信号处理·音响·蓝牙音箱
Do vis8248 小时前
STM32第十七天ESP8266-01Swifi模块
stm32·单片机·嵌入式硬件