STM32(二十七)——独立看门狗&窗口看门狗

一、独立看门狗

一、库函数

1. void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);

作用:开启 / 关闭 IWDG 寄存器写权限

IWDG 有硬件保护不开启写权限 → 不能改分频、不能改重装值

2. void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);

作用:设置 IWDG 预分频系数

决定看门狗计时快慢

3. void IWDG_SetReload(uint16_t Reload);

作用:设置重装载值

计数器从这个值往下减,减到 0 就复位

4. void IWDG_ReloadCounter(void);

作用:喂狗!

把重装载值重新装进计数器,清零倒计时

5. void IWDG_Enable(void);

作用:启动 IWDG

一旦启动 → 无法关闭 → 只能复位停止

二、代码

main代码
复制代码
int main(void)
{
	OLED_Init();
	OLED_ShowString(1,1,"IWDG TEST");
	Key_Init();
	
	if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET)
	{
		OLED_ShowString(2,1,"IWDGRST");
		Delay_ms(500);
		OLED_ShowString(2,1,"       ");
		Delay_ms(100);
		RCC_ClearFlag();
	}
	else
	{
		OLED_ShowString(3,1,"RSE");
		Delay_ms(500);
		OLED_ShowString(3,1,"   ");
		Delay_ms(100);
	}
	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
	IWDG_SetPrescaler(IWDG_Prescaler_16);
	IWDG_SetReload(2499);
	IWDG_ReloadCounter();
	IWDG_Enable();
	
	while(1)
	{
		Key_GetNum();
		
		IWDG_ReloadCounter();
		
		OLED_ShowString(4,1,"FEED");
		Delay_ms(200);
		OLED_ShowString(4,1,"    ");
		Delay_ms(600);
	}
}
独立看门狗初始化

解锁 → 分频 → 重装值 → 喂狗 → 启动

复制代码
    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
	IWDG_SetPrescaler(IWDG_Prescaler_16);
	IWDG_SetReload(2499);
	IWDG_ReloadCounter();
	IWDG_Enable();

设置为1000ms的喂狗时间,采用16分频,1000 = (1/400000 )* (PL +1)* 16 *1000,算出PL为2499.

判断是否喂狗
  • 如果是 IWDG 看门狗复位 → 显示 IWDGRST

  • 如果是 其他 → 显示 RST

    if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET)
    {
    OLED_ShowString(2,1,"IWDGRST");
    Delay_ms(500);
    OLED_ShowString(2,1," ");
    Delay_ms(100);
    RCC_ClearFlag();
    }
    else
    {
    OLED_ShowString(3,1,"RSE");
    Delay_ms(500);
    OLED_ShowString(3,1," ");
    Delay_ms(100);
    }

if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET)

判断看门狗的复位标志位是否置1,如果置1了要手动清除标志位RCC_ClearFlag()。

While循环
没有按住按键:
  • 进来 → 喂狗
  • 显示 FEED 200ms
  • 清空 600ms
  • 循环结束
  • 立刻再次喂狗
按住按键不放:程序超时,看门狗复位,标志位置1,程序从头执行,显示 IWDGRST,清除标志位,往下执行然后又是超时,重复。
复制代码
while(1)
	{
		Key_GetNum();
		
		IWDG_ReloadCounter();
		
		OLED_ShowString(4,1,"FEED");
		Delay_ms(200);
		OLED_ShowString(4,1,"    ");
		Delay_ms(600);
	}

二、窗口看门狗

一、库函数

1. void WWDG_DeInit(void);

作用:复位 WWDG 外设 把窗口看门狗寄存器恢复到默认值。几乎不用,因为 WWDG 一旦开启就关不掉。


2. void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);

作用:设置 WWDG 时钟分频


3. void WWDG_SetWindowValue(uint8_t WindowValue);

作用:设置窗口值 W


4. void WWDG_EnableIT(void);

作用:开启 WWDG 早期唤醒中断(EWI) 计数器快到 0x3F 时会先触发中断,不立刻复位。


5. void WWDG_SetCounter(uint8_t Counter);

