第十课时:中断优先级揭秘:抢占与嵌套的底层逻辑:

第十课时:中断的基本概念

本课主题:中断的基本概念,理论加实践。


一、中断的理论概念

先用一个生活里的比喻来理解中断。

左边是读书的时候来了电话:放下书去接电话,接完再回来接着读。右边换到单片机:常规程序执行中来了突发事件,也就是中断源,CPU 停下来去执行处理突发事件的代码,处理完再回到常规程序。

这大概就是小循环和大循环的区别。

左边是闪灯程序,while(1) 里点亮、延时、熄灭、延时。右边是串口接收程序,while(1) 里调用 HAL_UART_Receive,Size 填 1,表示每次接收一个字节,Timeout 填 0,表示无需等待,有数据就接收,没数据直接返回失败。

这样能不能实现不同的逻辑循环呢?把两段合起来看就知道了。

直接把串口接收塞进闪灯循环里,是不行的。因为 HAL_Delay 会把 CPU 占住,这段时间里根本轮不到串口。

串口在读取数据的时候会有两个缓冲区,一级缓冲和二级缓冲。每接收一个字节都要及时读走,如果拖到最后再读,缓冲区满了就会丢数据。

算一下时间就明白了。波特率 115200,一位约 10µs,一个字节连起始位、8 个数据位、停止位一共 10 位,传一个字节只要 0.1ms。而闪灯一个延时就是 200ms,这期间串口早就收满溢出了。

实际的情况是,传输数据时有两层缓冲区,每接收一个字节就要读一个字节,读不出来,缓冲区满了就丢数据。而串口什么时候收到数据是不知道的:如果在闪灯的过程中来了串口数据,阻塞式的程序会让 CPU 停在那一步,第一层缓冲区就会溢出,数据就丢了。

图上把闪灯和读取数据的时间轴画了出来,串口收到数据的那一刻,CPU 还在延时里,等它回来数据已经没了。

解决办法是,每次接收到数据时都调用中断响应函数来处理数据,这样就能避免数据丢失。单片机里几乎每一个串口都能用中断。图上就是闪灯程序照常跑,串口一来数据就插进来执行中断响应函数,里面读数据、处理数据,处理完再回去闪灯。

多个中断同时来的时候,它们会按优先级去竞争中断响应函数,下面就讲这个。


二、中断的实践过程

中断的本质,是让单片机停下来,去做一件更重要的事情。

图里画了两种情况:中断 1 正在执行时来了中断 2,左边是等中断 1 执行完再执行中断 2,右边是中断 2 直接打断中断 1。能不能打断,取决于优先级。

中断的优先级用中断优先级来表示。优先级只有 4 个 bit,bit3 到 bit0,从 0000b 到 1111b,也就是 0 到 15,一共 16 个中断优先级。

这 4 位还要再分:高两位 bit3、bit2 是抢占优先级,决定中断嵌套和中断排队;低两位 bit1、bit0 是子优先级,只决定中断排队。

分组的档位就是这样来的:抢占优先级占 0 个位是 1 级,占 1 位是 2 级,占 2 位是 4 级,占 3 位是 8 级,占 4 位是 16 级;剩下的位给子优先级,数量反过来。这就是为什么优先级级数和二进制的位数有关。

中断排队的原则是,优先级越高排队越靠前;优先级相同时,遵循先来后到的原则。

课上还用游戏打了比方:防守基地、集合打团、线上补兵,事情有轻重缓急,要先处理更重要的。

2.1 我的疑问:中断优先级到底怎么排

我的问题是:正点原子讲,抢占优先级越小越先执行、能打断其他中断,抢占优先级相同看子优先级,子优先级越小越先执行、没有打断能力,子优先级也相同就看中断向量表里的中断函数顺序,越靠前越先执行,这个说法对不对?优先级相同时遵循先来后到,对不对?优先级相同时 IRQ 编号较小的中断优先执行,对不对?

统合起来的规则是:先比抢占,再比子优先级,全都相同就不互相打断,同时排队时看编号。

  1. 抢占优先级,数值越小优先级越高。高的可以打断正在跑的低优先级中断,这一层决定能不能插队。
  2. 子优先级,只在抢占优先级相同时起作用。两个中断同时挂着时,子优先级小的先跑,但它不能打断已经跑起来的中断,不能插队,只决定排队顺序。所以正点原子那段里,抢占能打断、子优先级不能打断,这两点都对。
  3. 两个都相同时,先说先来后到,严格说它不正确。如果 A、B 优先级完全一样,A 已经在跑,B 才来,同优先级不能打断 A,所以 A 先跑完、B 再跑;但如果两个都在排队,比如都被一个更高优先级的中断挡住,等回来时不是谁先来谁先跑。再说 IRQ 编号,异常编号小的先执行,这是 Cortex-M 的硬件规定,而中断向量表正是按编号从小到大排的,所以向量表里越靠前越先执行也对。
  4. 一句话总结:抢占,小的是高、能插队;子优先级,小的是先排、不能插队;全相同,互不打断,同时排队时 IRQ 编号小的先跑。

