1.2 EXIT 中断
1.2 EXIT 中断
Sarzn中断的具象理解
在日常生活中, 中断其实十分常见, 一个很形象的例子是: 你在打电脑, 然后你的朋友突然来敲门(一个事件), 你放下电脑转身去开门, 这就是中断, 你朋友的到访打断了你正在做的事情, 这就是中断的具象理解.
其实在单片机的世界中也是这样的, 我们在执行主程序的时候, 如果有一个中断程序发生了, 那么它会打断我们主程序的执行, 让 MCU 先去处理这个中断任务, 处理完成之后再回过头来继续执行主程序
中断也有优先级
还是上面这个例子, 你在打电脑, 然后你的朋友来敲门, 但是同一时间, 你把蜜雪冰城不小心倒在了电脑上. 你顾不得朋友正在敲门了, 你必须马上把电脑擦干净. 也就是说奶茶抢占了你的给朋友开门, 因为他的优先级更高
在单片机中也是同样的, 你可以添加多个中断, 中断的发生按照他们的优先级进行排序, 优先级越高的中断它越先被执行, 因为它抢占了别人
嵌套 刚刚说的是同一时间发生的事, 如果低优先级的中断先发生了, 并且正在执行, 这时有另一个更高优先级的中断后发生了, 这个更高优先级的中断会打断低优先级的中断, 也就是说低优先级的中断会被挂起, 于是处理器会先执行更高优先级的中断
这就像是中断里面套中断, 这就是嵌套
看到这里, 你已经能够知道中断大概是个啥了, 你不再害怕它 在我们使用的这个蓝色小药丸(f103)中你便可以添加中断, 这个在实验篇中我们进行具体操作
但是在此之前, 我们要再详细的聊一聊中断
中断
“中断”是指处理器(CPU)暂停当前正在执行的程序,转去处理突发事件的机制
现在我们来谈谈发生一次完整的中断你的 MCU 中发生的过程 一张很好的图:

第0步: 需要先配置一个中断
中断不是凭空就有的, 我们需要先在 CubeMX 中配置一个 GPIO 口作为中断的触发
在 CubeMX 中, 选择一个没有被占用的引脚(这里以 PA1 举例), 将它设置为
GPIO_EXIT, 在此之后, 如果这个引脚上的电平发生了变化, 就会发起一个中断的信号, 表示事件的发生
EXTI = External Interrupt/Event Controller(外部中断控制器): STM32 里专门把 GPIO 引脚变化转成中断的那个外设 – 就是你在这里配的东西 ## 第 2 步: 事件发生, 发出 IRQ, 设置中断标志(flag)
- 在你的 GPIO 引脚发生变化之后, EXIT(外部中断控制器) 会发出一个中断信号, 这个中断信号就是 IRQ(中断请求)
IRQ = Interrupt Request(中断请求):
EXIT发出的”求助信号”。在 ARM Cortex-M
里每个中断信号有个编号,叫 IRQn(你之后会在
CubeMX/HAL 见到 EXTI0_IRQn、USART1_IRQn
就表示编号为EXIT0 这个中断信号, 编号为USART1 这个中断信号 )
所以 IRQ 是中断请求, IRQn
是中断请求的编号
- 再之后, 外设硬件会设置一个中断标志位(flag)
中断标志位 (Interrupt Flag): 事件发生时,外设硬件会把一个位置标志为 1,表示”我这有情况”。处理完这个中断后通常要手动清掉这个标志,否则会反复触发这个中断。但是在这里 HAL 会自动帮你清理这个标志, 所以你不用管
第 3 步: 途径 NVIC 中断控制器
NVIC = Nested Vectored Interrupt Controller(嵌套向量中断控制器): 别被他的名字给吓到了, 我们所有的中断信号都有一个统一的调度台进行管理和控制, 这个就是 NVIC
它是ARM Cortex-M 里管理所有中断的总调度台 它负责: 谁能打断谁 (优先级)、哪个中断开启/关闭、要不要嵌套
同样我们需要在 CubeMX 里配置 NVIC Settings
就是配NVIC
Nested(嵌套) 和 Vectored(向量化) 这两个词正是它的两大本事, 向量这个词我之后会提到
第 4 步: 查中断向量表, 找对应 ISR 的入口
- 刚刚说完中断信号(IRQ) 由 EXIT 产生, 途径 NVIC 的管理, 现在这个信号终于抵达处理器(CPU)了!
- 这个时候 CPU 必须知道它接收到信号之后要做什么事情, 也就是说, CPU 在接收到 IRQ 之后必须去处理对应编号的中断函数了, 中断函数也就是这个中断事件, 或者说中断服务程序(ISR)
ISR = Interrupt Service Routine(中断服务程序): CPU
收到请求后专门去执行的那段代码,也叫中断处理函数 /
handler 之后你会看见一个 EXTI1_IRQHandler , 这就是
ISR
- 那么 CPU 如何找到对应编号的中断函数呢? CPU 其实不会记得任何东西, 它靠查表来确定它到底要使用哪个 ISR(中断服务程序), 而这张表, 就叫做中断向量表
中断向量表 (Interrupt Vector Table):
一张存放在内存固定位置的表,每个中断号(IRQn)对应一个 ISR
的地址。CPU 收到中断后,靠查这张表瞬间跳到正确的处理函数 –
这就是 NVIC 名字里 “Vectored(向量化)”
的含义
第 5 步: 执行 ISR
- 执行 ISR(中断服务程序) 之前, CPU 还会做许多工作, 因为我们在执行完中断之后还需要主程序能继续执行, 所以 CPU会 “保存现场”
现场保护 / 上下文保存 (Context Saving): CPU 跳去执行 ISR 之前,先把当前寄存器状态存起来,处理完再恢复,这样原程序感觉不到被打断过。在 Cortex-M 中这个过程有一部分是硬件自动做的
- CPU 保存完现场之后, 进入到 ISR 中, 在执行真正的你写的中断程序之前, 他会将我们之前提到的那个标志位给清除, 这是为了防止中断被重复的执行
- 再之后, 你自己写的中断函数将会被调用, 中断的效果开始显现出来
第 6 步: 返回原程序
处理完这个中断之后, CPU 会恢复”现场”, 继续处理原程序, 这个原程序可以就是主程序, 也可以是一个被触发过的低优先级的中断, 这就是我们之前提到过的嵌套, 它会回到嵌套的上一层
整理
现在感觉脑子被干货喂满了?, 我们来这里整理一下遇到过的名词!
中断过程遇到的角色
- IRQ = Interrupt
Request(中断请求):外设发出的”求助信号”。在 ARM Cortex-M
里每个中断有个编号,叫
IRQn比如有EXTI0_IRQn、USART1_IRQn等等 - ISR = Interrupt Service Routine(中断服务程序):CPU
收到请求后专门去执行的那段代码,也叫中断处理函数 /
handler。你写的
EXTI1_IRQHandler就是 ISR - NVIC = Nested Vectored Interrupt Controller(嵌套向量中断控制器):ARM Cortex-M 里管理所有中断的总调度台。它负责:谁能打断谁(优先级)、哪个中断开启/关闭、要不要嵌套。你在 CubeMX 里的那个 “NVIC Settings” 就是配它。Nested(嵌套) 和 Vectored(向量化) 这两个词正是它的两大本事
- EXTI = External Interrupt/Event Controller(外部中断控制器):STM32 里专门把 GPIO 引脚变化转成中断的那个外设, 就是你在引脚里配的东西
一些名词
- 中断标志位 (Interrupt Flag):事件发生时,外设硬件会把一个位置标志为 1,表示”我这有情况”。一般来说进了 ISR 通常要手动清掉这个标志,否则会反复触发, 但是 HAL 自动帮我们清了 EXTI 的标志, 所以不必管
- Pending(挂起 / 中断挂起):标志已置位、但还没轮到它执行(比如优先级不够、或正被屏蔽),就处于挂起状态,排队等着
- 中断向量表 (Interrupt Vector Table):一张存放在内存固定位置的表,每个中断号对应一个 ISR 的地址。CPU 收到中断后,靠查这张表瞬间跳到正确的处理函数, 这就是 NVIC 名字里 “Vectored(向量化)” 的含义
- 现场保护 / 上下文保存 (Context Saving):CPU 跳去执行 ISR 之前,先把当前寄存器状态存起来,处理完再恢复,这样原程序感觉不到被打断过
- 中断延迟 (Interrupt Latency):从 IRQ 发出到 ISR 真正开始执行之间的时间。延迟越小,系统响应越实时
小小练习
回看前面的那个流程图, 试着在评论区里面用自己的话总结整个流程
如果你对如果同时有两个 GPIO 配成中断会发生什么?感兴趣你可以去看[[番外篇 - 如果同时有两个 GPIO 配成中断会发生什么?|番外篇 - 如果同时有两个 GPIO 配成中断会发生什么?]]






