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);
      }
相关推荐
Morwit28 分钟前
【力扣hot100】 1. 两数之和
数据结构·c++·算法·leetcode·职场和发展
无小道1 小时前
算法——暴力+优化
算法·优化·暴力
金戈鐡馬1 小时前
BetaFlight中的定时器引脚绑定详解
stm32·单片机·嵌入式硬件·无人机
Free Tester1 小时前
如何判断 LeakCanary 报告的严重程度
java·jvm·算法
zyq99101_12 小时前
DFS算法实战:经典例题代码解析
python·算法·蓝桥杯·深度优先
智者知已应修善业2 小时前
【51单片机单按键切换广告屏】2023-5-17
c++·经验分享·笔记·算法·51单片机
广州灵眸科技有限公司2 小时前
为RK3588注入澎湃算力:RK1820 AI加速卡完整适配与评测指南
linux·网络·人工智能·物联网·算法
qinian_ztc2 小时前
frida 14.2.18 安装报错解决
算法·leetcode·职场和发展
AI应用实战 | RE2 小时前
012、检索器(Retrievers)核心:从向量库中智能查找信息
人工智能·算法·机器学习·langchain
凤年徐2 小时前
C++手撕红黑树:从0到200行,拿下STL map底层核心
c++·后端·算法