当前位置: 首页 > news >正文

STM32单片机学习(16) —— 中断相关概念

文章目录

  • 概述
  • 中断是什么?
  • 中断优先级
    • 抢占优先级
    • 子优先级
    • 中断执行优先级举例
  • STM32的中断系统框图
    • NVIC的作用
    • NVIC不属于片上外设
  • NVIC中断优先级的配置
    • 中断优先级分组
    • 优先级都一样怎么办?

概述

**中断(Interrupt)**作为嵌入式系统一个非常重要的概念,已成为单片机(MCU)中最基础的外设模块/功能之一。

利用中断机制可以有效提高 CPU 效率,绝大多数嵌入式应用开发都会用到中断系统。

熟练编写中断程序是嵌入式开发人员必备的基本技能。

是我们学习STM32外设的第三大部分。

中断是什么?

为了讲清楚中断是什么,我们可以打一个通俗的比喻:

你正在图书馆看书学习,这时快递员通知你的快递到了,你暂停看书去拿快递,那么拿快递就是一个中断。中止你现在正在做的事情(看书)转而去做另一个事情。

如果在去取快递的路上,你突然肚子疼,只好先去趟卫生间,然后再去拿快递。

此时,肚子疼又是一个中断,而且是比拿快递更重要、更紧迫的事件,也就是说,中断中又有一个中断,这就是中断嵌套

只有更重要、更迫切的(高级别)中断才能中止当前级别低的中断,也就是说中断是有优先级的。

能够引发中断的事件(快递到了、肚子疼等)称为中断源

而对中断进行处理(拿快递、去卫生间等)称为中断服务程序(Interrupt Service Routine, 简称ISR)

这里有三个重要的概念:

  1. 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。
  2. **中断优先级:**当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应处理更加紧急的中断源。
  3. **中断嵌套:**当一个中断服务程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回。

下面的两张图就很好的解释了中断和中断嵌套:

在一个实际程序中,中断的处理是自动完成的,请看下图:

简单来说:

程序员只需要编写好中断服务程序,并完成中断触发条件等相关配置即可。

当主程序运行过程中触发中断条件时,嵌入式系统会自动完成以下操作:

  1. 自动保存主程序的当前执行状态
  2. 跳转去执行中断处理函数(中断服务程序,ISR)
  3. 执行完毕中断处理逻辑后,自动恢复之前保存的主程序状态,并继续从中断前的指令处执行。
  4. 这个过程就是常说的“上下文切换”,或者“中断上下文切换”。

以上这些过程,都由嵌入式系统自动完成,程序员不需要手动处理这些细节。

那么程序员在使用中断这种机制时,需要动手做的事情有哪些呢?

  1. 设置好中断源,配置好中断相关的参数数据,还需要手动开启这个中断源。
  2. 编写好相应的中断服务程序,也就是编写对应的中断处理函数。

从这个角度看,中断是一种高效且易用的语法机制。

中断优先级

在上面我们已经理解了中断的概念含义,现在我们进一步来了解一下中断优先级的概念。

在一个STM32嵌入式系统中,几乎所有的外设都可以产生中断源。

如果这些中断同时发生(例如多个外设同时产生中断请求),那么必须决定哪一个中断先被处理。

为此,STM32 提供了中断优先级机制,允许程序员为每个中断源设置不同的优先级。

STM32 的中断优先级被分为两组,这两组优先级分别是:

  1. 抢占优先级(Preemption Priority)
  2. 子优先级(Subpriority,有些地方也叫响应优先级)

下面来讲解一下这两个优先级的相关概念。

优先级具体在表示时,都会使用非负整数表示,最小值是0,数值越小表示优先级越高,0就是最高的优先级。

抢占优先级

抢占优先级是最关键且核心的优先级:

  1. 若主程序正常运行时,同时产生了多个中断,那么抢占优先级更高的中断先执行。
  2. 若主程序已经在执行中断A了,中断A执行过程中产生了中断B,且中断B的抢占优先级更高,则会产生中断嵌套,优先执行中断B。

总之抢占优先级的核心点在于"抢占"二字,具有更高抢占优先级的中断可以打断正在执行中的低优先级中断。

