5.32 WWDG 使用说明
本章说明 N32H49x 标准外设库中 WWDG 驱动的文件组成与 8 个公开函数,以及 WWDG_Reset 示例。WWDG 为 14 位窗口看门狗,计数来自 APB1 时钟,只有在计数值落在刷新窗口内才允许喂狗,早喂或晚喂都会触发复位;窗口值与刷新窗口的计算请配合用户手册的“窗口看门狗(WWDG)”章节阅读。
5.32.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32h49x_std_periph_driver/inc/n32h49x_wwdg.h |
定义预分频与工作模式参数,声明 8 个公开函数 |
firmware/n32h49x_std_periph_driver/src/n32h49x_wwdg.c |
实现上述 8 个函数:寄存器复位、写入预分频、窗口值与计数值、使能与中断、提前唤醒中断标志的读取与清除 |
projects/n32h49x_EVAL/examples/WWDG/ |
WWDG 示例根目录,含 WWDG_Reset 1 个示例 |
projects/n32h49x_EVAL/examples/WWDG/WWDG_Reset/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32h49x_EVAL/bsp/ |
该示例引用的公共板级文件:串口日志与毫秒延时函数 |
5.32.2 API 参考
以下 8 个公开函数按 n32h49x_wwdg.h 的声明顺序分为 3 组;每个条目给出功能摘要与 n32h49x_wwdg.c 中该函数正上方的注释原文。
复位与配置
WWDG_DeInit、WWDG_SetPrescalerDiv、WWDG_SetWValue
计数与使能
WWDG_EnableInt、WWDG_SetCnt、WWDG_Enable
标志状态
WWDG_GetEWINTF、WWDG_ClrEWINTF
void WWDG_DeInit(void)将 WWDG 外设寄存器复位为默认复位值。
name WWDG_DeInit.
fun Resets the WWDG peripheral registers to their default reset values.
return none
void WWDG_SetPrescalerDiv(uint32_t WWDG_Prescaler)设置 WWDG 预分频值。
name WWDG_SetPrescalerDiv.
fun Set the WWDOG 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
void WWDG_SetWValue(uint16_t WindowValue)设置 WWDG 窗口值。
name WWDG_SetWValue.
fun Set the WWDOG Window Value.
param WindowValue : WWDOG Window Value
The value range of this parameter :
- 0x0040 ~ 0x3FFF
return none
void WWDG_EnableInt(void)使能 WWDG 提前唤醒中断(EWINT)。
name WWDG_EnableInt.
fun Enable WWDG Early Wakeup interrupt(EWINT).
return none
void WWDG_SetCnt(uint16_t Counter)设置 WWDG 计数值。
name WWDG_SetCnt.
fun Set the WWDOG Counter Value.
param Counter : WWDOG Counter value
The value range of this parameter :
- 0x40 ~ 0x3FFF
return none
void WWDG_Enable(uint16_t Counter)设置 WWDG 计数值并使能 WWDG。
name WWDG_Enable.
fun Set the WWDOG Counter Value and Enable WWDOG .
param Counter : WWDOG Counter value
The value range of this parameter :
- 0x40 ~ 0x3FFF
return none
使用提示: 实现按 WWDG->CTRL = CTRL_ACTB_SET | Counter 写入,即同时置说明位并写入 14 位计数值。
FlagStatus WWDG_GetEWINTF(void)获取 WWDG 提前唤醒中断标志。
name WWDG_GetEWINTF.
fun Get WWDOG Early Wake-up Interrupt Flag.
param none
return SET or RESET
void WWDG_ClrEWINTF(void)清除 WWDG 提前唤醒中断标志。
name WWDG_ClrEWINTF.
fun Clear WWDOG Early Wake-up Interrupt Flag.
return none
使用提示: 实现向 WWDG->STS 写 RESET(写 0)来清除提前唤醒中断标志。
5.32.3 Demo 示例说明
本节说明 WWDG 的 1 个示例:WWDG_Reset 配置刷新窗口并在主循环中定期更新计数值,用于演示刷新过早或过晚触发的 WWDG 复位。
5.32.3.1 WWDG_Reset WWDG 复位
工程目录: projects/n32h49x_EVAL/examples/WWDG/WWDG_Reset/
初始化串口日志与指示灯并清除提前唤醒中断标志→检查上次复位是否由 WWDG 触发并点亮 LED1→延时 1 秒以避免频繁复位导致下载困难→配置预分频、窗口值与计数值并启动 WWDG→主循环翻转 LED3、延时后更新计数值
| 项目 | 源码解读 |
|---|---|
| 功能 | 配置 WWDG 计数器时钟为 PCLK1/4096/8、窗口值 80、初始计数值 127; 主循环每 16 ms 更新一次计数值,正常运行时 LED3 持续闪烁,刷新过早或过晚会触发 WWDG 复位,复位后点亮 LED1 并在串口打印 reset by WWDG。 |
| 源码组成 | src/main.c:main 与 LedInit、LedOn、LedOff、LedBlink;inc/main.h:包含 n32h49x_wwdg.h、n32h49x_rcc.h、n32h49x_gpio.h、delay.h、log.h;src/n32h49x_it.c、inc/n32h49x_it.h:中断服务函数;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程。 |
| 关键配置 | 时钟:RCC_EnableAPB1PeriphClk 使能 WWDG 与 PWR 时钟,预分频 WWDG_PRESCALER_DIV8;窗口与计数: WWDG_SetWValue(80)、WWDG_Enable(127),刷新须使计数值落在 64 到 80 之间;指示灯:LED1 为 PA3、LED3 为 PA8,推挽输出; 使能前有 1 秒延时,避免频繁复位影响下载。 |
| 程序与数据路径 | main 调用 log_init,用 WWDG_ClrEWINTF 清提前唤醒中断标志,初始化并熄灭 LED1、LED3,再使能 PWR 时钟;检查 RCC_FLAG_WWDGRSTF,置位时点亮 LED1、打印 reset by WWDG 并清除复位标志,否则熄灭 LED1;延时 1 秒后使能 WWDG 时钟并配置预分频、窗口值与计数值; while(1) 中翻转 PA8(LED3)、延时 16 ms,再用 WWDG_SetCnt(127) 更新计数值。 |
| 主要 API | WWDG_SetPrescalerDiv、WWDG_SetWValue、WWDG_Enable、WWDG_SetCnt、WWDG_ClrEWINTF |
| 验证方法 | 编译下载并复位运行后 LED3 约每 16 ms 翻转、持续闪烁,说明刷新落在窗口内; 把 systick_delay_ms 的参数改到窗口区间之外(过小或过大),系统将持续复位、LED1 点亮,串口打印 reset by WWDG。 |
| 使用提示 | 硬件开发环境为全功能板 N32H497ZGL7_EVB V1.0; 开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1; 窗口值很小时系统可能频繁复位导致程序无法正常下载,示例在使能 WWDG 前加了 1 秒延时来规避,也可在下载时直接把 BOOT0 引脚拉高。 |
核心代码解读与移植
示例先清提前唤醒中断标志并判断上次复位是否来自 WWDG,预先延时 1 秒规避下载问题,随后配置并启动 WWDG,最后在主循环中更新计数值。
数据路径: WWDG_ClrEWINTF 清标志 → RCC_FLAG_WWDGRSTF 复位标志 → WWDG_SetPrescalerDiv、WWDG_SetWValue、WWDG_Enable 写 WWDG 寄存器 → 主循环 WWDG_SetCnt 更新计数值 → LED3 翻转、复位时 LED1 点亮
1. 初始化日志、指示灯与中断标志。 main 先调用 log_init,清除提前唤醒中断标志,把 LED1(PA3)与 LED3(PA8)初始化为推挽输出并熄灭,再使能 PWR 时钟。
log_init();
log_info("--- WWDG demo reset ---\n");
WWDG_ClrEWINTF();
LedInit(GPIOA, LED1 | LED3);
LedOff(GPIOA, LED1 | LED3);
/* Enable PWR Clock */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_PWR, ENABLE);
移植到其它板卡时改 LED1、LED3 两个引脚宏即可;WWDG_ClrEWINTF 需在使能 WWDG 前调用,避免上一次的标志残留。
2. 检查复位来源并显示。 读取 RCC_FLAG_WWDGRSTF:若本次复位由 WWDG 触发就点亮 LED1、打印提示并清除复位标志,否则熄灭 LED1。
/* Check if the system has resumed from WWDG reset */
if (RCC_GetFlagStatus(RCC_FLAG_WWDGRSTF) != RESET)
{
/* WWDGRST flag set */
/* Turn on LED1 */
LedOn(GPIOA, LED1);
log_info("reset by WWDG\n");
/* Clear reset flags */
RCC_ClearResetFlag();
}
else
{
/* WWDGRST flag is not set */
/* Turn off LED1 */
LedOff(GPIOA, LED1);
}
移植时要保留清除复位标志的调用,否则下一次上电仍会读到旧的复位来源。
3. 使能前延时 1 秒。 窗口值很小时系统可能处于频繁复位状态,导致程序无法正常下载;示例在这里延时 1 秒来规避。
/*
When the window value is very small, the system is in a frequent reset state,
at this time, easy to cause the program can not download normally.
Add a delay of 1 second here to avoid this phenomenon. Of course,
it can also be downloaded without delay, directly pull the pin of BOOT0 high.
*/
systick_delay_ms(1000);
移植时如需缩短上电等待可以调小该延时,但要同时保证能正常下载程序。
4. 配置并启动 WWDG。 使能 WWDG 时钟后,依次写入预分频、窗口值与计数值,WWDG_Enable 在写入计数值的同时启动计数器。
/* WWDG configuration */
/* Enable WWDG clock */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_WWDG, ENABLE);
/* WWDG clock counter = 1/((PCLK1(120MHz)/4096)/8) = (~273 us) */
/* WWDG clock counter = 1/((PCLK1(100MHz)/4096)/8) = (~327 us) */
WWDG_SetPrescalerDiv(WWDG_PRESCALER_DIV8);
/* Set Window value to 80; WWDG counter should be refreshed only when the counter
is below 80 (and greater than 64) otherwise a reset will be generated */
WWDG_SetWValue(80);
/*
When PCLK1 = 120MHz, in this case the refresh window is: ~273 us * (127-80) = 12.831 ms < refresh window < ~273 us * (127-63) = 17.472ms
When PCLK1 = 100MHz, in this case the refresh window is: ~327 us * (127-80) = 15.401 ms < refresh window < ~327 us * (127-63) = 20.971ms
*/
WWDG_Enable(127);
刷新窗口由预分频、窗口值与当前计数值共同决定,改任意一个都要重新核对窗口区间。
5. 主循环更新计数值。 循环里翻转 LED3、延时 16 ms,再调用 WWDG_SetCnt(127) 更新计数值。
while (1)
{
/* Toggle LED3 */
LedBlink(GPIOA, LED3);
systick_delay_ms(16);
/* Update WWDG counter */
WWDG_SetCnt(127);
}
延时 16 ms 落在示例的刷新窗口内;改到窗口之外会触发 WWDG 复位。
对应源码: src/main.c
5.32.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| 刷新窗口 | 计数器在递减到计数值 0x40 之前(即计数值仍大于 0x3F)必须刷新,否则产生复位。 | 用户手册 |
| 窗口值约束 | 刷新只允许发生在计数值小于窗口值时; 窗口值写入 WWDG_CFG.W[13:0],且 T[13:6] 中至少要有一位为 1,即窗口值不小于 0x40。 |
用户手册 |
| 计数值初值 | 计数器初值须大于 0x3F,且不大于窗口值,否则启动即不满足刷新窗口条件。 | 用户手册 |
| 提前唤醒中断标志 | 提前唤醒中断标志 EWINTF 为写 0 清除;在提前唤醒中断中刷新计数器可避免复位,但刷新同样须满足窗口条件。 |
用户手册 |
| 调试模式下停止 | 内核调试停止时 WWDG 是否冻结由调试模块的 DBG_CTRL.WWDG_STOP 位决定。 |
用户手册 |
| 时钟来源 | WWDG 计数器时钟来自 PCLK1,经固定 4096 分频后再由预分频系数分频; 使能 WWDG 前必须先使能其 APB1 时钟。 |
用户手册 |