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 中断系统架构图,帮你理清整体脉络:
从图上你能看到,外设产生中断请求后,NVIC 会根据优先级决定是否响应。如果 CPU 当前执行的任务优先级更低,NVIC 就会通知 CPU 暂停当前任务,自动保存现场(压栈),然后从向量表中找到对应的 ISR 地址并跳转过去。
执行完 ISR 后,CPU 自动恢复现场(出栈),继续执行原来的任务。整个过程硬件自动完成,不需要我们手动写保存现场的代码——这也是 Cortex-M 系列的一大优势。
我的习惯:在配置中断时,我一般先把所有中断的优先级分组设好,再逐个使能。这样能避免中途改分组导致优先级混乱。另外,ISR 里尽量少做事,把耗时操作放到主循环或任务里,保证中断响应够快。
嗯,中断系统的基本概念就这些。你想想看,如果没有中断,CPU 得一直轮询外设,那得多累?中断让 CPU 能“按需响应”,这才是嵌入式系统的精髓。