一、中断基础知识
1.概念
中断(Interrupt)是一种特殊的事件处理机制。当CPU正在执行主程序时,如果出现了某些紧急或重要的事件(如外设请求、定时器溢出等),可以暂时中止当前的程序,转而去处理这些事件,处理完毕后再返回原来的程序继续执行。
2.特点
(1)异步性
中断事件的发生是不可预测的,随时可能打断CPU正在执行的主程序。
处理方式是"随时响应",而不是"定时检查"。
(2)优先级
多个中断源可以设置不同的优先级。
高优先级中断可以打断低优先级中断(嵌套中断)。
(3)自动性
中断响应和中断服务程序的调用由硬件自动完成,无需主程序干预。
CPU自动保存当前执行现场,跳转到中断服务程序(ISR)。
(4)高效性
只在有事件发生时才占用CPU资源,避免了无效的轮询,提高了系统效率。
(5)实时性
能够及时响应外部或内部的紧急事件,保证系统的实时性。
(6)可屏蔽性
某些中断可以通过软件设置屏蔽(禁止),防止其打断主程序或更高优先级中断。
(7)现场保护与恢复
响应中断时,CPU会自动保存当前程序的状态(如PC、寄存器等),中断服务程序执行完毕后自动恢复,继续原程序运行。
(8)中断服务程序简短
中断服务程序(ISR)一般要求短小精悍,只处理紧急任务,避免长时间占用CPU。
(9)多源性
一个系统可以有多个中断源(如外部引脚、定时器、串口、ADC等),每个中断源可独立配置和管理。
3.中断的优点
中断能够对突发事件进行及时处理,实现程序的并行化(时间片),进而提高CPU的工作效率。当发生突发事件时,比如外部触发的输入信号、定时器溢出等,中断会立即打断正在执行的程序,转而执行中断服务函数(ISR)来处理该事件。
中断的意义在于让系统能够高效、及时、自动地响应各种事件,提升系统的实时性、效率和可靠性,是现代嵌入式和计算机系统不可或缺的机制。
二、中断流程

1.中断事件发生
2.中断请求检测
3.CPU响应中断
4.跳转到中断服务程序
5.执行中断服务程序
6.清除中断标志
7.恢复现场
8.返回主程序
三、中断系统结构框图

1. 内核部分(左侧蓝色区域)
1.1 CORTEX-M0 内核指令执行单元
负责执行主程序和中断服务程序,是整个MCU的"核心大脑"。
1.2 FLASH中断向量表
存储中断向量表(即每个中断类型对应的服务程序入口地址),当中断发生时,内核会根据向量表跳转到对应的中断服务程序。
1.3 NVIC(嵌套向量中断控制器)
每一个中断事件都有执行或禁止两种状态,由NVIC负责将中断事件标记为清除和挂起两种状态。
挂起: 中断事件已经发生,但是还没有被CPU响应和处理(中断标志位置0)
清除: 清除操作是把中断的挂起标志位或中断标志位从1变为0,别是该终端已经被处理或不再需要处理。
作用:
(1)管理中断事件(清除、挂起)
(2)支持中断向量化处理(向量表)
中断向量化处理,就是每个中断源都有一个唯一的入口地址(即"向量"),当中断发生时,CPU会自动跳转到对应的中断服务程序(ISR)。
(3)支持中断嵌套 (优先级)
NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队
1.4 系统定时器、CSS时钟安全系统等
这些是内核内部的特殊中断源,也会通过NVIC统一管理。
2. 片内外设部分(右侧黄色区域)
2.1 串口、定时器、I2C、EXTI等外设
这些是MCU内部的各种外设模块,每个外设都可以产生中断请求(如串口接收完成、定时器溢出、I2C通信完成、外部中断EXTI等)。
2.2 GPIO(通用输入输出口)
GPIO可以配置为外部中断输入(EXTI),用于响应外部事件(如按键、传感器信号)。
3. 中断流转过程
(1)外设产生中断请求(如串口收到数据、定时器溢出、I2C通信完成、外部引脚电平变化等)。
(2)中断请求送到NVIC,NVIC判断优先级、是否使能等。
(3)NVIC向内核发出中断信号,内核暂停当前任务,查找FLASH中的中断向量表,跳转到对应的中断服务程序(ISR)。
(4)ISR执行完毕后,内核恢复主程序。
四、EXTI(外部中断/事件控制器)
1. EXTI基础知识
1.1 概念
EXTI(External Interrupt/Event Controller,外部中断/事件控制器)是STM32等Cortex-M系列单片机中用于管理外部中断和事件的专用硬件模块。
1.2 EXTI其他特性
支持的触发方式: 上升沿/下降沿/双边沿/软件触发
**支持的GPIO口:**所有GPIO口,但相同的Pin不能同时触发中断
**通道数:**16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒等 26个输入事件
**触发响应方式:**中断响应/事件响应
1.3 EXTI的作用
(1)将外部引脚(如GPIO)上的信号变化转化为中断或事件,通知CPU及时响应外部世界的变化。但相同的Pin不能同时触发中断,就是同一时刻只能选择一个具体的引脚作为中断源。
(2)支持多种触发方式(上升沿、下降沿、双边沿)。
(3)可用于按键检测、外部传感器信号捕获、外部设备唤醒等场景。
1.4 EXTI的基本结构
(1)STM32的EXTI通常有16~23条中断线(EXTI0~EXTI22),每条线可连接到一个或多个(2)GPIO引脚。
(3)每条EXTI线都可以独立配置触发方式和中断使能。
1.5 EXTI的主要功能
(1)中断触发:当选定的GPIO引脚检测到设定的电平/边沿变化时,EXTI产生中断请求。
(2)事件触发:可用于唤醒低功耗模式等。
(3)软件触发:可通过软件模拟外部中断。
2.EXTI外部中断框架流程图

