目录
1. 独立看门狗(IWDG)
1.1 IWDG键寄存器
1.2 IWDG超时时间
1.3 IWDG程序设计
1.3.1 写使能控制
1.3.2 写预分频器
1.3.3 写重装值
1.3.4 喂狗
1.3.5 启动独立看门狗
1.3.6 获取标志位状态
1.3.7 代码片段
2. 窗口看门狗(WWDG)
2.1 工作特性
2.2 WWDG超时时间
2.3 WWDG程序设计
2.3.1 恢复缺省配置
2.3.2 写入预分频器
2.3.3 写入窗口值
2.3.4 使能中断
2.3.5 喂狗
2.3.6 使能窗口看门狗
2.3.7 获取标志位
2.3.8 清除标志位
2.3.7 代码片段
3. IWDG和WWDG对比
看门狗可以监控程序的运行状态,当程序因为设计漏洞、硬件故障、电磁干扰等原因,出现卡死或跑飞现象时,看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(重置计数器)操作时,看门狗硬件电路就自动产生复位信号STM32内置两个看门狗。
独立看门狗(IWDG) :独立工作,对时间精度要求较低
窗口看门狗(WWDG) : 要求看门狗在精确计时窗口起作用
首先,我们可以类比定时中断的时基单元。
时基单元由预分频器、计数器和重装载寄存器组成。
假如72MHz的输入时钟,经过预分频器(这里假如2分频),则驱动时钟为72/2=36,在计数器会产生自增和自减,看门狗是进行自减,自减到0,定时器产生更新事件和中断,看门狗则进行复位。
键寄存器本质上是控制寄存器,用于控制硬件电路的工作。
在可能存在干扰的情况下,一般通过在整个键寄存器写入特定值来代替控制寄存器写入一位的功能,以降低硬件电路受到干扰的概率。
写入键寄存器的值 | 作用 |
OxCCCC | 启用独立看门狗 |
OxAAAA | IWDG_RLR中的值重新加载到计数器(喂狗) |
0x5555 | 解除IWDG_PR和IWDG_RLR的写保护 |
0x5555之外的其他值 | 启用IWDG_PR和IWDG_RLR的写保护 |
超时时间:PR预分频系数(RL+1)
其中:
对于=1/40KHz=0.025ms。
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);
定义:
/**
* @brief Enables or disables write access to IWDG_PR and IWDG_RLR registers.
* @param IWDG_WriteAccess: new state of write access to IWDG_PR and IWDG_RLR registers.
* This parameter can be one of the following values:
* @arg IWDG_WriteAccess_Enable: Enable write access to IWDG_PR and IWDG_RLR registers
* @arg IWDG_WriteAccess_Disable: Disable write access to IWDG_PR and IWDG_RLR registers
* @retval None
*/
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess)
{
/* Check the parameters */
assert_param(IS_IWDG_WRITE_ACCESS(IWDG_WriteAccess));
IWDG->KR = IWDG_WriteAccess;
}
#define IWDG_WriteAccess_Enable ((uint16_t)0x5555)
#define IWDG_WriteAccess_Disable ((uint16_t)0x0000)
#define IS_IWDG_WRITE_ACCESS(ACCESS) (((ACCESS) == IWDG_WriteAccess_Enable) || \
((ACCESS) == IWDG_WriteAccess_Disable))
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);
就是写DR寄存器
定义:
/**
* @brief Sets IWDG Prescaler value.
* @param IWDG_Prescaler: specifies the IWDG Prescaler value.
* This parameter can be one of the following values:
* @arg IWDG_Prescaler_4: IWDG prescaler set to 4
* @arg IWDG_Prescaler_8: IWDG prescaler set to 8
* @arg IWDG_Prescaler_16: IWDG prescaler set to 16
* @arg IWDG_Prescaler_32: IWDG prescaler set to 32
* @arg IWDG_Prescaler_64: IWDG prescaler set to 64
* @arg IWDG_Prescaler_128: IWDG prescaler set to 128
* @arg IWDG_Prescaler_256: IWDG prescaler set to 256
* @retval None
*/
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler)
{
/* Check the parameters */
assert_param(IS_IWDG_PRESCALER(IWDG_Prescaler));
IWDG->PR = IWDG_Prescaler;
}
void IWDG_SetReload(uint16_t Reload);
就是写RLR寄存器
定义:
/**
* @brief Sets IWDG Reload value.
* @param Reload: specifies the IWDG Reload value.
* This parameter must be a number between 0 and 0x0FFF.
* @retval None
*/
void IWDG_SetReload(uint16_t Reload)
{
/* Check the parameters */
assert_param(IS_IWDG_RELOAD(Reload));
IWDG->RLR = Reload;
}
void IWDG_ReloadCounter(void);
重新装载寄存器
定义:
/**
* @brief Reloads IWDG counter with value defined in the reload register
* (write access to IWDG_PR and IWDG_RLR registers disabled).
* @param None
* @retval None
*/
void IWDG_ReloadCounter(void)
{
IWDG->KR = KR_KEY_Reload;
}
在键寄存器写入:KR_KEY_Reload
/* KR register bit mask */
#define KR_KEY_Reload ((uint16_t)0xAAAA)
#define KR_KEY_Enable ((uint16_t)0xCCCC)
void IWDG_Enable(void);
/**
* @brief Enables IWDG (write access to IWDG_PR and IWDG_RLR registers disabled).
* @param None
* @retval None
*/
void IWDG_Enable(void)
{
IWDG->KR = KR_KEY_Enable;
}
FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);
#include "stm32f10x.h" // Device header
int main(void)
{
/*IWDG初始化*/
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //独立看门狗写使能
IWDG_SetPrescaler(IWDG_Prescaler_16); //设置预分频为16
IWDG_SetReload(2499); //设置重装值为2499,独立看门狗的超时时间为1000ms
IWDG_ReloadCounter(); //重装计数器,喂狗
IWDG_Enable(); //独立看门狗使能
while (1)
{
IWDG_ReloadCounter(); //重装计数器,喂狗
}
}
递减计数器T[6:0]的值小于0x40时,WWDG产生复位;
递减计数器T[6:0]在窗口W[6:0]外被重新装载时,WWDG产生复位;
递减计数器T[6:0]等于0x40时可以产生早期唤醒中断(EWI),用于重装载计数器以避免WWDG复位;
定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位。
超时时间(喂狗的最晚时间):
=× 4096× WDGTB预分频系数× (T[5:0] + 1)
窗口时间(喂狗的最早时间):
= × 4096 × WDGTB预分频系数 × (T[5:0] - W[5:0])
其中:
= 1 /
void WWDG_DeInit(void);
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
void WWDG_SetWindowValue(uint8_t WindowValue);
void WWDG_EnableIT(void);
void WWDG_SetCounter(uint8_t Counter);
void WWDG_Enable(uint8_t Counter);
FlagStatus WWDG_GetFlagStatus(void);
void WWDG_ClearFlag(void);
#include "stm32f10x.h" // Device header
int main(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); //开启WWDG的时钟
/*WWDG初始化*/
WWDG_SetPrescaler(WWDG_Prescaler_8); //设置预分频为8
WWDG_SetWindowValue(0x40 | 21); //设置窗口值,窗口时间为30ms
WWDG_Enable(0x40 | 54); //使能并第一次喂狗,超时时间为50ms
while (1)
{
WWDG_SetCounter(0x40 | 54); //重装计数器,喂狗
}
}
STM32F1之RTC实时时钟(Unix时间戳)-CSDN博客
BKP备份寄存器、RTC实时时钟-CSDN博客