STM32 异步事件处理:中断、NVIC 与 EXTI 深度全书
引言:为什么我们需要中断?
在进入技术细节前,让我们先思考一个生活场景:
如果你正在厨房煮粥,需要 20 分钟才能熟。为了不让粥糊掉,你会一直站在锅边盯着看(轮询),还是回客厅看书,等锅里的定时器响了(中断)再去关火?
我当然会去客厅看书,否则那 20 分钟我什么也干不了。
没错。那么对于主频几十兆赫兹的 CPU 来说,如果它每一秒钟都要花 90% 的时间去检测一个按键是否按下,这难道不是一种巨大的计算资源浪费吗?
这就是**中断(Interrupt)**存在的意义:让 CPU 从无意义的等待中解脱出来,实现“平行的效率”。
第一部分:核心灵魂——中断系统基础理论
1.1 中断的本质:上下文切换
当中断发生时,CPU 必须立即停止当前的流水线。但这里有一个关键问题:
如果你书读到一半去关火,回来时如何精准地找到刚才读到的那一页、那一行?
我会用书签标记一下。
在 STM32 中,这个“书签”就是现场保护。CPU 会自动将当前的程序计数器(PC)、状态寄存器等压入堆栈。处理完中断后,再通过“现场恢复”回到断点。
图 1:中断触发、嵌套与返回的逻辑路径。注意:断点是程序恢复运行的唯一凭证。
1.2 中断向量表:指令的“导航图”
CPU 怎么知道中断发生后该去哪里执行代码?在内存的固定位置,有一张表格记录了所有中断服务程序(ISR)的入口地址,这就是中断向量表。
第二部分:中央司令部——NVIC 嵌套向量中断控制器
如果说外设(按键、定时器、串口)是士兵,那么NVIC就是负责调度的将军。
2.1 为什么必须经过 NVIC?
如果厨房的锅响了,同时门口有人按门铃,你该先处理哪一个?如果这时候你的电话也响了呢?
我需要根据事情的紧急程度排个序。
这就是 NVIC 的核心职能:优先级裁决。
图 2:NVIC 架构。它位于内核内部,是所有外设中断通往 CPU 的必经之路。
2.2 优先级的双重奏:抢占与响应
STM32 将优先级分成了两个维度,这是初学者最容易混淆的地方:
抢占优先级(Preemption Priority):
核心能力:“打断权”。
如果 A 的抢占优先级高于 B,A 可以直接掐断正在运行的 B,这就是中断嵌套。
响应优先级(Subpriority):
核心能力:“排队权”。
如果 A 和 B 的抢占优先级相同,且同时发生,谁的响应优先级高,谁先执行。但它不能打断正在运行的同级抢占中断。
想象你在排队。抢占优先级高的人可以直接冲到柜台前把正在办事的人推开;而响应优先级高的人只能在大家都排队时,站在更靠前的位置。你能理解这两者的区别吗?
第三部分:核心重难点——EXTI 外部中断
EXTI(External Interrupt)是初学者最先接触的硬件中断,它负责将 GPIO 的电平变化转变为中断信号。
3.1 硬件架构与映射逻辑
STM32 有上百个引脚,但 NVIC 的通道是有限的。为了解决这个矛盾,工程师设计了引脚映射。
图 3:EXTI 结构图。展示了从 GPIO 到 AFIO 选择器,再到 EXTI 通道,最后进入 NVIC 的全过程。
关键点解构:
16 条线:EXTI0 到 EXTI15 对应引脚的编号。
映射机制:PA0, PB0, PC0... 全部连接在 EXTI0 上。
苏格拉底式提问:“如果 PA0 和 PB0 同时想当外部中断源,可以吗?”
答案:不可以。通过 AFIO 选通器,每一条 EXTI 线在同一时刻只能选择一个端口的引脚。
3.2 触发方式的科学选择
上升沿(Rising):低电平变高。适合检测“开启”动作。
下降沿(Falling):高电平变低。常用于按键(按下通常为低)。
双边沿(Both):只要变了就触发。适合检测信号的翻转。
第四部分:次重点——定时器中断(TIM)
如果说 EXTI 是“被动响应”,那么定时器中断就是“主动出击”。
4.1 更新中断(Update Interrupt)
这是最常用的定时器功能。基于时钟源的计数器溢出时,产生中断。
如果你需要每秒钟精确地测量一次温度,是用 EXTI 还是 TIM?
TIM。因为 EXTI 取决于外部信号,而 TIM 取决于内部稳定的晶振。
4.2 核心参数计算
初学者必须掌握的公式(以72MHz主频为例):
Prescaler(预分频):把频率降下来。
Period(计数值):数多少个数触发一次。
第五部分:其他常用中断巡礼
串口中断(UART/USART):
RXNE(接收非空):对方发来消息了,快去读。IDLE(空闲中断):一帧数据发完了,适合配合 DMA 使用。
ADC 中断:
EOC(转换结束):模拟量转数字量完成了,可以取值了。
SysTick(系统滴答):
内核自带的定时器,专门用于给操作系统(如 FreeRTOS)提供时基,或实现精准的
Delay。
第六部分:实战进阶——如何写出高质量的中断代码?
6.1 标志位的“生死时速”
在中断服务程序(ISR)中,你必须做的第一件事或最后一件事通常是:清除中断标志位(Pending Bit)。
如果闹钟响了,你不去按下“停止”键,它会发生什么?
它会一直响,或者等一会儿又响。
硬件也是如此。如果你不清除标志位,CPU 刚退出中断就会发现标志位还在,于是立刻又跳回中断,导致主程序永远无法执行。
所以:遇到中断卡死?先检查标志位清了没!
6.2 ISR 编写的三大禁令
禁耗时操作:不要放
printf或大循环。禁长延时:绝对不要在中断里用
Delay()。禁复杂运算:尽量只做状态转换或标志位修改。
结语:思维导图式总结
中断管理:交给NVIC(分清抢占与响应优先级)。
外部信号:交给EXTI(记住 16 条线的映射互斥原则)。
时间任务:交给TIM(计算好频率与周期)。
执行原则:保护现场 -> 处理逻辑 ->清除标志-> 恢复现场。
现在你已经理解了中断。如果一个系统中所有任务都放在中断里执行,而主程序只有一个
while(1)空循环,这和轮询又有什么本质区别呢?
笔记说明:
本文素材来源于b站up江协科技
希望这份笔记能帮你攻克 STM32 开发中最关键的一环。
