5.12 NVIC 使用说明
本章说明 N32G033 标准外设库中 NVIC 相关的文件组成、2 个公开函数,以及 IRQ_Mask 1 个示例。中断与异常的向量分配、优先级与嵌套响应请配合用户手册的“中断和事件”章节阅读,芯片已知问题以勘误手册为准。
5.12.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32g033_std_periph_driver/inc/misc.h |
定义 NVIC 初始化结构体 NVIC_InitType 与 SysTick 时钟源宏,并声明 NVIC、SysTick 两个配置函数 |
firmware/n32g033_std_periph_driver/src/misc.c |
实现上述两个函数:NVIC 中断通道与优先级初始化、SysTick 时钟源选择 |
projects/n32g033_EVAL/examples/NVIC/ |
NVIC 示例根目录,含 IRQ_Mask 1 个示例 |
projects/n32g033_EVAL/examples/NVIC/IRQ_Mask/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32g033_EVAL/bsp/ |
示例共用的板级支持文件:delay.h 的 SysTick 延时与 log.h 的串口日志接口 |
5.12.2 API 参考
以下 2 个公开函数按 misc.h 的声明顺序分为 1 组;每个条目给出功能摘要与 misc.c 中该函数正上方的注释原文。
中断与系统节拍配置
NVIC_Init、SysTick_CLKSourceConfig
void NVIC_Init(NVIC_InitType* NVIC_InitStruct)按 NVIC_InitStruct 中的参数初始化 NVIC 外设。
name NVIC_Init
fun Initializes the NVIC peripheral according to the specified parameters in the NVIC_structure_initializes.
param NVIC_InitStruct (The input parameters must be the following values) :
- NVIC_IRQChannel :
- IRQn_Type N32G033 Interrupt Number Definition
- NVIC_IRQChannelPriority :
- NVIC_PRIORITY_0
- NVIC_PRIORITY_1
- NVIC_PRIORITY_2
- NVIC_PRIORITY_3
- NVIC_IRQChannelCmd :
- ENABLE
- DISABLE
return none
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)配置 SysTick 时钟源。
name SysTick_CLKSourceConfig
fun Configures the SysTick clock source.
param SysTick_CLKSource (The input parameters must be the following values) :
- SysTick_CLKSource_HCLK_Div8 External clock selected as SysTick clock source.
- SysTick_CLKSource_HCLK AHB clock selected as SysTick clock source.
return none
5.12.3 Demo 示例说明
本节说明 NVIC 的 1 个示例:IRQ_Mask 用 TIM3 的更新中断周期打印日志,并通过按键的 EXTI 中断与全局中断开关演示中断屏蔽。
5.12.3.1 IRQ_Mask 中断屏蔽
工程目录: projects/n32g033_EVAL/examples/NVIC/IRQ_Mask/
使能 GPIO、EXTI 与 TIM3 时钟→把按键引脚配成上拉输入并接到 EXTI 线→配置 TIM3 时基与更新中断→在主循环里按按键开关全局中断
| 项目 | 源码解读 |
|---|---|
| 功能 | 让 TIM3 的更新中断每秒打印一次日志,按一次按键用全局中断开关屏蔽或恢复中断响应。 |
| 源码组成 | src/main.c 含 TIM_Config、KeyInputExtiInit 与主循环;src/n32g033_it.c 中的 EXTI0_6_IRQHandler、TIM3_IRQHandler 为中断服务函数;inc/main.h 定义按键引脚、EXTI 线与中断号宏;readme.txt 给出配置与测试步骤;工程文件在 MDK-ARM/ 与 EWARM/。 |
| 关键配置 | 按键:PA4 为上拉输入,接 EXTI_LINE1,中断号 EXTI0_6_IRQn,优先级 1;TIM3:预分频 SystemCoreClock/1200-1、周期 0x4AF,中断号 TIM3_IRQn,优先级 0;串口:波特率 115200,TX PA9、RX PA10。 |
| 程序与数据路径 | main → log_init 初始化串口 → KeyInputExtiInit 配按键引脚、EXTI 线与中断 → TIM_Config 配 TIM3 时基并开更新中断 → 主循环等按键状态置位后调用 __disable_irq,再等按键松开后调用 __enable_irq。 |
| 主要 API | NVIC_Init |
| 验证方法 | 把串口工具接到 PA9 并打开接收; 全速运行时每秒打印一次定时器中断信息,按下 KEY1(PA4)后停住,再按一次继续打印。 |
| 使用提示 | 开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1,硬件基于评估板 N32G033K8Q7-1_STB V1.0; 系统时钟 64 MHz。 |
核心代码解读与移植
示例把 TIM3 更新中断与按键 EXTI 中断分别接入 NVIC,再用全局中断开关控制是否响应。
数据路径: KeyInputExtiInit 把 PA4 接到 EXTI_LINE1 并设 EXTI0_6_IRQn 优先级 → TIM_Config 配 TIM3 时基并设 TIM3_IRQn 优先级 → 主循环等按键状态 → __disable_irq 屏蔽可配置优先级中断 → 等按键松开 → __enable_irq 恢复响应
1. 每个中断通道各用一次 NVIC_Init 设置优先级。 按键与 TIM3 属于两个通道,分别传入各自的 IRQn_Type 与优先级。
/*Set key input interrupt priority*/
NVIC_InitStructure.NVIC_IRQChannel = KEY_INPUT_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the TIM3 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
两次配置的优先级不同,移植时按系统优先级规划统一编排各通道的取值。
2. 主循环用 __disable_irq 与 __enable_irq 开关全局中断。 屏蔽期间可配置优先级的中断都不再响应,等待按键松开后再恢复。
while (Key_Status == DISABLE)
{
}
log_info("Disable irq \r\n");
/* This instruction raises the execution priority to 0. This prevents all
exceptions with configurable priority from activating, other than through
the HardFault fault escalation mechanism. */
__disable_irq();
while (GPIO_ReadInputDataBit(KEY_INPUT_PORT, KEY_INPUT_PIN) != SET)
{
}
while (GPIO_ReadInputDataBit(KEY_INPUT_PORT, KEY_INPUT_PIN) != RESET)
{
}
log_info("enable irq \r\n");
/* This instruction will allow all exceptions with configurable priority to
be activated. */
__enable_irq();
屏蔽期间的引脚轮询不依赖中断,去掉 __disable_irq 后按键将无法起到暂停日志的作用。
3. 中断服务函数按标志分支清挂起位。 两个处理函数分别对应按键的 EXTI 线与 TIM3 更新事件,清标志后完成各自动作。
void EXTI0_6_IRQHandler(void)
{
/* EXTI IRQHandler */
log_info("EXTI IRQHandler \r\n");
if (EXTI_GetITStatus(KEY_INPUT_EXTI_LINE) != RESET)
{
if (Key_Status == ENABLE)
{
Key_Status = DISABLE;
}
else
{
Key_Status = ENABLE;
}
/* Clears the SEL Button EXTI line pending bits. */
EXTI_ClrITPendBit(KEY_INPUT_EXTI_LINE);
}
}
void TIM3_IRQHandler(void)
{
/* Clear TIM3 update interrupt */
TIM_ClrIntPendingBit(TIM3, TIM_INT_UPDATE);
/* TIM3 IRQHandler */
log_info("TIM3 IRQHandler \r\n");
}
清挂起位必须在分支内完成,移植时保持标志判断与清除成对出现。
对应源码: src/main.c、src/n32g033_it.c、firmware/n32g033_std_periph_driver/inc/misc.h
5.12.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| 可屏蔽中断通道数与优先级级数 | 用户手册中断和事件章写明 N32G033 有 21 个可屏蔽中断通道、4 个可编程优先等级(使用 2 位中断优先级); 配置优先级时不要超过该级数。 |
用户手册 |
| 异常与中断的向量优先级 | 用户手册中断和事件章给出各异常与中断的优先级分配,如 SVCall 为 3、SysTick 为 6、EXTI0_6 为 9、TIM3 为 19; 规划通道优先级时以此表为准。 |
用户手册 |
| 用 EXTI 产生中断的条件 | 用户手册中断和事件章写明要产生中断必须使能外部中断控制器的 NVIC 中断通道,并向 EXTI_IMASK 对应位写 1;只配置触发边沿而未开放屏蔽位不会进入中断。 |
用户手册 |
| SysTick 校准值与时间基准 | 用户手册中断和事件章写明系统嘀嗒校准值固定为 8000,当系统嘀嗒时钟设定为 8 MHz(HCLK/8 的最大值)时产生 1 ms 时间基准; 选择时钟源时按此关系核对频率。 |
用户手册 |
勘误手册 V1.0.0(2025.9.25)针对 A 版芯片,未列出 NVIC 相关条目。