GD32F407 NVIC(嵌套向量中断控制器)详细笔记
掌握 NVIC,才能真正玩转 STM32/GD32!
·
1. NVIC 基本概念
1.1 NVIC 作用
NVIC(Nested Vectored Interrupt Controller)是 ARM Cortex-M4 内核的一部分,主要负责 管理和调度中断,包括:
-
使能/屏蔽中断
-
设置中断优先级
-
响应和分发中断
-
支持中断嵌套
1.2 中断优先级划分
在 GD32F407 中,中断优先级由 先占优先级(Preempt Priority) 和 子优先级(Sub Priority) 组成。
-
先占优先级:决定是否可以抢占正在执行的中断(数值越小,优先级越高)。
-
子优先级:用于区分同一先占优先级下的中断,数值小的会优先执行。
2. NVIC 相关寄存器
| 寄存器名 | 作用 |
|---|---|
| NVIC_ISER (中断使能寄存器) | 用于使能中断 |
| NVIC_ICER (中断清除寄存器) | 用于禁用中断 |
| NVIC_ISPR (中断挂起寄存器) | 设置中断挂起标志 |
| NVIC_ICPR (中断清除挂起寄存器) | 清除中断挂起标志 |
| NVIC_IABR (中断活动标志寄存器) | 读取当前中断是否处于活动状态 |
| NVIC_IPR (中断优先级寄存器) | 设置中断优先级 |
3. NVIC 中断优先级配置
3.1 设置优先级分组
GD32F407 允许通过 NVIC_SetPriorityGrouping() 设置优先级分组,影响先占优先级和子优先级的位数。
| PRIGROUP 值 | 先占优先级位数 | 子优先级位数 |
|---|---|---|
| 0 | 4 | 0 |
| 1 | 3 | 1 |
| 2 | 2 | 2 |
| 3 | 1 | 3 |
| 4 | 0 | 4 |
示例代码:
void NVIC_Configuration(void) {
// 设置优先级分组: 2 位先占优先级 + 2 位子优先级
NVIC_SetPriorityGrouping(NVIC_PRIGROUP_PRE2_SUB2);
}
3.2 设置中断优先级
使用 nvic_irq_enable() 设置中断的 先占优先级 和 子优先级。
nvic_irq_enable(USART1_IRQn, 0, 0); // 先占优先级 0,子优先级 0
nvic_irq_enable(TIM3_IRQn, 2, 2); // 先占优先级 2,子优先级 2
或者使用 NVIC_InitTypeDef 结构体:
NVIC_InitTypeDef NVIC_InitStructure;
// 配置 USART1
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 先占优先级 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 子优先级 0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
4. NVIC 使能、屏蔽和清除中断
4.1 使能中断
NVIC_EnableIRQ(USART1_IRQn); // 使能 USART1 中断
4.2 禁用中断
NVIC_DisableIRQ(USART1_IRQn); // 禁用 USART1 中断
4.3 清除中断挂起标志
NVIC_ClearPendingIRQ(USART1_IRQn); // 清除 USART1 挂起标志
5. NVIC 常见问题
5.1 为什么 NVIC_EnableIRQ(USART1); 会报错?
✅ 正确写法
NVIC_EnableIRQ(USART1_IRQn); // 需要传入 USART1_IRQn,而不是 USART1
❌ 错误写法
NVIC_EnableIRQ(USART1); // USART1 是外设地址,而不是中断号
5.2 为什么高优先级的中断没有抢占低优先级的中断?
可能的原因:
-
没有正确设置优先级分组,导致优先级没有正确比较。
-
没有开启全局中断 (
__enable_irq();) -
被屏蔽了(检查
NVIC_GetEnableIRQ()是否返回 0)。
5.3 如何手动触发中断?
NVIC_SetPendingIRQ(USART1_IRQn); // 触发 USART1 中断
6. 总结
-
NVIC 负责中断管理,包括使能、屏蔽、优先级分配等。
-
中断优先级包括“先占优先级”和“子优先级”,数值越小优先级越高。
-
使用
nvic_irq_enable()或NVIC_Init()进行中断配置。 -
NVIC API 操作时,参数必须使用
xxx_IRQn,不能直接写外设名。
掌握 NVIC,才能真正玩转 STM32/GD32!🚀
更多推荐



所有评论(0)