STM32中IWDG、WWDG配置(HAL)
前言
1、IWDG简介
STM32中的IWDG(Independent Watchdog,独立看门狗)是一种硬件监控机制,主要用于监控系统的运行状态,防止系统因软件故障或意外情况进入不可预期的状态。
IWDG是一个递减的计数器,其时钟通常由独立的RC振荡器提供,使得IWDG能够在待机和停止模式下运行,即使主系统时钟停止,IWDG仍然能够正常工作。计数器从设定的值开始递减,如果在预设的超时时间内未被及时“喂狗”(刷新),即未将重装载寄存器的值写入计数器以重置其值,系统将自动触发复位,确保系统能够从异常状态中恢复。
IWDG一旦启动,除非发生复位,否则无法通过软件禁用,这增加了系统的可靠性,防止看门狗被意外或恶意关闭。IWDG还设计为低功耗模式,适用于对功耗有严格要求的应用,如电池供电的设备。
在STM32中,IWDG的配置通常包括启用IWDG时钟、设置预分频器和计数器以确定超时时间、启动IWDG,并在超时时间之前定期刷新IWDG以防止系统复位。IWDG的配置和使用对于提高系统的稳定性和可靠性具有重要意义。
2、IWDG工作原理
STM32中的IWDG(独立看门狗)工作原理相对简单。它基于一个递减的计数器,该计数器由独立的低速内部振荡器(LSI)提供时钟。计数器从预设值开始递减,如果在计数器递减到0之前没有及时通过软件重载(喂狗)来重置计数器的值,那么当计数器递减至0时,IWDG将产生一个系统复位信号,使系统重新启动。这种机制有助于防止系统因软件错误或外部干扰而陷入不可预测的状态。
3、IWDG溢出时间计算
STM32中IWDG(独立看门狗)的溢出时间计算公式为:Tout = (IWDG_RLR寄存器对应的装载数值) × (看门狗时钟周期)。其中,看门狗时钟周期由LSI(低速内部振荡器)频率和预分频系数决定。LSI频率通常为40kHz,预分频系数通过IWDG_PR寄存器设置,影响时钟频率
Tout:看门狗溢出时间
fIWDG:看门狗的时钟源频率
psc:看门狗预分频系数
rlr:看门狗重装载值
4、WWDG简介
STM32中的WWDG(Window Watchdog,窗口看门狗)是一种用于监控系统的硬件设备。它是一个递减的计数器,能够产生系统复位信号和提前唤醒中断(EWI)。WWDG的计数器值在特定窗口范围内递减,若在规定时间内未进行喂狗操作(即重载计数器值),则WWDG会触发系统复位。此外,当计数器达到预设值时,WWDG还可以产生提前唤醒中断,允许系统执行一些预定义的操作。WWDG主要用于监测单片机程序的运行时效性,确保系统的稳定性和可靠性。
5、WWDG工作原理
WWDG是一个递减计数器,其时钟信号来自PCLK1,并经过预分频器进行分频。在WWDG启动时,计数器的初始值被设定为窗口上限值,并随着时钟信号的到来而递减。在递减的过程中,如果计数器的值大于窗口上限值,WWDG可以产生中断,允许系统执行一些预定义的中断服务程序。然而,如果计数器的值在递减到窗口下限值(固定为0x3F)之前没有被重载(即喂狗),WWDG将触发系统复位。窗口期的起始和结束条件取决于窗口上限值和窗口下限值的设置,以及对计数器的喂狗操作。WWDG的主要作用是监测单片机程序的运行时效性,确保系统能够在软件异常或外部干扰时保持稳定和可靠
6、WWDG溢出时间计算
计算公式一般为:
Twwdg = (4096 × 2^WDGTB × (T[5:0] + 1)) / Fpclk1
其中:
需要注意的是,WWDG的溢出时间计算需要确保计数器的值在窗口范围内,即在窗口上限值和窗口下限值(固定为0x3F)之间。如果计数器的值在递减到窗口下限值之前没有被重载(喂狗),WWDG将触发系统复位。因此,在配置WWDG时,需要仔细计算溢出时间,并根据系统需求设置合适的预分频系数和计数器值。
IWDG配置过程:
1、取消预分频器和重装载寄存器写保护
IWDG_HandleTypeDef iwdg_handle = {0};
void iwdg_init(uint8_t psc,uint16_t rlr)
{
iwdg_handle.Instance = IWDG;
iwdg_handle.Init.Prescaler = psc;
iwdg_handle.Init.Reload = rlr;
HAL_IWDG_Init(&iwdg_handle);
}
这里的1-3步都写在初始化函数里,下面的2、3就不重复写代码了
2、设置IWDG预分频系数和重装载值
3、启动IWDG
4、喂狗
调用HAL_IWDG_Refresh()函数,可以理解为这个函数就是喂狗的。
void iwdg_feed(void)
{
HAL_IWDG_Refresh(&iwdg_handle);
}
WWDG配置过程:
1、设置WWDG预分频系数、重装载值和窗口值
WWDG_HandleTypeDef wwdg_handle = {0};
void wwdg_init(uint8_t tr,uint8_t wr,uint32_t psc)
{
wwdg_handle.Instance = WWDG;
wwdg_handle.Init.Counter = tr;
wwdg_handle.Init.EWIMode = WWDG_EWI_ENABLE;
wwdg_handle.Init.Prescaler = psc;
wwdg_handle.Init.Window = wr;
HAL_WWDG_Init(&wwdg_handle);
}
第一行代码是定义的一个句柄
函数的传入参数:
tr:计数器的值
wr:窗口值
psc:预分频系数
函数里的结构体就不过多赘述,其中EWIMode是提前唤醒中断模式
2、MSP初始化
void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
{
__HAL_RCC_WWDG_CLK_ENABLE();
HAL_NVIC_SetPriority(WWDG_IRQn,2,2);
HAL_NVIC_EnableIRQ(WWDG_IRQn);
}
wwdg相关硬件初始化只需要使能其时钟,开始中断即可。
3、编写中断服务函数
void WWDG_IRQHandler(void)
{
HAL_WWDG_IRQHandler(&wwdg_handle);
}
注意这里中断服务函数中的函数,是公共服务函数。
4、编写提前唤醒回调函数
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
{
wwdg_feed();
}
5、窗口期内喂狗
void wwdg_feed(void)
{
HAL_WWDG_Refresh(&wwdg_handle);
}
作者:ljhlovezyx