引言:为什么我们需要中断?

在进入技术细节前,让我们先思考一个生活场景:

 如果你正在厨房煮粥,需要 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 将优先级分成了两个维度,这是初学者最容易混淆的地方:

  1. 抢占优先级(Preemption Priority):

    • 核心能力: “打断权”。

    • 如果 A 的抢占优先级高于 B,A 可以直接掐断正在运行的 B,这就是中断嵌套

  2. 响应优先级(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(计数值): 数多少个数触发一次。


第五部分:其他常用中断巡礼

  1. 串口中断(UART/USART):

    • RXNE(接收非空):对方发来消息了,快去读。

    • IDLE(空闲中断):一帧数据发完了,适合配合 DMA 使用。

  2. ADC 中断:

    • EOC(转换结束):模拟量转数字量完成了,可以取值了。

  3. SysTick(系统滴答):

    • 内核自带的定时器,专门用于给操作系统(如 FreeRTOS)提供时基,或实现精准的 Delay


第六部分:实战进阶——如何写出高质量的中断代码?

6.1 标志位的“生死时速”

在中断服务程序(ISR)中,你必须做的第一件事或最后一件事通常是:清除中断标志位(Pending Bit)

如果闹钟响了,你不去按下“停止”键,它会发生什么?

它会一直响,或者等一会儿又响。

硬件也是如此。如果你不清除标志位,CPU 刚退出中断就会发现标志位还在,于是立刻又跳回中断,导致主程序永远无法执行。

所以:遇到中断卡死?先检查标志位清了没!

6.2 ISR 编写的三大禁令

  1. 禁耗时操作: 不要放 printf 或大循环。

  2. 禁长延时: 绝对不要在中断里用 Delay()

  3. 禁复杂运算: 尽量只做状态转换或标志位修改。


结语:思维导图式总结

  • 中断管理: 交给 NVIC(分清抢占与响应优先级)。

  • 外部信号: 交给 EXTI(记住 16 条线的映射互斥原则)。

  • 时间任务: 交给 TIM(计算好频率与周期)。

  • 执行原则: 保护现场 -> 处理逻辑 -> 清除标志 -> 恢复现场。

现在你已经理解了中断。如果一个系统中所有任务都放在中断里执行,而主程序只有一个 while(1) 空循环,这和轮询又有什么本质区别呢?

笔记说明:

本文素材来源于b站up江协科技

希望这份笔记能帮你攻克 STM32 开发中最关键的一环。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