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);
      }
相关推荐
The_superstar618 小时前
衡山派学习之串口
单片机·嵌入式硬件·串口·衡山派
CN-Dust18 小时前
【C++】while语句例题专题
数据结构·c++·算法
Ww.xh18 小时前
STM32按键去抖动软件实现详解
stm32·单片机·嵌入式硬件
灵智实验室18 小时前
PX4位置速度估计技术详解(四):LPE 激光雷达高度融合的实现错误
算法·无人机·px 4
ghie909018 小时前
基于STM32的CAN通信完整例程(HAL库实现)
stm32·单片机·嵌入式硬件
CQU_JIAKE18 小时前
【A】3742,3387,并查集
算法
gihigo199818 小时前
CHAN时延估计算法(二维/三维定位实现)
算法
lzj_pxxw18 小时前
W25Q64存储芯片 软件设计刚需常识
stm32·单片机·嵌入式硬件·mcu·学习
freexyn19 小时前
Matlab自学笔记七十六:表达式的展开、因式分解、化简、合并同类项
笔记·算法·matlab
样例过了就是过了19 小时前
LeetCode热题 不同路径
c++·算法·leetcode·动态规划