简介
与 STM32 的 IWDG 一样,窗口看门狗的作用也是从不可预知的情况下,进行恢复的一种手段,只不过窗口看门狗的用法和 IWDG 有一定的差异,主要体现在“窗口”二字。那么什么是窗口看门狗呢?顾名思义,窗口看门狗就是在指定的时间窗口进行喂狗,才有效,在窗口外进行喂狗,都视为无效。具体的内容,请看下面分析
时钟
与独立看门狗 IWDG 不同,WWDG 窗口看门狗由 APB1 提供时钟输入:
工作原理
WWDG 的基本组成为:
可编程的自由运行递减计数器。
条件复位
---- 当递减计数器的值小于0x40,(若看门狗被启动)则产生复位。
---- 当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位。
如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI),它可以被用于重装载计数器以避免WWDG复位
WWDG 看门狗依然存在一个预分频器:
预分频器将来自 PCLK1 的时钟进行分频处理:
存在两个可以配置的寄存器:
WWDG_CR ----------- 用于配置递减计数器的值
WWDG_CFR ----------- 用于窗口计数器的值
如果看门狗被启动(WWDG_CR寄存器中的WDGA位被置’1’), 并且当7位(T[6:0])递减计数器从0x40翻转到0x3F(T6位清零)时,则产生一个复位。
如果软件在计数器值大于窗口寄存器中的数值时重新装载计数器,将产生一个复位。
也就是说,递减计数器的值永远不可能小于 0x3F,当达到了 0x3F 时刻,马上产生复位信号(所以当我们在写递减计数器的时候,必须保证写入的值要大于 0x40,这样才不会马上就产生复位信号)。
同时,喂狗的时间也需要正确,不然也会产生复位。
那有没有办法在计数器翻转到 0x3F 之前,我们还不让复位呢?当然有,WWDG 存在一个叫做 EWI 的中断,这个中断产生的条件是当递减寄存器到达 0x40 的时候产生,也就是此刻,我们在中断里面进行及时的喂狗,就可以避免复位产生了。
现在解释一下,什么是窗口的意思:
如图所示,在我们设置的窗口 W[6:0] 之前,若是进行了喂狗,则产生复位,或者到达了 0x3F,也产生复位。只有在“刷新窗口”那个区域进行喂狗,才能够继续运行。
中断
支持配置打开叫做 EWI 的提前唤醒中断,当递减计数器达到 0x40 的时候产生中断。
中断中,需要清除对应的中断标志位,若是不希望复位的产生,则还需要重新刷新一下递减计数器即可。
配置过程
1. 开启 WWDG 的时钟
2. 设置预分频器的值
3. 设置窗口的值
4. 设置递减计数器的值
5. 初始化 NVIC
6. 使能看门狗
7. 清除中断标志位
8. 使能 EWI 中断
#define MAX_WWDG_CNT 0x7F
#define WWDG_TEST_WIN 0x5F
/*
***************************************************************
******************* WWDG Function Defination *******************
***************************************************************
*/
static void SK_WWDGNVICConfig(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
}
void SK_WWDGInit(uint8_t target, uint8_t window, uint32_t fprer)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
target = target & MAX_WWDG_CNT;
WWDG_SetPrescaler(fprer);
WWDG_SetWindowValue(window);
SK_WWDGNVICConfig();
WWDG_Enable(target);
WWDG_ClearFlag();
WWDG_EnableIT();
}
void SK_WWDGFeed(uint8_t target)
{
WWDG_Enable(target);
}
void WWDG_IRQHandler(void)
{
//WWDG_SetCounter(MAX_WWDG_CNT); // If open this, it will never reset
WWDG_ClearFlag();
//SK_SetLedStatus(SK_LED_1, SK_LED_ON);
//SK_SetLedStatus(SK_LED_1, SK_LED_OFF);
}
上一篇:【STM32F103】按键检测(GPIO输入)
下一篇:stm32按键的检测(EXTI和Polling两种方式)
推荐阅读最新更新时间:2024-03-16 16:27