打印
[应用相关]

【经验分享】STM32 窗口看门狗程序

[复制链接]
773|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
01. 窗口看门狗简介
窗口看门狗(WWDG)通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。除非递减计数器的值在 T6 位(WWDG->CR 的第六位)变成 0 前被刷新,看门狗电路在达到预置的时间周期时,会产生一个 MCU 复位。在递减计数器达到窗口配置寄存器(WWDG->CFR)数值之前,如果 7 位的递减计数器数值(在控制寄存器中)被刷新, 那么也将产生一个 MCU 复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。他们的关系可以用图 12.1.1 来说明:



图 12.1.1 中,T[6:0]就是 WWDG_CR 的低七位,W[6:0]即是 WWDG->CFR 的低七位。T[6:0]就是窗口看门狗的计数器,而 W[6:0]则是窗口看门狗的上窗口,下窗口值是固定的(0X40)。当窗口看门狗的计数器在上窗口值之外被刷新,或者低于下窗口值都会产生复位。

上窗口值(W[6:0])是由用户自己设定的,根据实际要求来设计窗口值,但是一定要确保窗口值大于 0X40,否则窗口就不存在了。

使用特权

评论回复
沙发
stormwind123|  楼主 | 2022-4-1 11:25 | 只看该作者
窗口看门狗的超时公式如下:

Twwdg=(4096×2^WDGTB×(T[5:0]+1)) /Fpclk1;
其中:
Twwdg:WWDG 超时时间(单位为 ms)
Fpclk1:APB1 的时钟频率(单位为 Khz)
WDGTB:WWDG 的预分频系数
T[5:0]:窗口看门狗的计数器低 6 位

02. 硬件设计
本实验用到的硬件资源有:

1) 指示灯 DS0 和 DS1

2) 窗口看门狗

窗口看门狗属于 STM32F4 的内部资源,只需要软件设置好即可正常工作。

使用特权

评论回复
板凳
stormwind123|  楼主 | 2022-4-1 11:26 | 只看该作者
03. 编程步骤
1) 使能 WWDG 时钟
WWDG 不同于 IWDG,IWDG 有自己独立的 32Khz 时钟,不存在使能问题。而 WWDG使用的是 PCLK1 的时钟,需要先使能时钟。

  • RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能

复制代码


2) 设置窗口值和分频数
设置窗口值的函数是:

  • void WWDG_SetWindowValue(uint8_t WindowValue);

复制代码


这个函数就一个入口参数为窗口值,很容易理解。

设置分频数的函数是:

  • void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);

复制代码


这个函数同样只有一个入口参数就是分频值。

3) 开启 WWDG 中断并分组

开启 WWDG 中断的函数为:

  • WWDG_EnableIT(); //开启窗口看门狗中断

复制代码


接下来是进行中断优先级配置,这里就不重复了,使用 NVIC_Init()函数即可。

使用特权

评论回复
地板
stormwind123|  楼主 | 2022-4-1 11:28 | 只看该作者
4) 设置计数器初始值并使能看门狗

这一步在库函数里面是通过一个函数实现的:

  • void WWDG_Enable(uint8_t Counter);

复制代码


该函数既设置了计数器初始值,同时使能了窗口看门狗。

这里还需要说明一下,库函数还提供了一个独立的设置计数器值的函数为:

  • void WWDG_SetCounter(uint8_t Counter);

复制代码


5) 编写中断服务函数

在最后,还是要编写窗口看门狗的中断服务函数,通过该函数来喂狗,喂狗要快,否则当窗口看门狗计数器值减到 0X3F 的时候,就会引起软复位了。在中断服务函数里面也要将状态寄存器的 EWIF 位清空。

使用特权

评论回复
5
stormwind123|  楼主 | 2022-4-1 11:29 | 只看该作者
04. 程序示例
wwdg.h
  • #ifndef __WWDG_H__
  • #define __WWDG_H__
  • #include "sys.h"
  • //初始化函数
  • void WWDG_Init(u8 tr,u8 wr,u32 fprer);
  • //中断处理函数
  • void WWDG_IRQHandler(void);
  • #endif /*__WWDG_H__*/

复制代码