作用:手动给计数器赋值 就是给 T [6:0] 赋值范围:0x40 ~ 0x7F


6. void WWDG_Enable(uint8_t Counter);

作用:启动 WWDG + 给计数器赋初值 一旦启动,无法关闭!

这是启动看门狗的最终函数


7. FlagStatus WWDG_GetFlagStatus(void);

作用:获取唤醒中断标志判断是否快要触发复位了。


8. void WWDG_ClearFlag(void);

作用:清除中断标志位在中断服务函数里用。

二、代码

main代码
复制代码
int main(void)
{
	OLED_Init();
	OLED_ShowString(1,1,"WWDG TEST");
	Key_Init();
	
	if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET)
	{
		OLED_ShowString(2,1,"WWDGRST");
		Delay_ms(500);
		OLED_ShowString(2,1,"       ");
		Delay_ms(100);
		RCC_ClearFlag();
	}
	else
	{
		OLED_ShowString(3,1,"RSE");
		Delay_ms(500);
		OLED_ShowString(3,1,"   ");
		Delay_ms(100);
	}
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
	WWDG_SetPrescaler(WWDG_Prescaler_8);
	WWDG_SetWindowValue(0x40 | 21);
	WWDG_Enable(0x40 | 54);
	
	while(1)
	{
		Key_GetNum();
		
//		OLED_ShowString(4,1,"FEED");
//		Delay_ms(20);
//		OLED_ShowString(4,1,"    ");
		Delay_ms(31);
		WWDG_SetCounter(0x40 | 54);
	}
	
}
初始化

WWDG挂载在APB1 总线上,使用前必须开启时钟,否则寄存器无法写入。

复制代码
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
	WWDG_SetPrescaler(WWDG_Prescaler_8);
	WWDG_SetWindowValue(0x40 | 21);
	WWDG_Enable(0x40 | 54);
为什么要加 0x40?
  • WWDG 是 7 位计数器
  • Bit6 必须保持为 1,否则会直接触发复位
  • 0x40 就是让 Bit6 = 1,保证不会意外复位
计算

超时时间:

窗口时间:

  • 延时 < 30ms → 喂早了 → 复位
  • 延时 > 50ms → 喂晚了 → 复位
判断是否喂狗
复制代码
    if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) == SET)
	{
		OLED_ShowString(2,1,"WWDGRST");
		Delay_ms(500);
		OLED_ShowString(2,1,"       ");
		Delay_ms(100);
		RCC_ClearFlag();
	}
	else
	{
		OLED_ShowString(3,1,"RSE");
		Delay_ms(500);
		OLED_ShowString(3,1,"   ");
		Delay_ms(100);
	}
while循环
  • 延时31毫秒到59毫秒喂狗成功,屏幕不闪烁

  • 延时30毫秒喂狗太早,屏幕闪烁WWDGRST

  • 延时50毫秒喂狗太晚,屏幕闪烁WWDGRST

    复制代码
      while(1)
      {
      	Key_GetNum();
      	
      	Delay_ms(31);
      	WWDG_SetCounter(0x40 | 54);
      }
相关推荐
weixin_462901972 小时前
方案 3:手机控制 ESP32
单片机·嵌入式硬件
不要秃头的小孩2 小时前
50. 随机数排序
数据结构·python·算法
tankeven2 小时前
HJ139 小红的01子序列计数(hard)
c++·算法
weixin_649555672 小时前
C语言程序设计第四版(何钦铭、颜晖)第十章函数与程序设计之汉诺塔问题
c语言·c++·算法
C羊驼2 小时前
C语言:随机数
c语言·开发语言·经验分享·笔记·算法
風清掦2 小时前
【江科大STM32学习笔记-09】USART串口协议 - 9.1 STM32 USART串口外设
笔记·stm32·单片机·嵌入式硬件·学习
xushichao19892 小时前
实时数据压缩库
开发语言·c++·算法
minji...2 小时前
Linux 文件系统 (三) 软连接和硬链接
linux·运维·服务器·c++·算法
逐步前行3 小时前
STM32_USART_寄存器操作
stm32·单片机·嵌入式硬件