窗口看门狗WWDG
Posted 旭日初扬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了窗口看门狗WWDG相关的知识,希望对你有一定的参考价值。
一、窗口看门狗(WWDG)简介
1.1、概念
是一个7位的递减计数器,当递减到一个固定值(此值为窗口的下限,是固定的不能改变)0x40时不喂狗,会产生一个MCU复位。
窗口看门狗的上限值:当窗口看门狗的计数值递减到某个数之前喂狗也会产生复位。这个值称为窗口的上限,由用户独立设置。
窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗(刷新)。
1.2、时序图
- T[6:0]是窗口控制寄存器(WWDG_CR)的低 7 位。T[6:0]就是窗口看门狗的计数器值,而W[6:0]是窗口看门狗的上窗口,下窗口是固定值 0X40。
- 当窗口看门狗的计数器在上窗口值之外或者低于下窗口值被刷新都会产生复位。上窗口值(W[6:0])是由用户自己设定的,根据实际要求来设计窗口值,但是一定要确保窗口值大于 0X40,否则窗口就不存在了。
- 窗口看门狗 WWDG 通常被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。
二、结构框图
应用程序在正常运行过程中必须定期地写入WWDG_CR寄存器以防止MCU发生复位。只有当计数器值小于窗口寄存器的值时,才能进行写操作。储存在WWDG_CR寄存器中的数值必须在0xFF(1111 1111)和0xC0(1100 1111)之间:
2.1、标识1 WWDG时钟
窗口看门狗(WWDG)的时钟来自 PCLK1,即挂接在 APB1 总线上,由 RCC 时钟控制器开启。APB1 时钟最大为 36M。
2.2、标识2 预分频器
PCLK1 时钟并不直接提供给窗口看门狗计数器时钟,而是通过一个 WDG 预分频器分频后输入给计数器时钟。我们可以操作配置寄存器 WWDG_CFR 的位 8:7WDGTB[1:0]来设置分频因子,分频因子可以为 0、1、2、3。分频后的计数器时钟为:CK_CNT= PCLK1/4096/(2^WDGTB),除以 4096 是中文参考手册内公式规定,没有为什么。PCLK1 等于 APB1 时钟,WDGTB 为分频因子(0-3),2^WDGTB 大小就是 1、2、4、8,与库函数中的分频参数对应。每经过一个计数器时钟,计数器就减 1。
2.3、标号3 计数器
窗口看门狗的计数器是一个 7 位的递减计数器,计数最大值为 0X7F(0111 1111),其值存放在控制寄存器 WWDG_CR 中的 6:0 位,即 T[6:0]。当递减到 T6 位变成 0 时,即从 0X40 变为 0X3F 时候,会产生看门狗复位。这个值 0X40 是窗口看门狗能够递减到的最小值,所以计数器的值只能在 0X40~0X7F 之间,实际上用来计数的是 T[5:0]。当递减计数器递减到 0X40 的时候,还不会马上产生复位,如果使能了提前唤醒中断,窗口配置寄存器(WWDG_CFR)位 9 EWI 置 1,则产生提前唤醒中断,也就是在快产生复位的前一段时间提醒我们,需要进行喂狗了,否则将复位。我们通常都是在提前唤醒中断内向 WWDG_CR 重新写入计数器的值,来达到喂狗的目的。需要注意的是:在进入中断后,必须在不大于 1 个窗口看门狗计数周期的时间(在 PCLK1 频率为 36M 且 WDGTB 为 0 的条件下,该时间为 113us)内重新写 WWDG_CR,否则,看门狗将产生复位!
RCC结构体(复位和时钟控制(RCC))
全称:Reset and clock control (RCC)
typedef struct
{
__IO uint32_t CR; // 控制寄存器
__IO uint32_t CFGR; // 配置寄存器
__IO uint32_t CIR;
__IO uint32_t APB2RSTR;
__IO uint32_t APB1RSTR;
__IO uint32_t AHBENR;
__IO uint32_t APB2ENR;
__IO uint32_t APB1ENR;
__IO uint32_t BDCR;
__IO uint32_t CSR;
#ifdef STM32F10X_CL
__IO uint32_t AHBRSTR;
__IO uint32_t CFGR2;
#endif /* STM32F10X_CL */
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
uint32_t RESERVED0;
__IO uint32_t CFGR2;
#endif /* STM32F10X_LD_VL || STM32F10X_MD_VL || STM32F10X_HD_VL */
} RCC_TypeDef;
WWDG结构体
typedef struct
{
__IO uint32_t CR;
__IO uint32_t CFR;
__IO uint32_t SR;
} WWDG_Typ
WWDG_GetFlagStatus
- SET 代表 1
- RESET 代表 0
/**
* @brief Checks whether the specified RCC flag is set or not. 检查是否设置了指定的RCC标志
* @param RCC_FLAG: specifies the flag to check. 指定要检查的标志*
* For @b STM32_Connectivity_line_devices, this parameter can be one of the following values: stm32连接线路设备 此参数可以是以下值之一
* @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready HSI振荡器时钟准备就绪* @arg RCC_FLAG_HSERDY: HSE oscillator clock ready
* @arg RCC_FLAG_PLLRDY: PLL clock ready
* @arg RCC_FLAG_PLL2RDY: PLL2 clock ready
* @arg RCC_FLAG_PLL3RDY: PLL3 clock ready
* @arg RCC_FLAG_LSERDY: LSE oscillator clock ready
* @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready
* @arg RCC_FLAG_PINRST: Pin reset
* @arg RCC_FLAG_PORRST: POR/PDR reset
* @arg RCC_FLAG_SFTRST: Software reset
* @arg RCC_FLAG_IWDGRST: Independent Watchdog reset
* @arg RCC_FLAG_WWDGRST: Window Watchdog reset
* @arg RCC_FLAG_LPWRRST: Low Power reset
*
* For @b other_STM32_devices, this parameter can be one of the following values: 其他STM32设备
* @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready
* @arg RCC_FLAG_HSERDY: HSE oscillator clock ready
* @arg RCC_FLAG_PLLRDY: PLL clock ready
* @arg RCC_FLAG_LSERDY: LSE oscillator clock ready
* @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready
* @arg RCC_FLAG_PINRST: Pin reset
* @arg RCC_FLAG_PORRST: POR/PDR reset
* @arg RCC_FLAG_SFTRST: Software reset
* @arg RCC_FLAG_IWDGRST: Independent Watchdog reset
* @arg RCC_FLAG_WWDGRST: Window Watchdog reset
* @arg RCC_FLAG_LPWRRST: Low Power reset
*
* @retval The new state of RCC_FLAG (SET or RESET).
*/
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG)
{
uint32_t tmp = 0;
uint32_t statusreg = 0;
FlagStatus bitstatus = RESET; // RESET默认为0 SET默认为1
/* Check the parameters */ // 检查参数
assert_param(IS_RCC_FLAG(RCC_FLAG));/* Get the RCC register index */ // 检查RCC寄存器的索引
tmp = RCC_FLAG >> 5; //
if (tmp == 1) /* The flag to check is in CR register */
{
statusreg = RCC->CR;
}
else if (tmp == 2) /* The flag to check is in BDCR register */
{
statusreg = RCC->BDCR;
}
else /* The flag to check is in CSR register */
{
statusreg = RCC->CSR;
}/* Get the flag position */
tmp = RCC_FLAG & FLAG_Mask;
if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}/* Return the flag status */
return bitstatus;
}
二、WWDG配置
(1)使能WWDG时钟
WWDG不同于IWDG,IWDG有自己独立的LSI时钟,所以不存在使能问题,而WWDG使能的是APB1时钟,需要先使能时钟。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
(2)设置 WWDG 窗口值、分频数
设置WWDG窗口值函数为:
void WWDG_SetWindowValue(uint8_t WindowValue);
窗口值最大值为 0X7F,最小不能低于 0X40,否则就失去了窗口的意义。
设置分频函数:
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
(3)开启 WWDG 中断并分组
通常对窗口看门狗进行喂狗是在提前唤醒中断内操作,所以需要打开 WWDG的中断功能,并且配置对应的中断通道及分组。中断分组及通道选择是在 NVIC_Init 初始化内完成
WWDG_EnableIT();
(4)设置计数器初始值并使能 WWDG
库函数中提供了一个同时设置计数器初始值和使能 WWDG 的函数
void WWDG_Enable(uint8_t Counter);
注意计数器最大值不能大于 OX7F。
库函数还提供了一个独立设置计数器值的函数
void WWDG_SetCounter(uint8_t Counter);
(5)编写 WWDG 中断服务函数
编写一个 WWDG 中断服务函数,通过中断函数进行喂狗。WWDG中断服务函数名在 STM32F1 启动文件内就有,WWDG 中断函数名如下:
WWDG_IRQHandler
在中断内要进行喂狗,可以直接调用 WWDG_SetCounter()函数,给它传递一个窗口值即可,特别注意,在中断内喂狗一定要快,否则当看门狗计数器值减到0X3F 时将产生复位。然后清除 WWDG 中断状态标志位 EWIF,函数如下
WWDG_ClearFlag(); //清除窗口看门狗状态标志
以上是关于窗口看门狗WWDG的主要内容,如果未能解决你的问题,请参考以下文章