wwdg.c

  • #include "wwdg.h"
  • #include "led.h"
  • //保存WWDG计数器的设置值,默认为最大.
  • u8 WWDG_CNT=0X7F;
  • //初始化函数
  • //tr计数器的值
  • //wr窗口值
  • //fprer 预分频值
  • void WWDG_Init(u8 tr,u8 wr,u32 fprer)
  • {
  •         NVIC_InitTypeDef NVIC_InitStruct;
  •         //使能WWDG时钟
  •         RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
  •         //设置预分频
  •         WWDG_SetPrescaler(fprer);
  •         //设置窗口值
  •         WWDG_SetWindowValue(wr & WWDG_CNT);
  •         //使能看门狗
  •         WWDG_Enable(WWDG_CNT);
  •         //设置中断
  •         NVIC_InitStruct.NVIC_IRQChannel = WWDG_IRQn;
  •         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  •         NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
  •         NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
  •         NVIC_Init(&NVIC_InitStruct);
  •         //清除提前唤醒中断标志位
  •         WWDG_ClearFlag();
  •         //开启提前唤醒中断
  •         WWDG_EnableIT();
  • }
  • //中断处理函数
  • void WWDG_IRQHandler(void)
  • {
  •         //清除提前唤醒中断标志位
  •         WWDG_ClearFlag();
  •         WWDG_SetCounter(WWDG_CNT);
  •         LED2 = !LED2;
  • }

复制代码


使用特权

评论回复
6
stormwind123|  楼主 | 2022-4-1 11:31 | 只看该作者
main.c
  • #include "sys.h"
  • #include "delay.h"
  • #include "usart.h"
  • #include "led.h"
  • #include "beep.h"
  • #include "key.h"
  • #include "exti.h"
  • #include "iwdg.h"
  • #include "wwdg.h"
  • int main(void)
  • {
  •         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  •         delay_init(168);
  •         LED_Init();
  •         KEY_Init();
  •         LED1 = 0;
  •         LED2 = 0;
  •         delay_ms(300);
  •         WWDG_Init(0x7F,0X5F,WWDG_Prescaler_8);         //计数器值为7f,窗口寄存器为5f,分频数为8
  •         while(1)
  •         {
  •                 LED1 = 1;
  •         }
  • }


复制代码


05. 测试结果
可以看到 DS0 亮一下之后熄灭,紧接着 DS1 开始不停的闪烁。每秒钟闪烁 20 次左右。

使用特权

评论回复
7
x88484532| | 2022-4-2 09:11 | 只看该作者
一直搞不明白怎么计算窗口时间的

使用特权

评论回复
8
Jacquetry| | 2022-10-5 21:19 | 只看该作者
不是靠定时器计算吗?

使用特权

评论回复
9
Pulitzer| | 2022-10-8 08:29 | 只看该作者

事实上很多做项目的工程师本身自己也会在用

使用特权

评论回复
10
Uriah| | 2022-10-8 15:30 | 只看该作者

超过变量128后必须使用compact模式编译

使用特权

评论回复
11
Bblythe| | 2022-10-8 18:29 | 只看该作者

这是个再正常不过的coding习惯

使用特权

评论回复
12
周半梅| | 2023-7-1 07:26 | 只看该作者

当端口P1.0输出低电平时,小灯就亮,因为此时小灯中有电流通过

使用特权

评论回复
13
Pulitzer| | 2023-7-1 08:29 | 只看该作者

算数逻辑单元(ALU):处理算数和逻辑运算

使用特权

评论回复
14
周半梅| | 2023-7-1 09:32 | 只看该作者

需要在做项目的过程中经历磨难

使用特权

评论回复
15
童雨竹| | 2023-7-1 10:25 | 只看该作者

TIM4正常中断,UART1串口发送正常,就是串口接收中断进不去。

使用特权

评论回复
16
Wordsworth| | 2023-7-1 11:28 | 只看该作者

格式化输出需要删除掉多余的空白行

使用特权

评论回复
17
Clyde011| | 2023-7-1 12:31 | 只看该作者

I2C1工作时钟源选择;I2C1模块工作时钟的开启使能。

使用特权

评论回复
18
万图| | 2023-7-1 14:27 | 只看该作者

Git 的api很多,但其实平时项目中90%的需求都只需要用到几个基本的功能即可

使用特权

评论回复
19
Uriah| | 2023-7-1 15:30 | 只看该作者

孔璧里头必须经过电镀

使用特权

评论回复
20
帛灿灿| | 2023-7-1 17:26 | 只看该作者

完全不必要的 Else 块

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

403

主题

2060

帖子

2

粉丝