2.1 上升沿和下降沿:
1. 什么是上升沿和下降沿?
- 上升沿(Rising Edge):
指数字信号从低电平(0)跳变到高电平(1)的那一瞬间。
- 下降沿(Falling Edge):
指数字信号从高电平(1)跳变到低电平(0)的那一瞬间。
2. 什么时候产生?
- 当外部信号(如按键、传感器输出、通信信号等)发生电平变化时,就会产生上升沿或下降沿。
- 例如:
- 按下按键时,GPIO引脚电平从高变低,产生下降沿。
- 松开按键时,GPIO引脚电平从低变高,产生上升沿。
- 传感器输出信号变化时,也会产生沿。
3. 谁产生的?
- 沿的产生者是外部信号源,比如:
- 按键、开关
- 传感器
- 其他外部电路或设备
- MCU(如STM32)内部的边沿检测电路负责检测这些沿的出现,并据此触发中断或事件。
4. 在中断系统中的作用
- MCU的外部中断(EXTI)模块可以配置为对上升沿、下降沿或双边沿敏感。
- 当检测到配置的沿时,EXTI会产生中断请求,通知CPU去响应。
2.2 流程
1. 输入线(右侧①)
- 这是外部信号输入端,比如按键、传感器等外部设备的信号线,连接到MCU的某个GPIO引脚。
2. 边沿检测电路(②)
- 用于检测输入信号的变化类型(上升沿、下降沿或电平变化)。
- 可以通过配置,选择对哪种信号变化敏感。
3. 选择/采样寄存器(上升沿/下降沿/软件中断/事件)(③)
- 这些寄存器决定了哪些信号变化会被采样、记录,并进一步产生中断或事件。(是一个或门)
- 包括上升沿选择寄存器、下降沿选择寄存器、软件中断/事件寄存器等。
4. NVIC中断控制器(④)
- 这里是触发中断服务后交给NVIC进行响应
- 最终有效的中断请求会被送到NVIC(嵌套向量中断控制器),由NVIC统一管理中断优先级、分发中断服务。(是一个与门)
5. 脉冲发生器/事件屏蔽寄存器(⑤)
- 产生中断脉冲信号,或用于事件触发(如唤醒等)。
- 事件屏蔽寄存器决定哪些事件可以被传递。
6. 中断服务程序/其他硬件动作(左下⑥)
- NVIC通知CPU进入中断服务程序(ISR),进行相应处理。
- 或者触发其他硬件设备完成必要动作。
7. 挂起请求寄存器/中断屏蔽寄存器
- 挂起请求寄存器:当检测到有效的信号变化时,在这里置位,表示有中断请求待处理。
- 中断屏蔽寄存器:可以屏蔽(禁止)某些中断请求,只有未被屏蔽的请求才会继续传递。
五、EXTI和NVIC的关系
EXTI是中断的"产生者",NVIC是中断的"管理者"
- EXTI负责检测外部信号的变化(如按键按下/松开),当检测到设定的触发条件(如上升沿、下降沿)时,向NVIC发送中断请求。
- NVIC接收到EXTI的中断请求后,根据中断优先级和使能状态,决定是否立即响应,并最终通知CPU跳转到对应的中断服务程序(ISR)。
六、实现按键中断
目标:使用按键实现控制风扇是否转动。
通过上面的学习我们可以发现,中断机制有点类似于"多路复用"。它将所有可能触发中断的外设或事件都登记在中断向量表中。当某个中断被触发时,系统会优先响应并处理该中断事件,主程序则暂时挂起等待。
这种机制为原本单线程、顺序执行的嵌入式系统带来了更多的灵活性,使其能够同时应对多种突发事件,从而实现许多原本难以实现的功能。
1.设置PC9为外部中断--下降沿感应

