Skip to content

NVIC (中断控制器)

它是 STM32 中断系统的灵魂。如果说 CPU 是皇帝,NVIC 就是拥有最高权力的总管太监

核心概念

  • 嵌套 (Nested) :NVIC 可以处理多个中断,每个中断可以嵌套在另一个中断中。
  • 向量 (Vectored) :每个中断都有一个唯一的向量地址,CPU 可以根据向量地址跳转到中断服务程序。
  • 中断 (Interrupt) :外部设备触发的事件,需要 CPU 立即响应。
  • 控制器 (Controller) :NVIC 负责管理中断,包括使能、失能、优先级设置等。

1. N - Nested (嵌套):能不能插队?

这是 NVIC 最强大的功能。

  • 场景: 皇帝 (CPU) 正在批阅奏折(执行主程序)。
  • 普通中断: 突然太监来报:“有人送水果来了(串口接收中断)”。皇帝停下笔,去吃水果。
  • 嵌套中断: 就在皇帝吃水果的时候,太监又冲进来了:“不好啦!失火啦(看门狗/系统故障中断)!
    • 如果不支持嵌套: 皇帝会说:“没看见我在吃水果吗?等我吃完!” -> 结果:宫殿烧没了。
    • NVIC 的做法: 皇帝立刻扔掉水果(保存当前中断现场),先去救火。救完火回来接着吃水果,吃完水果回去继续批奏折。

这就是嵌套: 高优先级的中断,可以打断正在执行的低优先级中断。


2. V - Vectored (向量):去哪办事?

为什么叫“向量”?这其实是一个数学/计算机术语,在这里你可以理解为**“精准的地址列表”**。

  • 非向量中断 (老式单片机):
    • 不管谁来了,CPU 都跳到同一个地方(比如 0x0004)。
    • CPU 到了那里还得自己查:“是谁叫我?是定时器吗?还是串口?” -> 效率低。
  • 向量中断 (NVIC):
    • NVIC 手里有一张巨大的表格(中断向量表)
    • 表格里写得清清楚楚:
      • EXTI0 来了 -> 请直接跳到 0x0000_0058 (找 EXTI0_IRQHandler)。
      • TIM2 来了 -> 请直接跳到 0x0000_00B0 (找 TIM2_IRQHandler)。
    • 结果: 速度极快,无需查询,直接瞬移到位。

3. I & C - Interrupt Controller (中断控制器)

这说明了它的身份。它不是外设(Peripheral),它是内核外设 (Core Peripheral)

  • 它长在 Cortex-M3 内核 里面,是 ARM 公司设计的,不是 ST 公司设计的。
  • 所以你在配置 NVIC 时,引用的头文件通常是 misc.h 或者 core_cm3.h,而不是 stm32f10x_gpio.h 这种。

4. 核心难点:优先级 (Priority)

这是面试和实际开发中必定会问的问题。NVIC 把优先级分成了两类:抢占优先级 (Preemption)响应优先级 (Sub)

我们需要用一个**“医院急诊室”**的模型来理解:

A. 抢占优先级 (Preemption Priority) —— “决定能不能插队”

  • 比喻: 这是一个病人病情的危急程度
  • 规则:
    • 值越小,优先级越高。(0级最高,15级最低)。
    • 高抢占的病人来了,医生必须立刻丢下正在看的低抢占病人,先救这个。这就是中断嵌套发生的唯一条件。

B. 响应优先级 (Sub Priority) —— “决定排队顺序”

  • 比喻: 这是挂号的早晚(但在 NVIC 里,这也是个数字)。
  • 规则:
    • 只有当抢占优先级相同,且两个病人同时到达时,这个参数才有用。
    • 高响应的病人排在前面,低响应的病人排在后面。
    • 关键点: 高响应优先级的人,不能插队!如果医生正在看一个“低响应”的病人,你也得等着。

C. 举个栗子

角色抢占优先级 (Preemption)响应优先级 (Sub)结果
病人 A10正在就诊中...
病人 B0(更高)3直接把 A 推开,插队先看 B
病人 C1(相同)0(相同)乖乖排队,等 A 看完
病人 D1(相同)0(但是比 C 晚来)排在 C 后面

5. 优先级分组 (Priority Grouping)

STM32 有一个很变态的设计:它只给了 4个 bit (二进制位) 的空间来存这两个优先级。

你需要配置 NVIC_PriorityGroupConfig 来决定这 4 个 bit 怎么分:

  • Group_0: 0 bit 给抢占,4 bit 给响应。(此时没有任何中断能插队,大家全是按顺序来)。
  • Group_2 (最常用): 2 bit 给抢占 (0~3),2 bit 给响应 (0~3)。
  • Group_4: 4 bit 给抢占,0 bit 给响应。(此时全是插队狂魔,谁等级高谁就直接打断别人)。

总结

NVIC 就是 CPU 的贴身大管家。

  1. 它手里拿着一张地图(向量表),指引 CPU 该去执行哪个函数。
  2. 它手里拿着一本VIP名单(优先级)
    • 抢占优先级高的人可以推门而入(中断嵌套)。
    • 响应优先级高的人可以优先排队

写代码时的建议:

整个工程中,最好只选择一种优先级分组方式(比如 NVIC_PriorityGroup_2),然后在 main 函数的最开头配置一次,之后就别改了,否则整个系统的中断逻辑会乱套。