NVIC_PriorityGroup_0是几个抢占优先级 + 响应优先级,如何实现16个中断呢?
想明确 NVIC_PriorityGroup_0 的优先级拆分规则,以及用它配置 16 个中断的具体组合方案,下面清晰拆解并给出可直接使用的配置示例。
- NVIC_PriorityGroup_0 的核心定义
NVIC_PriorityGroup_0 是 STM32 NVIC 优先级分组中最特殊的一种,对 4 位优先级寄存器的拆分规则为:
抢占优先级:0 位 → 仅 1 个级别(固定为 0,所有中断抢占优先级相同)
响应优先级:4 位 → 共 16 个级别(0~15,数值越小优先级越高)
总组合数:1 × 16 = 16 种 → 刚好能覆盖 16 个中断的优先级配置需求
核心特点:所有中断无抢占能力(因为抢占优先级都为 0),仅能通过响应优先级决定执行顺序,适合无需中断嵌套、低实时性的场景。 - 能否实现 16 个中断?
完全可以!该分组下的 16 种响应优先级(0~15)刚好能为 16 个中断分配唯一的优先级,满足 16 个中断的配置需求。 - 16 个中断的具体组合配置示例
假设你有 16 个典型中断(EXTI0EXTI7、USART1USART3、TIM1~TIM4、SPI1、SPI2),以下是完整的配置代码,按响应优先级从 0(最高)到 15(最低)分配:
c
运行
#include "stm32f10x.h"
void NVIC_Config_16IRQ_Group0(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 第一步:配置优先级分组为Group_0(0位抢占 + 4位响应)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// ==================== 所有中断抢占优先级固定为0 ====================
// 中断1:EXTI0(抢占0,响应0)→ 最高优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 必须为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 响应优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断2:EXTI1(抢占0,响应1)
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断3:EXTI2(抢占0,响应2)
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断4:EXTI3(抢占0,响应3)
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断5:EXTI4(抢占0,响应4)
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断6:EXTI5(抢占0,响应5)
NVIC_InitStructure.NVIC_IRQChannel = EXTI5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断7:EXTI6(抢占0,响应6)
NVIC_InitStructure.NVIC_IRQChannel = EXTI6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 6;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断8:EXTI7(抢占0,响应7)
NVIC_InitStructure.NVIC_IRQChannel = EXTI7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 7;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断9:USART1(抢占0,响应8)
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 8;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断10:USART2(抢占0,响应9)
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 9;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断11:USART3(抢占0,响应10)
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 10;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断12:TIM1(抢占0,响应11)
NVIC_InitStructure.NVIC_IRQChannel = TIM1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 11;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断13:TIM2(抢占0,响应12)
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 12;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断14:TIM3(抢占0,响应13)
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 13;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断15:SPI1(抢占0,响应14)
NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 14;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 中断16:SPI2(抢占0,响应15)→ 整体最低优先级
NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 15;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
- 关键注意点(Group_0 特有)
抢占优先级必须设 0:如果误将抢占优先级设为 1/2 等非 0 值,NVIC 会忽略该配置,仍按 0 处理,不会报错但优先级逻辑会混乱;
无中断嵌套能力:比如 EXTI0 中断正在执行时,即使 SPI2 中断触发,也必须等 EXTI0 执行完毕才能响应,无法打断;
响应优先级范围:仅能配置 0~15,超出该范围的数值会被 NVIC 自动截断(比如设 16 会被当作 0 处理)。
- 16 个中断的优先级排序
整体优先级从高到低严格对应响应优先级:
EXTI0(0) > EXTI1(1) > ... > EXTI7(7) > USART1(8) > ... > SPI2(15)
总结
NVIC_PriorityGroup_0 是 0 位抢占优先级 + 4 位响应优先级,仅 1 个抢占级别、16 个响应级别,总 16 种组合;
完全支持 16 个中断的配置,只需为每个中断分配唯一的响应优先级(0~15),抢占优先级固定设 0;
核心特点:无中断嵌套、仅按响应优先级排队执行,适合对实时性要求低、无需中断打断的场景。