每日更新教程,评论区答疑解惑,小白也能变大神!"
目录
一.窗口看门狗(WWDG)简介
二.窗口看门狗寄存器列表
三.窗口看门狗复位案例
一.窗口看门狗(WWDG)简介
- CW32F030C8T6 内部集成窗口看门狗定时器 (WWDT),用户需要在设定的时间窗口内进行刷新,否则将触发系统复位。 WWDT 通常被用来监测有严格时间要求的程序执行流程,防止由外部干扰或未知条件造成应用程序的执行异常, 导致发生系统故障。
1.1主要特性
- 7 位向下计数器。
- PCLK 时钟驱动,8 级预分频,最大分频 524288。
- 支持预溢出中断和计数溢出、加载计数值出错复位。
- 开启后不可关闭,除非系统复位。
1.2功能框图
1.3工作方式
- 系统复位后,窗口看门狗 WWDT 处于关闭状态,设置控制寄存器 WWDT_CR0 的 EN 位域为 1,可启动 WWDT。 WWDT 开启后,除非发生复位,否则不能被关闭。 启动 WWDT 之前,用户必须预设看门狗溢出时间和窗口时间。设置 WWDT_CR0.WCNT 的值,可更新计数器的 初始值,设置 WWDT_CR1.WINR 的值,可配置看门狗的窗口值,窗口值必须小于看门狗计数器的初始值。启动 WWDT 后,计数器从初始值开始递减计数。
- 当计数器递减到 0x40 时,将产生预溢出信号 POV,设置 WWDT_CR1.IE 为 1 将产生预溢出中断。
- 当计数器递减到 0x3F 时,将产生溢出信号 OV,该溢出信号可触发系统复位。
- 在当前计数值 WCNT 大于窗口值 WINR 时,更新看门狗计数器,也会触发系统复位。
1.4刷新计数器
- WWDT 运行时,只有在计数值小于等于窗口值且计数值递减到 0x3F 之前,才能刷新计数器,即喂狗操作,否则 将产生系统复位。 设置 WWDT_CR1.WINR 的值,可配置复位前延时时间窗口的上限值,延时时间窗口的下限固定为 0x3F,窗口看 门狗的喂狗操作时机,如下图所示:
1.5喂狗时间
- 窗口看门狗的喂狗时间计算公式:
- 喂狗时间下限: TWWDT_MIN = TPCLK×4096×2PRS×( WCNT – WINR )
- 喂狗时间上限: TWWDT_MAX = TPCLK×4096×2PRS×( WCNT – 0x3F )
- 其中: TPCLK:PCLK 的时钟周期 PRS:预分频系数 WCNT:计数器当前计数值 WINR:
- 看门狗窗口值
- 例: 当 PCLK 频率为 24MHz 时,预分频系数 PRS 设置为 0x01,WCNT 设置为 0x6F,窗口值 WINR 设置为 0x4F,
- 则喂狗时间如下: TWWDT_MIN = 1 / 24MHz×4096×21 ×( 0x6F - 0x4F ) ≈ 10.922 ms TWWDT_MAX = 1 / 24MHz×4096×21 ×( 0x6F - 0x3F ) = 16.384 ms
- 即,喂狗时间最早不能早于 10.922ms,否则将发生加载计数值出错而引起系统复位;喂狗最晚不能迟于 16.384ms,否则将发生下溢出引起系统复位。正确喂狗的时间窗口大小约为 5ms。
1.6复位与中断
- 当计数器 WCNT 的值递减到 0x40 时,预溢出中断标志位 WWDT_SR.POV 由硬件置位,若设置了控制寄存器 WWDT_CR1 的 IE 位域为 1(注:该位置 1 后不可清 0),将产生预溢出中断请求。用户可在中断服务程序中更 新计数器 WCNT,以避免 WWDT 产生复位。 在以下条件之一成立时,均可触发系统复位:
- 1. 计数器 WCNT 的值递减到 0x3F;
- 2. 更新计数器 WCNT 时当前计数值大于窗口值;
- 3. 向 WWDT_CR0.WCNT 写入小于或等于 0x3F 的值。
1.7 WWDT 基本配置流程
- 步骤 1:设置 SYSCTRL_APBEN1.WWDT 为 1,使能 WWDT 的配置时钟及工作时钟;
- 步骤 2:通过 WWDT_CR1.PRS 配置窗口看门狗计数器时钟的预分频;
- 步骤 3:通过 WWDT_CR1.WINR 配置窗口看门狗计数的比较值;
- 步骤 4:通过 WWDT_CR0.WCNT 配置计数器的初始值;
- 步骤 5:根据是否需要使能预溢出中断,配置 WWDT_CR1.IE;
- 步骤 6:设置 WWDT_CR0.EN 为 1 启动窗口看门狗。 WWDT 喂狗 当计数器 WCNT 的值递减到小于等于 WWDT_CR1.WINR,且大于 0x3F 之前,向 WWDT_CR0.WCNT 重新写入计 数器的初始值。
二.窗口看门狗寄存器列表
三.窗口看门狗复位案例
以下是针对代码生成的详细注释,按功能模块划分:
/*** @brief 主函数入口,初始化硬件并进入主循环* @return int32_t 程序执行状态(通常不返回)*/
int32_t main(void)
{// 系统时钟配置(HSI->PLL 48MHz)RCC_Configuration();// GPIO初始化(按键输入PA1)GPIO_Configuration();// LED1初始化(PB9),默认点亮LED1.LED_Port = CW_GPIOB;LED1.LED_Pin = GPIO_PIN_9;LED_Init(&LED1);LED1.LED_On(&LED1);// LED2初始化(PB8),默认熄灭LED2.LED_Port = CW_GPIOB;LED2.LED_Pin = GPIO_PIN_8;LED_Init(&LED2);LED2.LED_Off(&LED2);// 系统节拍定时器初始化(250ms中断周期)SysTick_Config(SystemCoreClock / 1000 * 250);// 窗口看门狗配置(窗口值82,分频262144)WWDT_Config();// 中断控制器配置(优先级设定)NVIC_Configuration();// 检测是否因看门狗复位if (RCC_GetRstFlag(RCC_FLAG_WWDTRST)){LED2.LED_On(&LED2); // 若复位则点亮LED2指示}// 主循环(空跑)while (1) {}
}
/*** @brief 系统时钟配置(HSI->PLL 48MHz)* - HSI启用并校准(8MHz/6分频)* - PLL倍频到48MHz* - FLASH等待周期设为2(适应48MHz时钟)*/
void RCC_Configuration(void)
{// HSI使能,预分频6(默认8MHz输出)RCC_HSI_Enable(RCC_HSIOSC_DIV6);// AHB/APB总线无分频RCC_HCLKPRS_Config(RCC_HCLK_DIV1);RCC_PCLKPRS_Config(RCC_PCLK_DIV1);// PLL配置(HSI作为源,8MHz输入,6倍频至48MHz)RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000, 6);RCC_PLL_OUT();// FLASH等待周期配置(48MHz需2周期)__RCC_FLASH_CLK_ENABLE();FLASH_SetLatency(FLASH_Latency_2);// 切换系统时钟源至PLLRCC_SysClk_Switch(RCC_SYSCLKSRC_PLL);RCC_SystemCoreClockUpdate(48000000);
}
/*** @brief 窗口看门狗配置* - 时钟频率183Hz(分频262144)* - 窗口值82(约450ms窗口期)* - 计数器初始值0x7F(最大127)* - 启用中断*/
static void WWDT_Config(void)
{WWDT_InitTypeDef WWDT_InitStruct = {0};__RCC_WWDT_CLK_ENABLE();WWDT_InitStruct.WWDT_CounterValue = 0x7F;WWDT_InitStruct.WWDT_ITState = ENABLE;WWDT_InitStruct.WWDT_Prescaler = WWDT_Prescaler_DIV262144; // 5.46ms/周期WWDT_InitStruct.WWDT_WindowValue = 82; // 窗口期≈82*5.46ms≈450msWWDT_Init(&WWDT_InitStruct);WWDT_Cmd(); // 启动看门狗
}
/*** @brief SysTick中断服务函数* - 每250ms触发一次* - 喂狗操作(防止复位)* - LED1状态翻转*/
void SysTick_Handler(void)
{WWDT_FEED(0x7F); // 喂狗(重置计数器)LED1.LED_Toggle(&LED1); // LED1闪烁
}/*** @brief 看门狗中断服务函数* - 首次进入时喂狗2次并点亮LED1* - 后续若仍进入则触发系统复位*/
void WDT_IRQHandler(void)
{static uint8_t flag = 0;WWDT_ClearFlag(); // 清除中断标志if (flag < 2){WWDT_FEED(0x7F); // 喂狗延缓复位LED1.LED_On(&LED1); // LED1常亮作为预警flag++;}
}
/*** @brief GPIO配置* - PA1设置为下降沿触发输入(按键检测)*/
void GPIO_Configuration(void)
{GPIO_InitTypeDef GPIO_InitStruct;__RCC_GPIOA_CLK_ENABLE();GPIO_InitStruct.IT = GPIO_IT_FALLING; // 下降沿中断GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pins = GPIO_PIN_1;GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
}/*** @brief NVIC中断优先级配置* - SysTick优先级1* - GPIO/WDT中断优先级0(最高)*/
void NVIC_Configuration(void)
{__disable_irq();NVIC_SetPriority(SysTick_IRQn, 1);NVIC_SetPriority(GPIOA_IRQn, 0);NVIC_SetPriority(WDT_IRQn, 0);NVIC_EnableIRQ(WDT_IRQn);NVIC_EnableIRQ(GPIOA_IRQn);__enable_irq();
}