5.13 IWDG 使用说明
本章说明 N32G41x 标准外设库中 IWDG 驱动的文件组成与 7 个公开函数,内容包括写保护配置、预分频与重装载值设置、计数器重装与冻结控制,以及状态标志读取;示例部分说明 IWDG_Reset 如何用超时未喂狗触发系统复位。寄存器定义、配置流程与调试暂停行为请配合用户手册的“独立看门狗(IWDG)”章节阅读,芯片已知问题以勘误手册为准。
5.13.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32g41x_std_periph_driver/inc/n32g41x_iwdg.h |
定义 IWDG 状态标志与写访问配置枚举、密钥命令字与预分频宏,并在配置、使能、标志三个区段声明 7 个公开函数 |
firmware/n32g41x_std_periph_driver/src/n32g41x_iwdg.c |
实现上述 7 个函数:向 KEY 写密钥命令、限次等待 PVU 清零后写 PREDIV 与 RELV、冻结与解冻控制、状态标志读取 |
projects/n32g41x_EVAL/examples/IWDG/ |
IWDG 示例根目录,含 IWDG_Reset 1 个示例 |
projects/n32g41x_EVAL/examples/IWDG/IWDG_Reset/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32g41x_EVAL/bsp/ |
示例引用的板级支持文件:评估板 LED 引脚定义、毫秒延时函数与日志打印函数 |
5.13.2 API 参考
以下 7 个公开函数按 n32g41x_iwdg.h 的声明顺序分为 3 组;每个条目给出功能摘要与 n32g41x_iwdg.c 中该函数正上方的注释原文。
配置
IWDG_WriteConfig、IWDG_SetPrescalerDiv、IWDG_CntReload、IWDG_ReloadKey
使能与禁用
IWDG_Enable、IWDG_Freeze_Enable
标志管理
IWDG_GetStatus
void IWDG_WriteConfig(IWDG_WRITE_CONFIG IWDG_WriteAccess)配置 IWDG_PREDIV 与 IWDG_RELV 寄存器的写保护。
name IWDG_WriteConfig.
fun Config write protection of IWDG_PREDIV and IWDG_RELV registers.
param IWDG_WriteAccess : key value written to IWDG_KEY.KEYV[15:0]
- IWDG_WRITE_ENABLE (0x5555) : disable the write protection, so
that IWDG_PREDIV and IWDG_RELV become writable
- IWDG_WRITE_DISABLE (0x0000) : re-arm the write protection
return none
void IWDG_SetPrescalerDiv(uint8_t IWDG_Prescaler)设置 IWDG 预分频系数(IWDG_PREDIV.PD[2:0])。
name IWDG_SetPrescalerDiv.
fun Sets the IWDG prescaler divider ratio (IWDG_PREDIV.PD[2:0]).
param IWDG_Prescaler : prescaler divider, one of :
- IWDG_PRESCALER_DIV4 (PD[2:0] = 0b000, divisor 4)
- IWDG_PRESCALER_DIV8 (PD[2:0] = 0b001, divisor 8)
- IWDG_PRESCALER_DIV16 (PD[2:0] = 0b010, divisor 16)
- IWDG_PRESCALER_DIV32 (PD[2:0] = 0b011, divisor 32)
- IWDG_PRESCALER_DIV64 (PD[2:0] = 0b100, divisor 64)
- IWDG_PRESCALER_DIV128 (PD[2:0] = 0b101, divisor 128)
- IWDG_PRESCALER_DIV256 (PD[2:0] = 0b111, divisor 256)
return none
使用提示: 实现先用上限 IWDG_PVU_POLL_LIMIT(0x0000FFFF)的循环等待 IWDG_STS.PVU 清零,再写 IWDG->PREDIV;等待有上限,函数不会无限阻塞。
void IWDG_CntReload(uint16_t Reload)设置 IWDG 重装载值。
name IWDG_CntReload.
fun Sets IWDG reload value.
param Reload :
- 0x000 ~ 0xFFF (REL[11:0]); larger values are truncated by the field mask
return none
使用提示: 实现把入参与 IWDG_RELV_REL 掩码相与后写入 IWDG->RELV,大于 0xFFF 的值被截断。
void IWDG_ReloadKey(void)用 IWDG_RELV 寄存器中定义的值重新加载 IWDG 计数器。
name IWDG_ReloadKey.
fun Reload IWDG counter with value defined in IWDG_RELV register.
param none
return none
void IWDG_Enable(void)启动看门狗计数器。
name IWDG_Enable.
fun Start watch dog counter.
param none
return none
void IWDG_Freeze_Enable(FunctionalState Cmd)在 RUN 模式下 IWDG 运行期间冻结或解冻 IWDG。
name IWDG_Freeze_Enable.
fun Freeze or unfreeze IWDG while IWDG is running in run mode.
param Cmd : freeze control, written to IWDG_KEY.KEYV[15:0]
- ENABLE : 0x4567, stops the IWDG counter in RUN mode
- DISABLE : 0x89AB, resumes the counter in RUN mode
return none
使用提示: 实现仅在 Cmd 为 ENABLE 时写 IWDG_FREEZE(0x4567),其余取值都写 IWDG_UNFREEZE(0x89AB)。
FlagStatus IWDG_GetStatus(IWDG_STATUS_FLAG IWDG_FLAG)检查指定的 IWDG 标志是否置位。
name IWDG_GetStatus.
fun Checks whether the specified IWDG flag is set or not.
param IWDG_FLAG : status flag selected in the IWDG_STS register
- IWDG_PVU_FLAG
- IWDG_CRVU_FLAG
- IWDG_FRZF_FLAG
return FlagStatus :
- RESET
- SET
5.13.3 Demo 示例说明
本节说明 IWDG 的 1 个示例:IWDG_Reset 让看门狗在超时未喂狗时触发系统复位,并用 LED 与串口指示复位来源。
5.13.3.1 IWDG_Reset 独立看门狗复位
工程目录: projects/n32g41x_EVAL/examples/IWDG/IWDG_Reset/
使能 LSI 时钟并让调试暂停时 IWDG 停止→设置预分频与重装载值并启动看门狗→主循环翻转 LED3 并定时喂狗→喂狗间隔超过超时时间触发系统复位→复位后判读复位标志点亮 LED1
| 项目 | 源码解读 |
|---|---|
| 功能 | 演示 IWDG 超时复位:正常喂狗时 LED3 持续闪烁; 把喂狗间隔改到超过超时时间后系统反复复位,复位后 LED1 常亮并由串口打印 reset by IWDG。 |
| 源码组成 | src/main.c:main、MCO_Configuration、LedInit、LedOn、LedOff、LedBlink 与可选的 GTIM3_ConfigForLSI;inc/main.h:包含各驱动头文件,定义 MCO 引脚与复用宏、LSI 测量相关宏;src/n32g41x_it.c、inc/n32g41x_it.h:中断服务函数与可选的 GTIM3_IRQHandler;readme.txt:功能、环境与测试步骤;MDK-ARM/、EWARM/:Keil 与 IAR 工程。LED 引脚宏来自 bsp/inc/n32g41x_stb.h,SysTick_Delay_Ms 来自 bsp/src/delay.c。 |
| 关键配置 | IWDG 时钟为 LSI/32(IWDG_PRESCALER_DIV32),重装载值为 LsiFreq / 128,超时约 250 ms;LsiFreq 默认 32000 Hz,main 中通过 DBG_ConfigPeriph(DBG_IWDG_STOP, ENABLE) 让内核暂停时停止计数。LED1 为 PA1、LED3 为 PB1,推挽输出; MCO 引脚为 PA8,N32G412 复用为 GPIO_AF7、N32G415 复用为 GPIO_AF13。系统时钟为 HSE+PLL,N32G412 为 80 MHz,N32G415 为 96 MHz。 |
| 程序与数据路径 | main 先配置调试暂停行为并打开 LSI 时钟、等待 RCC_CTRL_FLAG_LSIRDF,再把 MCO 配为输出 LSI、初始化 LED 与日志;延时 1 s 后读 RCC_CTRLSTS_FLAG_IWDGRSTF 判断本次复位是否来自 IWDG,是则点亮 LED1 并清除复位标志;随后解除写保护、设置预分频与重装载值、重装计数器并使能看门狗; while(1) 中翻转 LED3、延时 249 ms 后重装计数器。 |
| 主要 API | DBG_ConfigPeriph、RCC_EnableLsi、RCC_GetFlagStatus、RCC_ClearResetFlag、IWDG_WriteConfig、IWDG_SetPrescalerDiv、IWDG_CntReload、IWDG_ReloadKey、IWDG_Enable |
| 验证方法 | 运行后 LED3 持续闪烁,说明喂狗正常; 把 SysTick_Delay_Ms(249) 的参数改成 251 及以上,系统反复复位,LED1 常亮,串口打印 reset by IWDG。未启用 LSI 测量时可用 MCO(PA8)在示波器上观察 LSI 实际频率。 |
| 使用提示 | 支持 N32G412x8L7、N32G412xBL7、N32G415x8L7、N32G415xBL7; 开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1。 inc/main.h 中的 LSI_TIM_MEASURE 默认被注释关闭,启用后由 GTIM3 输入捕获自动测量 LSI 频率用于超时计算。 |
核心代码解读与移植
示例先准备 LSI 时钟与看门狗在调试暂停下的行为,再配置超时、启动看门狗,最后在主循环中喂狗并根据复位标志判断复位来源。
数据路径: DBG_ConfigPeriph 与 RCC_EnableLsi 打开 LSI → IWDG_WriteConfig、IWDG_SetPrescalerDiv、IWDG_CntReload 写入 PREDIV、RELV → IWDG_Enable 启动计数器 → IWDG_ReloadKey 在 while(1) 中重装计数器 → 超时则 RCC_CTRLSTS_FLAG_IWDGRSTF 置位 → LedOn 点亮 LED1
1. 准备 LSI 时钟与调试暂停行为。 看门狗由 LSI 驱动,main 先让内核在调试暂停时停止 IWDG 计数,再打开 LSI 并轮询就绪标志,保证后续超时配置基于稳定的时钟。
DBG_ConfigPeriph(DBG_IWDG_STOP, ENABLE);
/* Enable LSI Clock */
RCC_EnableLsi(ENABLE);
while (RCC_GetFlagStatus(RCC_CTRL_FLAG_LSIRDF) != SET)
{
}
希望暂停调试时看门狗继续计数,就把 DBG_IWDG_STOP 换成其它外设宏或去掉这一句;LSI 就绪等待与超时计算相关,不要删除。
2. 配置预分频与重装载值并启动看门狗。 这段先解除 PREDIV、RELV 的写保护,按 LSI/32 设置预分频,再用 LsiFreq / 128 换算出约 250 ms 的重装载值,重装计数器后启动看门狗。
/* IWDG timeout equal to 250 ms (the timeout may varies due to LSI frequency
dispersion) */
/* Enable write access to IWDG_PR and IWDG_RLR registers */
IWDG_WriteConfig(IWDG_WRITE_ENABLE);
/* IWDG counter clock: LSI/32 */
IWDG_SetPrescalerDiv(IWDG_PRESCALER_DIV32);
/* Set counter reload value to obtain 250ms IWDG TimeOut.
Counter Reload Value = 250ms/IWDG counter clock period
= 250ms / (LSI/32)
= 0.25s / (LsiFreq/32)
= LsiFreq/(32 * 4)
= LsiFreq/128 */
log_debug("LsiFreq is: %d\n", LsiFreq);
IWDG_CntReload(LsiFreq / 128);
/* Reload IWDG counter */
IWDG_ReloadKey();
/* Enable IWDG (the LSI oscillator will be enabled by hardware) */
IWDG_Enable();
超时由预分频因子与重装载值共同决定;换预分频时要同步改 LsiFreq / 128 这个换算,并确认 LsiFreq 与实际 LSI 频率一致。
3. 在主循环中喂狗。 主循环先翻转 LED3 表示程序在运行,再在延时 249 ms(小于 250 ms 超时)后重装计数器,使看门狗不被触发。
while (1)
{
/* Toggle LED3 */
LedBlink(LED3_PORT, LED3_PIN);
/* Insert 249 ms delay (exceeds IWDG timeout -> reset) */
SysTick_Delay_Ms(249);
/* Reload IWDG counter */
IWDG_ReloadKey();
}
喂狗间隔必须小于重装载值换算出的超时时间;把 SysTick_Delay_Ms 的参数改到 251 及以上即触发复位,可用于验证超时。
4. 由复位标志判断复位来源。 复位后先读 RCC_CTRLSTS_FLAG_IWDGRSTF,置位说明本次复位来自 IWDG,点亮 LED1、打印提示后清除复位标志,未置位则熄灭 LED1。
/* Check if the system has resumed from IWDG reset */
if (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_IWDGRSTF) != RESET)
{
/* IWDGRST flag set */
LedOn(LED1_PORT, LED1_PIN);
log_info("reset by IWDG\n");
/* Clear reset flags */
RCC_ClearResetFlag();
}
else
{
/* IWDGRST flag is not set */
LedOff(LED1_PORT, LED1_PIN);
}
RCC_ClearResetFlag 会清除全部复位标志,需要区分多个复位来源时注意它会一并清掉其它标志;复位后 LED1 常亮即表示系统已发生过 IWDG 复位。
对应源码: src/main.c、inc/main.h、projects/n32g41x_EVAL/bsp/inc/n32g41x_stb.h
5.13.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| 修改预分频值或重装载值前未解除写保护 | IWDG_PREDIV 与 IWDG_RELV 受写保护,修改前必须向 IWDG_KEY.KEYV[15:0] 写 0x5555;写入其它任何值都会重新启用写保护,重装载操作(写 0xAAAA)也会启动写保护。 |
用户手册 |
| 预分频或重装载值更新未生效 | 只有在 IWDG_STS.PVU 与 IWDG_STS.CRVU 分别为 0 时才能更新对应的预分频值和重装载值;更新进行中硬件置位对应位,此时回读 IWDG_PREDIV.PD 或 IWDG_RELV.REL 无效,须等硬件清零后再读。 |
用户手册 |
| 计数器到 0 未产生复位 | 只有当 PWR_CTRL.IWDGRSTEN 为 1 时,IWDG 计数器递减到 0x000 才产生系统复位;该位为 0 时 IWDG 仍计数,但不产生复位。 |
用户手册 |
| 调试暂停时计数器行为 | 调试模式下 Cortex-M4 内核停止时,IWDG 计数器继续运行还是停止由 DBG_CTRL.IWDG_STOP 决定:该位为 1 时停止计数,为 0 时照常计数。 |
用户手册 |
| 看门狗使能后无法自行停止 | IWDG 一旦由软件或硬件使能,除非发生系统复位或写入 0x4567 冻结,否则不会停止计数; SLEEP、STOP 模式下的冻结分别由选项字节 FLASH_OB.IWDGSLEEPFRZ、FLASH_OB.IWDGSTOPFRZ 配置。 |
用户手册 |
N32G412、N32G415 系列勘误手册 V1.0.0(2026.6.30)的勘误列表只列出一行 A 版芯片条目,勘误链接列为空,未列出 IWDG 相关条目。