子优先级

只有当抢占优先级相同时,才需要考虑中断的子优先级:

  1. 若主程序正常运行时,同时产生了多个抢占优先级相同的中断,那么子优先级更高的中断先执行。
  2. 若A和B是相同抢占优先级的两个中断:
    1. 系统当前正在执行中断A,此时产生了中断B
    2. 无论中断B的子优先级更高还是更低,中断B都不能打断中断A的执行,无法产生中断嵌套。

也就是说,子优先级和中断嵌套没有关系,只要当前已有中断在执行,那么相同抢占优先级的中断就无法打断。

总之结论如下:

  1. 抢占优先级 决定了多个中断同时触发时,哪个中断优先执行,抢占优先级越高,越先执行。
  2. 抢占优先级 还决定了哪个中断可以打断另一个中断,抢占优先级高的中断可以打断,当前正在执行的,抢占优先级更低的中断。
  3. 子优先级 只用来区分同一抢占优先级的中断触发时,执行的先后顺序,子优先级越高,越先执行。子优先级和中断嵌套没有关系!

中断执行优先级举例

假如现在有5个中断:

  1. A中断,抢占优先级3,子优先级3
  2. B中断,抢占优先级2,子优先级4
  3. C中断,抢占优先级2,子优先级2
  4. D中断,抢占优先级2,子优先级3

假如主程序在正常执行的某点,突然触发了A中断,此时由于只有一个中断源,不用考虑优先级,直接执行A中断的处理函数,如下图所示:

假如在执行A中断处理函数的过程中,突然触发了B中断,会发生什么事情呢?

由于B中断的抢占优先级更高(2 < 3),所以B会打断A中断函数的执行,嵌套执行B中断,即产生了中断嵌套。如下图所示:

再假如在执行B中断处理函数的过程中,突然同时触发了CD两个中断,会发生什么事情呢?

BCD四者的抢占优先级是一致的,哪怕CD的子优先级更高,但子优先级和中断嵌套没有关系,所以CD都必须等待B中断执行完毕后才可能执行。

在B中断执行完毕后,会返回A中断被嵌套中断的断点位置,CD的抢占优先级高于A,所以CD会继续打断A的执行。

而C和D之间,则会根据子优先级来排列它们的执行顺序,C的子优先级更高,所以C先于C执行完毕,都先于A执行完毕。

整个中断执行的流程图,如下图所示:

在大多数嵌入式应用中,程序的复杂度往往比较低,中断触发的情况通常是由单一事件引起的,中断嵌套的情况是比较少见的,更不用说上述这么复杂的情况。

但是在一些实时系统中,还是会存在一些比较复杂的中断系统,所以对于中断优先级的相关概念,大家还是要了解清楚的。

搞清楚了STM32中断优先级的概念,那么如何设置中断的优先级呢?

为了搞清楚这个事情,我们先来看一下STM32的中断系统框图。

STM32的中断系统框图

STM32 当中有很多片上外设都可以产生中断源,例如 USART、EXTI、TIM、SPI、I2C 等。

这些外设在满足中断条件时:

都会向 CPU 提出中断请求,都希望抢占 CPU 的执行权,转而执行各自对应的中断服务程序(ISR)。

这么多中断如果同时存在,而没有一个统一管理的“机构”,那中断系统就乱套了。

在整个中断系统中,处于核心控制地位,负责中断调度、优先级管理和中断嵌套的组件,就是 NVIC。

NVIC的作用

NVIC (Nested Vectored Interrupt Controller) ,直译为嵌套矢量中断控制器。

当然一般没什么人直接叫它的中文译名,直接叫NVIC即可。

NVIC 是单片机中非常重要的、核心的组成部分,几乎所有中断相关的事项都需要NVIC参与处理。

其主要作用有以下几项:

  1. 中断的开启和关闭。
    1. 外设可以提交中断请求给NVIC,但只有被NVIC开启的中断才能够抢占CPU执行。
    2. NVIC如果关闭了某个中断,那么此中断就完全无效。
  2. 中断的优先级设置,NVIC 负责为各个中断源请求配置和管理优先级。
  3. 中断调度与执行控制。
    1. NVIC 会根据已配置的优先级规则,对所有中断请求进行仲裁,决定哪个中断优先进入 CPU 执行
    2. 中断的挂起等待、中断嵌套等一系列中断行为都由NVIC决定。