补充一句,STM32F1 也就是 Cortex-M3,优先级只有 4 位有效,共 16 级;用 NVIC_PriorityGroupConfig() 把这 4 位分成抢占位和子优先级位,分组不同,两者占的位数不同,这就是优先级级数和二进制位数有关的原因。

2.2 中断嵌套

中断嵌套,就是按照中断任务的重要性,在中断的过程中还能不断地再中断。

图里用具体数值举例:抢占优先级 2 位,范围 0 到 3,子优先级 2 位,范围 0 到 3。像 (2,x) 正在执行时,(0/1,x) 可以打断它,而 (2/3,x) 就不行。

是否使用中断嵌套,主要看抢占优先级。


三、中断的 NVIC 模块

和从前的模块一样,NVIC 模块也需要设置一番。NVIC 就是管理中断的。

NVIC 的全称是 Nested Vectored Interrupt Controller,嵌套向量中断控制器:Nested 是嵌套,Vectored 是向量,Interrupt 是中断,Controller 是控制器。

所有模块都能产生中断。模块 1、模块 2 一直到模块 n,各自有线接到 NVIC,NVIC 里有优先级寄存器,再往后是仲裁电路。仲裁之后,按中断优先级胜出的函数就能得到调用,去执行硬件功能。NVIC 相当于中断的管理员。

中断来了,就打断主循环,去读消息、回消息,处理完再回来。

四个方块代表优先级,虚线代表中断优先级分组。这里就能设置中断优先级分组,以及抢占优先级、子优先级。

在 CubeMX 的 NVIC 配置页里,Priority Group 可以选分组,比如 2 bits for pre-emption priority 2 bits for subpriority,下面就是中断列表,每一条都能勾选使能,并填抢占优先级和子优先级。

管理之后通过仲裁电路,仲裁结束以后,按照中断优先级胜出的函数就能得到调用、执行硬件的功能。

FLASH 中存储了中断响应函数,以及一些其他的基本代码。单片机通过其中的中断向量表这个目录,来查询 FLASH 里带的不同函数。


复习速记

  • 为什么要中断:串口数据什么时候来不知道,阻塞式等待会把缓冲区等满、丢数据;中断让 CPU 停下手头的事去处理。
  • 中断的本质:让单片机先停下,做更重要的事,也就是小循环和大循环的区别。
  • 优先级规则:先比抢占,小的是高、能打断;再比子优先级,小的是先、不能打断;全相同就不互相打断,同时排队时 IRQ 编号小的先跑。
  • 不是先来后到:同优先级时看起来先来后到,只是因为跑着的那个不会被后来的打断;真正同时排队时看 IRQ 编号。
  • STM32F1 的优先级只有 4 位,共 16 级;NVIC_PriorityGroupConfig() 把这 4 位分成抢占和子优先级。
  • 中断嵌套看抢占优先级;NVIC 是中断管理员,FLASH 里存中断响应函数,靠中断向量表来查。
相关推荐
国科安芯1 小时前
星载微控制器MCU功能安全与信息安全协同机制综述
网络·单片机·嵌入式硬件·安全·抗辐射
HRTOS1 小时前
HRTOS 4.0 官网系统正式更新发布:一轮系统升级完成,进入轻量维护阶段
经验分享·单片机·51单片机
深圳市恒锐丰科技杨生1 小时前
SS6209L 30V 集成 MOS 半桥功率芯片|LeadPower 率能半导体
嵌入式硬件·硬件工程
comyccccc1 小时前
STM32最小系统板高效布线与铺铜优化学习笔记
单片机·嵌入式硬件
学逆向的1 小时前
C printf原型解析
c语言·开发语言·网络安全
一直C2 小时前
嵌入式 Linux 驱动开发学习笔记:中断、等待队列与工作队列
linux·驱动开发·嵌入式硬件·学习·imx6ull
miofly2 小时前
GitHub 日榜趋势速报 | 2026-10-21
开源·github
u1301302 小时前
GitHub 热榜项目:日榜(2026-10-20)
人工智能·github
BeiGuTing_code2 小时前
C字符输出:一个换行符引发的“失踪案”
c语言·开发语言