一、独立看门狗
一、库函数
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 -
如果是 其他 → 显示
RSTif(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); }