总之,用通俗的话来说:

外设只负责产生中断请求,而NVIC来决定“中断是否生效、中断什么时候执行以及什么顺序执行”。

NVIC不属于片上外设

NVIC在使用时可以把它视为一个特殊的片上外设,尤其是在编程的时候。毕竟:

它同样具有寄存器,也需要配置寄存器,SPL库中也有对应函数可以调用。

但严格来说,NVIC并不是片上外设,它和GPIO、USART等外设有着本质上的区别:

  1. NVIC属于Cortex-M 内核的一部分。
  2. NVIC也并没有挂载在AHB或者APB总线上,它集成在CPU内部,是CPU的一部分,和CPU“住在一起”。

这样NVIC在使用时,就和一般片上外设具有差异性。最重要的有两条:

  1. 只要CPU运行,NVIC就处于工作状态。所以NVIC在使用时,不需要像传统外设那样开启时钟!
  2. 片上外设可能由于芯片型号不同,在数量或功能细节上存在差异。但NVIC属于内核组件,只要核心相同的芯片,NVIC在使用上都是一致的。

当然,在日常交流口头上,说“NVIC外设”通常也没有大问题,大家都能够理解。

NVIC中断优先级的配置

其它外设产生中断请求,然后交给NVIC外设统一配置,其中就包括配置此中断请求的优先级。

那么NVIC是如何实现中断优先级的配置呢?

NVIC的中断优先级由优先级寄存器的4位(上图中间的四个格子)决定,这4位可以进行切分:

  1. 高n位决定抢占优先级的取值。
  2. 低m位决定子优先级的取值,其中m = 4 - n

下面详细讲一下STM32中断优先级分组。

中断优先级分组

很明显,根据n的取值不同,一共可以分为5种情况,也就是5个分组。如下图所示:

分组0,注意从0开始,不是从1开始:

  1. n = 0,没有抢占优先级,或者可以认为所有中断的抢占优先级都一样,固定是0。
  2. m = 4,优先级寄存器的 4 位都用于子优先级,子优先级的取值范围是 0 ~ 15

采用分组0时,由于没有抢占优先级,中断系统完全依赖子优先级来管理。

此时中断系统中没有嵌套行为,单纯依赖子优先级排队执行。

分组1:

  1. n = 1,优先级寄存器的 1 位用于抢占优先级,抢占优先级的取值范围是 0 ~ 1
  2. m = 3,优先级寄存器的 3 位用于子优先级,子优先级的取值范围是 0 ~ 7

分组2:

  1. n = 2,优先级寄存器的 2 位用于抢占优先级,抢占优先级的取值范围是 0 ~ 3
  2. m = 2,优先级寄存器的 2 位用于子优先级,子优先级的取值范围是 0 ~ 3

分组3:

  1. n = 3,优先级寄存器的 3 位用于抢占优先级,抢占优先级的取值范围是 0 ~ 7
  2. m = 1,优先级寄存器的 1 位用于子优先级,子优先级的取值范围是 0 ~ 1

分组4:

  1. n = 4,优先级寄存器的 4 位都用于抢占优先级,抢占优先级的取值范围是 0 ~ 15
  2. m = 0,没有子优先级,或者可以认为所有中断的子优先级都一样,固定是0。

采用分组4时,中断系统没有子优先级,完全依赖抢占优先级来管理中断的执行顺序,存在中断嵌套。