2.NVIC打开EXTI9中断

3.设置风扇为GPIO-OUT

4.找中断处理程序(找GPIO的回调函数)
5.在程序中切换风扇的状态
重写HAL_GPIO_EXTI_Falling_Callback函数,这是GPIO下降沿触发的回调函数,当有GPIO触发中断(下降沿)就会停止主程序先去运行回调函数内的程序。这里就是当触发点GPIO是按键的时候,就让风扇状态转变。

七、实现串口中断
1.先设置串口引脚

2.添加串口到中断

3.找串口的回调函数

4.找到函数:
前面加了weak说明是虚函数,可以重写,所以我们把函数复制到主函数的全局定义区域重写内容就可以。
4.1 回调函数:
cs
weak void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart) //当单片机向着串口发送数据进入这个函数
4.2 中断函数
cs
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
5.代码实现
5.1 代码实现发送中断
当我们向着串口发送数据就会进入这个函数(T开头,对应着我们的HAL_UART_Transmit_IT函数),为什么不用HAL_UART_Transmit函数,因为这个中断专用的,普通的输出函数用不了。
别忘了printf和scanf重定向,不然hello输出不到串口。可以看我之前文章配置单片机(STM32-串口通信)-CSDN博客
5.2 代码实现接收中断
(1)定长 接收 中断
回调函数:
csweak void HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef *huart) //当单片机接收到串口发送的数据进入这个函数
定长接收的中断函数:
csHAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
(2)不定长 接收 中断 - - 空 闲 中断

1. 空闲中断的特点
1.在一帧数据传输结束后,通信线路将会维持高电平,这个状态称为空闲状态;
2.当 CPU 检测到通信线路处于空闲状态时,且空闲状态持续时间大于一个字节传输时间时,空闲状态标志 IDLE 将由硬件置 1 。如果串口控制寄存器 CR1 中的 IDLEIE 位为 1 ,将会触发空闲中断 (IDLE 中断);
3.由于空闲标志是在一帧数据传输完成后才置位,在有效数据传输过程中不会置位,因此借助空闲中断,可以实现不定长数据的收发。
2. 串口通信的常规中断
- 一般来说,串口每收到一个字节,就会触发一次"接收中断",你可以在中断里处理这个字节。
- 但如果你要接收一串数据(比如一条消息),你并不知道消息什么时候结束,只能一个字节一个字节地处理,很麻烦。
3. 空闲中断的作用
- 空闲中断就是:
当串口一段时间没有再收到新数据时,硬件会自动告诉你:"现在串口是空闲的,数据流已经结束了!"
- 这样你就可以在空闲中断里,一次性处理刚刚收到的那一串数据。
4. 函数:
回调函数:
csvoid HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
不定长接收的中断函数:
csvoid HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
5.代码实现:

这里的空闲中断函数只能用一次,想要多次使用,可以在回调函数里面调用空闲中断,上面的也是一样,最好不放在while循环里。

这里memset的作用是把数组清空
八、总结
中断是一种让CPU在处理主程序时,能够及时响应外部或内部突发事件的机制。它具有异步性、高效性、优先级、自动性等特点,极大提升了嵌入式系统的实时性和可靠性。
在STM32等单片机中,EXTI负责检测外部信号并产生中断请求,NVIC统一管理和分发中断,实现多源中断的高效处理。
通过合理配置和使用中断,可以让系统在单线程下实现"伪并行",高效应对各种输入输出需求,如按键控制、串口通信等。
特别是串口空闲中断,为不定长数据的高效接收提供了便利,是现代嵌入式开发不可或缺的重要技术。
可以自己尝试写一下:不定长接收去实现数码管显示内容,输入几个数据就改变几个数据