STM32 中断分组与优先级解析
STM32 的中断优先级管理是嵌入式开发中核心知识点之一,其设计兼顾了灵活性和确定性,核心围绕抢占优先级 和响应优先级(也叫子优先级)展开
一、核心概念
1. 中断优先级的两个维度
STM32 将中断优先级分为两级,目的是解决中断嵌套 和同优先级中断排队的问题:
-
抢占优先级(Preemption Priority)
决定中断能否 "打断" 正在执行的中断(即中断嵌套)。
-
抢占优先级数值越小,优先级越高;
-
高抢占优先级的中断可以打断低抢占优先级的中断执行。
-
-
响应优先级(Sub Priority)
仅当多个中断抢占优先级相同时生效,决定中断的响应顺序(排队执行)。
-
响应优先级数值越小,排队越靠前;
-
同抢占优先级的中断,响应优先级高的先执行,但无法嵌套(因为抢占优先级相同)。
-
2. 中断分组(NVIC_PriorityGroup)
STM32 的中断优先级寄存器是 4 位宽(共 16 级优先级),通过 "中断分组" 将这 4 位拆分给 "抢占优先级" 和 "响应优先级",共分 5 个分组(Group0~Group4),具体拆分规则如下:
|---------|---------|---------|---------|---------|
| 中断分组 | 抢占优先级位数 | 响应优先级位数 | 抢占优先级范围 | 响应优先级范围 |
| Group 0 | 0 位 | 4 位 | 仅 0 级 | 0~15 |
| Group 1 | 1 位 | 3 位 | 0~1 | 0~7 |
| Group 2 | 2 位 | 2 位 | 0~3 | 0~3 |
| Group 3 | 3 位 | 1 位 | 0~7 | 0~1 |
| Group 4 | 4 位 | 0 位 | 0~15 | 仅 0 级 |
关键规则:
-
整个系统只能选择一个中断分组(全局配置),所有中断都遵循该分组规则;
-
4 位总位数固定,抢占优先级位数越多,响应优先级位数越少,反之亦然;
-
数值越小,优先级越高(无论是抢占还是响应)
二、优先级判断规则
当多个中断同时触发时,STM32 按以下顺序判断执行顺序:
-
先比较抢占优先级:数值小的先执行,且可嵌套;
-
若抢占优先级相同,比较响应优先级:数值小的先执行;
-
若响应优先级也相同,比较中断向量表中的硬件编号:编号越小,优先级越高(硬件固定,无法修改)。
三、代码实现(以 STM32F103 为例)
1. 配置中断分组(全局唯一)
#include "stm32f10x.h"
// 配置中断分组为 Group2(2 位抢占 + 2 位响应)
void NVIC_ConfigGroup(void)
{
// 初始化 NVIC 结构体
NVIC_InitTypeDef NVIC_InitStructure;
// 配置中断分组:Group2
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// 示例:配置外部中断 EXTI0 的优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // 选择 EXTI0 中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级:1(0~3)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 响应优先级:0(0~3)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能该中断通道
NVIC_Init(&NVIC_InitStructure);
// 示例:配置定时器 TIM2 的优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; // 选择 TIM2 中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级:1(与 EXTI0 相同)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 响应优先级:1(比 EXTI0 低)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
2. 优先级效果说明
以上配置中:
-
EXTI0 和 TIM2 的抢占优先级都是 1,因此无法互相嵌套;
-
若 EXTI0 和 TIM2 同时触发,EXTI0 的响应优先级 0 高于 TIM2 的 1,因此先执行 EXTI0 中断服务函数;
-
若将 TIM2 的抢占优先级改为 0,则 TIM2 可以打断 EXTI0 的执行(嵌套)。
四、实际开发注意事项
-
分组选择原则
-
若需要频繁使用中断嵌套,选择抢占优先级位数多的分组(如 Group3/4);
-
若很少嵌套,仅需排队执行,选择响应优先级位数多的分组(如 Group1/0);
-
常规场景推荐 Group2(2+2),兼顾嵌套和排队需求。
-
-
优先级数值误区
-
不要认为 "数值大优先级高",STM32 是数值越小优先级越高;
-
分组配置后,抢占 / 响应优先级的取值范围会固定(如 Group2 抢占只能取 0~3),超出范围会导致配置失效。
-
-
系统异常优先级
-
-
复位、NMI(不可屏蔽中断)、HardFault 等系统异常的优先级高于所有外部中断,且无法通过 NVIC 修改;
-
SVC、PendSV、SysTick 等内核中断的优先级可通过 SCB->SHPR 寄存器配置。
-
总结
-
STM32 中断优先级分为抢占优先级 (决定嵌套)和响应优先级(决定同抢占优先级的排队),由 4 位寄存器拆分而来;
-
中断分组(Group0~4)全局唯一,决定 4 位寄存器在抢占 / 响应优先级的分配比例;
-
优先级判断顺序:抢占优先级 > 响应优先级 > 硬件中断编号,数值越小优先级越高。
关键点回顾
-
抢占优先级:决定中断嵌套,高优先级(数值小)可打断低优先级;
-
响应优先级:仅同抢占优先级时生效,决定排队顺序;
-
中断分组:全局配置,4 位寄存器的拆分规则决定了抢占 / 响应优先级的取值范围。