注意以下几点:

  1. 在设置具体中断优先级数值之前,应该先设置优先级分组。因为分组决定了优先级数值的具体取值范围!
  2. 如果不小心忘记明确设置优先级分组,那么单片机本身会采用默认分组0。
    1. 这个默认的分组0,来自于NVIC上电启动后寄存器的复位值,是一种默认行为。
    2. 默认分组0就意味着系统内不存在抢占优先级,全部依赖子优先级决定中断的执行。
    3. 在该分组下,中断之间不会发生嵌套抢占。
    4. 这显然是一种保守的、安全的中断优先级分组配置。
  3. 最好不要依赖优先级分组的默认行为。
    1. 试想一下,如果忘记设置优先级分组,直接配置抢占优先级字段。
    2. 看似设置成功,实则没有任何作用,中断不会出现任何抢占行为。
    3. 因为分组0没有抢占优先级。
    4. 为了避免这种情况出现,请大家一定不要忘记手动设置优先级分组!一定要显式设置分组后再设置优先级数值!
  4. 多次设置中断优先级分组通常也是无意义的,而且具有风险。所以设置分组的操作最好就放在main函数死循环的上面,只执行一次即可。
  5. 由于我们采用标准库开发方式,底层寄存器操作被封装了,所以分组和优先级数值的设置,实际都只需要调用函数就足够了。

优先级都一样怎么办?

如果你真正搞懂了上述优先级相关内容,且善于发散思考,你可能会提出这样的问题:

抢占优先级不同优先看抢占优先级,抢占优先级相同就看子优先级。

那么如果两个中断抢占优先级和子优先级都一样,怎么办呢?

谁先谁后执行?

STM32的设计者早已想到了这个问题了:

在多个中断优先级完全一致时,单片机会优先执行中断向量表中向上靠前的中断,也就是优先执行表格中编号小的中断。

那么什么是中断向量表呢?

  1. 简单来说,中断向量表是一张"函数地址表",每一个中断类型的中断服务程序(ISR)都具有唯一对应的函数入口地址(函数指针)。
  2. CPU在执行某一中断类型的中断服务程序时,就需要查表来确定函数的入口地址,从而执行该中断服务程序。

在《参考手册》的中断和事件章节,章节开头就给出了中断向量表。

一部分截图如下:

很明显如果两种优先级都一样,系统级中断具有优先执行权。

还有一个叫Reset的中断,也就是复位操作,它的优先级是固定最高的,不管单片机在做什么,触发复位时都会优先执行。

其余外设中断的执行顺序,则可以查表得到,这里就不赘述了。

http://www.jsqmd.com/news/869283/

相关文章:

  • 互联网英文缩写( “黑话”)
  • 2026黄石市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • 2026桂林市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • 备战618:如何利用邮件营销低成本精准获客?
  • 2026三门峡市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • VMware安装Linux系统笔记
  • 哪个跨境ERP不限采集数量?铺货卖家实测干货分享
  • 第一性原理缺陷计算准备:以氢掺杂氧化镓为例的VASP实践指南
  • 2026惠州市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • 商品详情实现与缓存问题(穿透、击穿、雪崩)解决方案
  • 如何让抓取手机日志---ADB 从入门到实战:小米14日志抓包与连接详解
  • 2026海口市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • 2026德阳市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • Gemini3.1Pro攻克长文本quot;迷失中间quot;难题
  • 从0到1万美元MRR:一个独立开发者的两年复盘
  • 3分钟部署OpenClaw最新版v2026.4.26指南,可视化小白可用操作简单
  • 【系统架构师-综合题(14)】数学与经济管理知识点
  • AI智能体安全防御:从代码数据分离到多代理系统架构实践
  • 企业内如何通过 Taotoken 实现 API 密钥的集中管理与访问审计
  • 2026邯郸市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • 简历上写“精通Vivado“,面试官问起时序约束就卡壳
  • 2026包头市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • 全球首创 XR+AGV 融合技术,超元力 XR 黑暗乘骑无轨AGV开启星际探险新纪元
  • NotebookLM关键词提取结果不一致?权威测试报告揭示模型版本、文档编码、上下文窗口三重耦合陷阱
  • Gemini3.1Pro如何使用代码教程
  • 2026临沂市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • 2026汉中市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989
  • 代码都是AI写的,你问我要操作手册??别慌!这个skill:ManualGen 可以帮助你生成专业的用户操作手册
  • 内连接,左连接,右连接怎么区别开来?
  • 2026宝鸡市最新黄金 白银 铂金 彩金回收收门店实力排行榜及联系方式推荐 - 大熊猫898989