STM32 的中断优先级机制,是很多初学者和项目新人经常绕晕的一个概念。什么是抢占?什么是响应优先级?优先级分组又到底是干嘛的?为什么你设置了优先级却根本没生效?
别慌,这篇文章用 10分钟 帮你从概念 -> 配置 -> 实战,一步步搞清楚 STM32 中断优先级到底怎么玩。
1. STM32 中断优先级机制全貌
STM32 的中断控制由 NVIC(Nested Vectored Interrupt Controller) 控制,它支持中断嵌套,也就是“中断中断”。
NVIC 的中断优先级包括两个核心概念:
-
抢占优先级(Preemption Priority):谁能打断谁。
-
响应优先级 / 子优先级(Sub Priority):在抢占等级相同的情况下,谁先被响应。
类比理解:
抢占优先级 = 职位高低
响应优先级 = 谁先排队等的久
如果两个中断的抢占等级不同,抢占等级高的可以中断低的中断。
如果抢占等级一样,就比较响应优先级。
2. 优先级分组是怎么回事?
STM32 使用 CMSIS 标准,将中断优先级表示为一个 4bit 的值(0~15),但这个 4bit 如何划分抢占和响应,是由你配置的:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
STM32 的库函数允许你在 5 个“优先级分组”之间选择:
分组模式 | 抢占优先级位数 | 响应优先级位数 |
---|---|---|
Group 0 | 0 | 4 |
Group 1 | 1 | 3 |
Group 2 | 2 | 2 |
Group 3 | 3 | 1 |
Group 4 | 4 | 0 |
例如:你设为 Group 2,则 2 位抢占优先级 + 2 位响应优先级。
注意:STM32 的默认分组不一定是你期望的!一定要显式调用 NVIC_PriorityGroupConfig()
来设置,否则你设的优先级可能完全没起作用。
3. 优先级配置函数怎么用?
NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
重点提示: 你设的优先级(0~15)实际上被映射成一个硬件中的优先级值,和 NVIC_PriorityGroupConfig()
直接相关,不设置分组会导致优先级行为完全失效。
4. 实战示例:两个中断,谁先响应?
我们设置两个中断:
-
EXTI0_IRQn
:外部按键中断 -
USART1_IRQn
:串口中断
设定如下:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_IRQChannelPreemptionPriority = 0; NVIC_IRQChannelSubPriority = 1; // 对 USART NVIC_IRQChannelPreemptionPriority = 1; NVIC_IRQChannelSubPriority = 0; // 对 EXTI
结果:即使 EXTI 先触发,也会被 USART 中断“插队”。
因为 USART 抢占优先级更高(0 < 1),所以可以打断正在执行的 EXTI。
结论:只要抢占优先级不同,不管谁先触发,中断一定被打断!
5. 初学者最容易犯的三大误区
误区1:只设置了优先级,没设置分组
STM32 的中断优先级配置是双重的:优先级值 + 分组配置 缺一不可。
误区2:以为抢占优先级和响应优先级加起来不能超过4
不是“加起来”,而是由 NVIC_PriorityGroup 分开定义的位数!
误区3:不知道某些中断(SysTick、PendSV)有固定优先级
系统中断(比如 SysTick
)的优先级用特殊寄存器设置,不能随便 NVIC_Init 配置!
6. 写给调试者的实用建议
-
调试中断优先级时,强烈建议使用逻辑分析仪或串口打印标记时间点。
-
建议固定使用
NVIC_PriorityGroup_2
,抢占优先级足够用,响应优先级也能灵活分配。 -
若需要确保某中断绝对优先,设为 Preemption = 0,并尽量避免复杂处理逻辑,防止中断阻塞。
总结
STM32 中断优先级看起来复杂,其实只要记住这三点就能掌握:
-
抢占优先级 = 谁能打断谁
-
响应优先级 = 抢占等级相同谁先响应
-
优先级分组决定了优先级的“位宽分配”