1. 中断系统概述

大家好,我是老周。做嵌入式这些年,我敢说中断是咱们和硬件打交道时最核心的机制之一。你想想看,CPU 就一个,外设却一大堆——按键要按、串口要收数据、定时器要溢出……要是 CPU 一个个轮询,那效率低得没法看。中断,就是来解决这个问题的。

1.1 中断的概念

中断,说白了就是“CPU 正在干一件事,突然被另一件事打断,处理完再回来继续干”。

举个例子:你在看书,电话响了。你记下看到哪一页(保存现场),接电话(执行中断服务),挂掉电话后翻回刚才那页继续看(恢复现场)。这就是中断的完整流程。

在 STM32 里,中断源可以是 GPIO 引脚电平变化、定时器溢出、串口收到数据、DMA 传输完成等等。每个中断源都有一个对应的中断服务函数(ISR),CPU 响应中断后就会跳过去执行。

核心要点:中断是异步事件,CPU 不需要一直等着它。这大大提高了系统的实时性和效率。

1.2 中断的作用

我总结了一下,中断在嵌入式系统里主要干这几件事:

  • 实时响应:外部事件来了,CPU 能立刻处理。比如按键按下,立即响应,而不是等到主循环轮询到才处理。
  • 提高效率:CPU 不用一直轮询外设状态。串口收数据时,你只管干别的,数据来了中断会通知你。
  • 多任务协作:不同优先级的中断可以嵌套,高优先级的能打断低优先级的。这在复杂系统中特别有用。
  • 低功耗:CPU 可以进入休眠模式,中断来了再唤醒。我在做电池供电项目时,这个特性帮了大忙。

我的经验:有一次做工业控制,需要同时处理多个传感器信号。如果不用中断,主循环轮询根本来不及。后来改用中断 + DMA,CPU 负载从 80% 降到了 15%。

1.3 中断的优先级与嵌套

中断优先级,就是给中断排个队。谁更重要,谁先处理。

STM32 的 NVIC(嵌套向量中断控制器)支持最多 16 级抢占优先级和 16 级子优先级。你可以通过配置优先级分组来分配。

优先级分组 抢占优先级位数 子优先级位数 说明
NVIC_PriorityGroup_0 0 4 只有子优先级,无抢占
NVIC_PriorityGroup_1 1 3 2级抢占,8级子优先级
NVIC_PriorityGroup_2 2 2 4级抢占,4级子优先级
NVIC_PriorityGroup_3 3 1 8级抢占,2级子优先级
NVIC_PriorityGroup_4 4 0 16级抢占,无子优先级

抢占优先级高的中断可以打断抢占优先级低的。如果抢占优先级相同,就看子优先级,子优先级高的先执行,但不能互相打断。

注意:我曾经在一个项目中,把两个外设的中断优先级设成了相同的抢占优先级,结果一个中断没处理完另一个又来了,导致数据错乱。后来改成不同抢占优先级才解决。所以,关键中断一定要给高优先级。

1.4 STM32 中断系统架构

STM32 的中断系统,核心就是 NVIC 和中断向量表。

NVIC 负责管理所有中断的使能、挂起、优先级等。中断向量表则是一张地址表,每个中断源对应一个入口地址,CPU 响应中断后就去这个地址执行。

下面这张图是我画的 STM32 中断系统架构图,帮你理清整体脉络:

STM32 中断系统架构图 外设中断源 GPIO EXTI 定时器 TIM 串口 USART DMA / ADC / SPI ... NVIC 中断使能/挂起 优先级管理 嵌套控制 中断向量表映射 CPU Cortex-M 自动保存现场 跳转 ISR 执行中断服务 恢复现场返回 中断向量表 ISR 地址映射 优先级配置 外设产生中断请求 → NVIC 仲裁优先级 → CPU 响应并查向量表 → 执行 ISR 中断响应延迟通常为 12 个 CPU 周期(Cortex-M3/M4)

从图上你能看到,外设产生中断请求后,NVIC 会根据优先级决定是否响应。如果 CPU 当前执行的任务优先级更低,NVIC 就会通知 CPU 暂停当前任务,自动保存现场(压栈),然后从向量表中找到对应的 ISR 地址并跳转过去。

执行完 ISR 后,CPU 自动恢复现场(出栈),继续执行原来的任务。整个过程硬件自动完成,不需要我们手动写保存现场的代码——这也是 Cortex-M 系列的一大优势。

我的习惯:在配置中断时,我一般先把所有中断的优先级分组设好,再逐个使能。这样能避免中途改分组导致优先级混乱。另外,ISR 里尽量少做事,把耗时操作放到主循环或任务里,保证中断响应够快。

嗯,中断系统的基本概念就这些。你想想看,如果没有中断,CPU 得一直轮询外设,那得多累?中断让 CPU 能“按需响应”,这才是嵌入式系统的精髓。