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

单片机(STM32-中断)

一、中断基础知识

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 回调函数:

weak void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart) //当单片机向着串口发送数据进入这个函数

4.2 中断函数

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)定长接收中断

回调函数:

weak void HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef *huart)  //当单片机接收到串口发送的数据进入这个函数
定长接收的中断函数:
HAL_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. 函数:

回调函数:

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)

不定长接收的中断函数:

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
5.代码实现:

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

这里memset作用数组清空

八、总结

中断是一种让CPU在处理主程序时,能够及时响应外部或内部突发事件的机制。它具有异步性、高效性、优先级、自动性等特点,极大提升了嵌入式系统的实时性和可靠性。

在STM32等单片机中,EXTI负责检测外部信号并产生中断请求,NVIC统一管理和分发中断,实现多源中断的高效处理。

通过合理配置和使用中断,可以让系统在单线程下实现“伪并行”,高效应对各种输入输出需求,如按键控制、串口通信等。

特别是串口空闲中断,为不定长数据的高效接收提供了便利,是现代嵌入式开发不可或缺的重要技术。
可以自己尝试写一下:不定长接收去实现数码管显示内容输入几个数据改变几个数据

http://www.dtcms.com/a/282544.html

相关文章:

  • JS逆向 - YandexSmartCaptcha (worker线程)
  • 基于WebRTC构建应用的可复用模块
  • 下载webrtc M114版本源码只能使用外网googlesource源-命令版
  • i.mx8 RTC问题
  • TEngine学习
  • 【Noah-MP模型】陆面生态水文模拟与多源遥感数据同化的实践技术应用
  • JavaScript进阶篇——第六章 内置构造函数与内置方法
  • alpineLinux修改包管理为国内源
  • 越野小车结构设计\越野小车设计cad【6张】三维图+设计说明书
  • 【Java】【力扣】101.对称二叉树
  • 数据结构与算法——Leetcode215. 数组中的第K个最大元素
  • 中国1km分辨率逐月平均气温数据集 - matlab按shp批量裁剪
  • Git远程仓库与协作技巧详解
  • 【add vs commit】Git 中的 add 和 commit 之间的区别
  • 秘塔AI搜索的深度研究推出:它的“免费午餐”还能走多远?
  • NULL值处理:索引优化与业务设计实践指南
  • GIT版本回退
  • 堆排序算法详解:原理、实现与C语言代码
  • ubuntu--自启动程序
  • Docker Compose 清理指南:`down` 与 `down -v` 的核心区别与使用场景
  • Jenkins credentials 增加了github credential 但是在Git SCM 凭证中不显示
  • 基于SpringBoot+Uniapp球场预约小程序(腾讯地图API、Echarts图形化分析、二维码识别)
  • 如何用 Charles 中文版抓包工具高效调试 API 并优化网络性能
  • 自适应哈希索引 和 日志缓冲区
  • 结构体(二)
  • XXE漏洞1-XXE 漏洞简介-XML 语法-DTD 讲解-外部实体讲解
  • 【React Native】安装配置 Expo Router
  • HTML基础P1 | HTML基本元素
  • Jmeter中Parallel Controller的配置方法(并发)
  • 小白学HTML,操作HTML文件篇(2)