Xiashiqi 发表于 2025-8-1 13:44

CW32F030C8T6:窗口看门狗功能全解析

一.窗口看门狗(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);

    // 切换系统时钟源至PLL
    RCC_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≈450ms
    WWDT_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();
}




————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_43260261/article/details/149110563

复古留声机 发表于 2025-8-2 22:16

这篇文章详细解释了窗口看门狗定时器(WWDT)的工作原理和配置方法,对于嵌入式系统开发人员来说非常有用。
页: [1]
查看完整版本: CW32F030C8T6:窗口看门狗功能全解析