5.22 WWDG 使用说明
本章说明 N32G41x 标准外设库中 WWDG 驱动的文件组成与 8 个公开函数,内容包括预分频与窗口值配置、计数器装载与看门狗启动、提前唤醒中断的使能与标志管理,以及 WWDG_Reset 示例。刷新窗口、计数时间与寄存器位定义请配合用户手册的“窗口看门狗(WWDG)”章节阅读,芯片已知问题以勘误手册为准。
5.22.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32g41x_std_periph_driver/inc/n32g41x_wwdg.h |
定义预分频分频值宏与 WWDG_CFG、WWDG_CTRL、WWDG_STS 的位掩码,并按复位、配置、使能、中断与标志四个区段声明 8 个公开函数 |
firmware/n32g41x_std_periph_driver/src/n32g41x_wwdg.c |
实现上述 8 个函数:WWDG_CFG 的读改写、经 WWDG_CTRL 的计数器装载与启动、提前唤醒中断与标志位的读写 |
projects/n32g41x_EVAL/examples/WWDG/ |
WWDG 示例根目录,含 WWDG_Reset 1 个示例 |
projects/n32g41x_EVAL/examples/WWDG/WWDG_Reset/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32g41x_EVAL/bsp/ |
该示例引用的板级支持文件:评估板 LED 定义、毫秒延时函数与日志打印接口 |
5.22.2 API 参考
以下 8 个公开函数按 n32g41x_wwdg.h 的声明顺序分为 4 组;每个条目给出功能摘要与 n32g41x_wwdg.c 中该函数正上方的注释原文。
复位
WWDG_Reset
配置
WWDG_SetPrescalerDiv、WWDG_SetWValue、WWDG_SetCnt
使能
WWDG_EnableInt、WWDG_Enable
中断与标志
WWDG_GetEWINTF、WWDG_ClrEWINTF
void WWDG_Reset(void)将 WWDG 外设寄存器复位为默认复位值。
name WWDG_Reset.
fun Resets the WWDG peripheral registers to their default reset values.
return none
使用提示: 实现通过 RCC 的 APB1 外设复位把 WWDG 寄存器恢复为默认复位值。
void WWDG_SetPrescalerDiv(uint32_t WWDG_Prescaler)设置 WWDG 预分频器的分频值。
name WWDG_SetPrescalerDiv.
fun Set the WWDG Prescaler Division Value.
param WWDG_Prescaler :
- WWDG_PRESCALER_DIV1 WWDG Counter Clock (PCLK1 / 4096) / 1
- WWDG_PRESCALER_DIV2 WWDG Counter Clock (PCLK1 / 4096) / 2
- WWDG_PRESCALER_DIV4 WWDG Counter Clock (PCLK1 / 4096) / 4
- WWDG_PRESCALER_DIV8 WWDG Counter Clock (PCLK1 / 4096) / 8
return none
使用提示: 实现只改写 WWDG_CFG 的 TIMERB[1:0] 位,其余位保持原值,可再次调用改变分频而不影响窗口值。
void WWDG_SetWValue(uint16_t WindowValue)设置 WWDG 窗口值。
name WWDG_SetWValue.
fun Set the WWDG Window Value.
param WindowValue : WWDG Window Value
The value range of this parameter :
- 0x0040 ~ 0x3FFF
return none
使用提示: 实现把 WindowValue 与 0x3FFF 按位与后写入 WWDG_CFG 的 W[13:0],EWINT 与 TIMERB[1:0] 位保持原值。
void WWDG_SetCnt(uint16_t Counter)设置 WWDG 计数器的值。
name WWDG_SetCnt.
fun Set the WWDG Counter Value.
param Counter : WWDG Counter value
The value range of this parameter :
- 0x40 ~ 0x3FFF
return none
使用提示: 实现把 Counter 与 0x3FFF 按位与后直接写入 WWDG_CTRL,不需要读改写;向 ACTB 位写 0 不改变看门狗的使能状态。
void WWDG_EnableInt(void)使能 WWDG 提前唤醒中断(EWINT)。
name WWDG_EnableInt.
fun Enable WWDG Early Wakeup interrupt(EWINT).
return none
使用提示: 实现置位 WWDG_CFG 的 EWINT 位,同寄存器的分频值与窗口值保持不变。
void WWDG_Enable(uint16_t Counter)设置 WWDG 计数器的值并使能 WWDG。
name WWDG_Enable.
fun Set the WWDG Counter Value and Enable WWDG.
param Counter : WWDG Counter value
The value range of this parameter :
- 0x40 ~ 0x3FFF
return none
使用提示: 实现把 ACTB 位与掩码后的 Counter 一起写入 WWDG_CTRL,一次完成计数器装载与看门狗使能。
FlagStatus WWDG_GetEWINTF(void)获取 WWDG 提前唤醒中断标志。
name WWDG_GetEWINTF.
fun Get WWDG Early Wakeup Interrupt Flag.
return SET or RESET
使用提示: 实现读取 WWDG_STS 的 EWINTF 位,置位时返回 SET,否则返回 RESET。
void WWDG_ClrEWINTF(void)清除 WWDG 提前唤醒中断标志。
name WWDG_ClrEWINTF.
fun Clear WWDG Early Wake-up Interrupt Flag.
return none
使用提示: 实现向 WWDG_STS 写 0,即对 EWINTF 位写 0 清零。
5.22.3 Demo 示例说明
本节说明 WWDG 的 1 个示例:WWDG_Reset 在窗口内周期性刷新计数器,使 LED3 持续闪烁,并在刷新时刻越出窗口导致系统复位时点亮 LED1。
5.22.3.1 WWDG_Reset 窗口看门狗复位
工程目录: projects/n32g41x_EVAL/examples/WWDG/WWDG_Reset/
使能 WWDG 与 GPIO 时钟并打印示例信息→配置 LED1、LED3 为推挽输出→判断上次复位是否由 WWDG 触发并点亮 LED1→设置分频与窗口值后以 127 启动看门狗→主循环每 45 ms 翻转 LED3 并在窗口内重装计数器
| 项目 | 源码解读 |
|---|---|
| 功能 | 配置 WWDG 的预分频、窗口值与计数器后在窗口内周期刷新,正常运行时 LED3 持续闪烁; 上次复位由 WWDG 触发时点亮 LED1 提示。 刷新时刻落在窗口之外时系统反复复位,LED3 不再正常闪烁。 |
| 源码组成 | src/main.c:main 与 LedInit、LedOn、LedOff、LedBlink;inc/main.h:包含 WWDG、GPIO、RCC 与日志头文件;src/n32g41x_it.c、inc/n32g41x_it.h:中断服务函数;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程。LED 引脚宏来自 bsp/inc/n32g41x_stb.h,SysTick_Delay_Ms 来自 bsp/src/delay.c。 |
| 关键配置 | 时钟源为 HSE+PLL,N32G412 为 80 MHz、N32G415 为 96 MHz;WWDG_SetPrescalerDiv(WWDG_PRESCALER_DIV8) 把计数器时钟设为 (PCLK1/4096)/8,WWDG_SetWValue(80) 设窗口值,WWDG_Enable(127) 以计数器初值 127 启动。LED1 为 PA1、LED3 为 PB1,均配为推挽输出。 |
| 程序与数据路径 | main 调用 log_init 打印 --- WWDG demo reset ---,用 WWDG_ClrEWINTF 清提前唤醒标志,LedInit 初始化 LED1、LED3 后熄灭;读取 RCC_CTRLSTS_FLAG_WWDGRSTF 判断上次复位来源,命中时用 LedOn 点亮 LED1 并调用 RCC_ClearResetFlag;延时 1 秒后使能 WWDG 时钟并完成配置; while(1) 中 LedBlink 翻转 LED3,延时 45 ms(N32G412)或 35 ms(N32G415)后用 WWDG_SetCnt(127) 在窗口内重装计数器。 |
| 主要 API | WWDG_ClrEWINTF、WWDG_SetPrescalerDiv、WWDG_SetWValue、WWDG_Enable、WWDG_SetCnt、RCC_EnableAPB1PeriphClk、RCC_GetFlagStatus、RCC_ClearResetFlag、GPIO_InitStruct、GPIO_InitPeripheral、GPIO_SetBits、GPIO_ResetBits、GPIO_TogglePin |
| 验证方法 | 上电后串口打印 --- WWDG demo reset ---,LED3 持续闪烁,说明窗口值刷新正常;把 SysTick_Delay_Ms 的实参改到窗口时间之外后系统进入反复复位,每次复位后 LED1 点亮、串口打印 reset by WWDG。 |
| 使用提示 | 窗口值很小时系统处于频繁复位状态,容易导致程序无法正常下载; 示例在使能 WWDG 前加了 1 秒延时,也可改为拉高 BOOT0 引脚下载。 支持 N32G412x8L7、N32G412xBL7、N32G415x8L7、N32G415xBL7; 开发环境为 KEIL MDK-ARM V5.34 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例先判断上次复位来源并点亮 LED1 提示,再配置窗口看门狗,最后在主循环里周期性喂狗。
数据路径: main → WWDG_ClrEWINTF 清提前唤醒标志 → LedInit 初始化 LED1、LED3 → RCC_GetFlagStatus 判断 WWDG 复位标志 → RCC_EnableAPB1PeriphClk 打开 WWDG 时钟 → WWDG_SetPrescalerDiv、WWDG_SetWValue、WWDG_Enable 配置并启动看门狗 → WWDG_SetCnt 在窗口内重装计数器 → LED3 闪烁、LED1 提示复位
1. 板级宏给出两路 LED 的端口、引脚与时钟。 评估板的 LED 定义集中在 BSP 头文件里,示例通过 LEDx_PORT、LEDx_PIN 引用这组宏,换板时只改这里。
#define LED1_STB
#define LED1_PORT GPIOA
#define LED1_PIN GPIO_PIN_1
#define LED1_CLOCK RCC_AHB_PERIPH_GPIO
#define LED1_CLOCK_ENABLE RCC_EnableAHBPeriphClk(LED1_CLOCK, ENABLE)
#define LED1_ON_STATE Bit_SET
#define LED3_STB
#define LED3_PORT GPIOB
#define LED3_PIN GPIO_PIN_1
#define LED3_CLOCK RCC_AHB_PERIPH_GPIO
#define LED3_CLOCK_ENABLE RCC_EnableAHBPeriphClk(LED3_CLOCK, ENABLE)
#define LED3_ON_STATE Bit_SET
更换 LED 引脚时同步修改 LED1_PORT、LED1_PIN、LED3_PORT 与 LED3_PIN,示例代码不用改。
2. LedInit 打开端口时钟并把引脚配为推挽输出。 它先取结构体默认值,再设置引脚与输出模式,最后用 GPIO_InitPeripheral 一次性写入。
void LedInit(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_InitType GPIO_InitStructure;
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_GPIO, ENABLE);
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);
换成其它端口或输出类型时,要同步修改 GPIO_Module、Pin 与 GPIO_Mode 的取值。
3. 复位后先清提前唤醒标志并判断上次复位来源。 程序先清 WWDG_STS.EWINTF,再读 RCC 的 WWDG 复位标志;命中时点亮 LED1 标明上次复位由看门狗触发,并清除该标志。
/* Clear WWDG early wakeup interrupt flag */
WWDG_ClrEWINTF();
/* Initialize LED1 and LED3 */
LedInit(LED1_PORT, LED1_PIN);
LedInit(LED3_PORT, LED3_PIN);
LedOff(LED1_PORT, LED1_PIN);
LedOff(LED3_PORT, LED3_PIN);
/* Check if the system has resumed from WWDG reset */
if (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_WWDGRSTF) != RESET)
{
/* WWDG reset flag set */
LedOn(LED1_PORT, LED1_PIN);
log_info("reset by WWDG\n");
RCC_ClearResetFlag();
}
else
{
LedOff(LED1_PORT, LED1_PIN);
}
改指示灯时,需同步修改判断复位来源后 LedOn、LedOff 所传的引脚参数。
4. 延时一秒后配置窗口看门狗并启动。 先使能 APB1 的 WWDG 时钟,再依次设置 8 分频、窗口值 80,并以计数器初值 127 启动;N32G412 与 N32G415 两段分别只在对应宏下编译。
SysTick_Delay_Ms(1000);
/* WWDG configuration */
/* Enable WWDG clock */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_WWDG, ENABLE);
#ifdef N32G412
/*********************** For N32G412 ***********************/
/* WWDG clock counter = (PCLK1(40MHz)/4096)/8 = 1220Hz (~0.82ms per count)
WWDG timeout = ~0.82ms * (127-63) = ~52ms
WWDG window = ~0.82ms * (127-80) = ~38ms
Allowed feed window: counter 80~63 (38ms~52ms after last feed) */
WWDG_SetPrescalerDiv(WWDG_PRESCALER_DIV8);
WWDG_SetWValue(80);
WWDG_Enable(127);
#endif /* N32G412 */
#ifdef N32G415
/*********************** For N32G415 ***********************/
/* WWDG clock counter = (PCLK1(48MHz)/4096)/8 = 1464.8Hz (~683us per count)
WWDG timeout = ~683us * (127-63) = ~43.7ms
WWDG window = ~683us * (127-80) = ~32.1ms
Allowed feed window: counter 80~63 (32.1ms~43.7ms after last feed) */
WWDG_SetPrescalerDiv(WWDG_PRESCALER_DIV8);
WWDG_SetWValue(80);
WWDG_Enable(127);
#endif /* N32G412 */
移植到其它 PCLK1 频率时,按超时公式同步改分频值、窗口值与计数器初值,使刷新间隔仍落在窗口内。
5. 主循环在窗口内翻转 LED3 并重装计数器。 每轮先翻转 LED3,再按型号延时 45 ms 或 35 ms,最后把计数器重装回 127,刷新时刻落在窗口之内。
while (1)
{
/* Feed the watchdog within the window */
LedBlink(LED3_PORT, LED3_PIN);
#ifdef N32G412
SysTick_Delay_Ms(45);
#endif /* N32G412 */
#ifdef N32G415
SysTick_Delay_Ms(35);
#endif /* N32G415 */
WWDG_SetCnt(127);
}
改变喂狗节奏时,要同步修改 SysTick_Delay_Ms 的实参与 WWDG_SetCnt 的初值,保证刷新时刻不越出窗口。
对应源码: src/main.c、projects/n32g41x_EVAL/bsp/inc/n32g41x_stb.h
5.22.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| 使能后立即复位 | 使能 WWDG 前,计数器值 WWDG_CTRL.T[13:0] 的高 8 位 T[13:6] 中至少要有一位为 1,否则看门狗使能后会立即产生复位;传入 WWDG_Enable 的计数器实参应大于 0x40。 |
用户手册 |
| 刷新时机越出窗口 | 递减计数器在到达窗口值 W[13:0] 之前被刷新,或在 T6 变为 0 之后被刷新时,会向 MCU 产生复位;刷新必须落在 W[13:0] 与 0x3F 之间。 |
用户手册 |
| 提前唤醒中断标志的清除 | 计数器到达 0x40 时 WWDG_STS.EWINTF 由硬件置位,须由软件写入 0 清除,写入 1 无效;即使中断未使能,该标志也会置位,可用 WWDG_ClrEWINTF 清除。 |
用户手册 |
| 看门狗使能后无法关闭 | WWDG_CTRL.ACTB 由软件置位、仅在上电复位后由硬件清零;看门狗一旦使能会一直保持打开直到发生复位,无法用软件关闭。 |
用户手册 |
| 内核暂停时计数器的行为 | Cortex-M4 内核停止时 WWDG 计数器继续计数还是停止由 DBG_CTRL.WWDG_STOP 决定:该位为 1 时计数器停止,为 0 时正常计数。 |
用户手册 |
| 超时时间计算 | 超时按 T_WWDG = T_PCLK1 × 4096 × 2^TIMERB × (T[13:0] - 0x3F + 1) 计算;N32G412 在 PCLK1=40 MHz、TIMERB=0 时最大超时 1671.270 ms、最小超时 102.4 us,N32G415 在 PCLK1=48 MHz 时对应为 1392.725 ms 与 85.3 us。 |
用户手册 |
| 保留位与复位值 | WWDG_CFG、WWDG_CTRL 的复位值为 0x00003FFF,WWDG_STS 为 0x0000;三个寄存器的保留位必须保持复位值。 |
用户手册 |
N32G412、N32G415 系列勘误手册 V1.0.0(2026.6.30)的勘误列表只列出一行 A 版芯片条目,勘误链接列为空,未列出 WWDG 相关条目。