|
|
@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
[视频](https://www.bilibili.com/video/BV1Fj411V7aq/?spm_id_from=333.788&vd_source=3c8e333d6657680a469ddf0238f01d6a)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[TOC]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 1. 中断概述
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[视频](https://www.bilibili.com/video/BV1Fj411V7aq/?spm_id_from=333.788&vd_source=3c8e333d6657680a469ddf0238f01d6a)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
常见的数据传输方式:p176
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1. 无条件方式:不关心外设的状态,直接发送或者读取。例如按键读取或则LED的控制。还有上个例子中串口的发送(问题:上个例子串口的程序有什么特点和缺陷)。
|
|
|
|
|
|
|
|
2. 查询方式:先查询外设的状态(一般是通过寄存器读);条件允许的情况下再进行读写。
|
|
|
|
|
|
|
|
3. 中断方式:不查询外设的状态,当外设有状态转变的时候产生一个中断,调用一小段代码(ISR中断服务),用来通知主程序;主程序根据通知的内容进行读写操作。
|
|
|
|
|
|
|
|
4. 直接存储器访问方式(DMA):与中断类似,更适合大批量数据的读写;外设与内存之间建立一个联系,当一批数据收到或则是发送完成后产生中断,通知主程序进行处理。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 1.1. 中断相关的概念(p177)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1.1. [中断的定义](https://www.bilibili.com/video/BV1M24y1473t/?spm_id_from=333.788&vd_source=3c8e333d6657680a469ddf0238f01d6a)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1.2. 中断的作用
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
最初是解决处理器速度高,外设速度低的问题,提高处理器的利用率。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
中断方式还有以下优点:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> 分时操作想到了什么?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1.3. 中断优先级和中断嵌套(p178)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
中断是有优先级的,当某个中断的ISR还没有执行完成,此时新中断产生;如果新中断的优先级高于正在执行的中断,就会先执行优先级高的中断ISR;否则当前中断的ISR不受影响,当前中断ISR执行完成后,再执行新的中断ISR。可以想象成多线程,主程序的优先级最低;ISR是按照优先级进行执行的,高优先级的ISR会打断低优先级的ISR执行。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1.4. 中断服务程序和中断向量表
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
我们将中断发生时所执行的特定程序称为中断服务程序,英文缩写为ISR。中断服务程序一般由用户编写,主要内容是该中断发生时需要执行的具体任务。以定时中断实现指示灯的闪烁为例,在发生定时中断时,需要切换指示灯的状态。那么定时中断所对应的中断服务程序的主要内容就是切换指示灯的状态。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
在计算机系统中,当某一个中断源提出中断申请后,处理器要如何准确地找到这个中断源所对应的中断服务程序呢?首先,为了区分各个中断源,计算机系统为每一个中断源分配了一个编号,这个编号称为中断类型号。接着,对于系统需要响应的每一个中断源,都预先编写好对应的中断服务程序。最后,按照中断类型号,从小到大将所有中断服务程序的入口地址(函数名)依次排列,组合为一张表格的形式,这个表格就称为中断向量表(中断对应的ISR,是有优先级的),而中断服务程序(ISR)的入口地址称为中断向量。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
中断向量表通常位于存储器的零地址处。当某一个中断源发出中断申请时,处理器根据识别到的中断类型号查找中断向量表,,到对应的表项。表项的内容就是该中断所对应的中断服务程序的入口地址,然后跳转到该地址执行具体的中断处理任务。从理解的角度上看,我们可以把中断向量表看作一个数组:每一个数组元素的内容就是中断服务程序的入口地址。数组元素的下标相当于每一个中断的中断类型号。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1.1.5. 中断相应过程
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
了解了中断的相关概念后,我们可以总结出中断响应的完整步骤:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1. 中断源发出中断请求。
|
|
|
|
|
|
|
|
2. 判断处理器是否允许中断,以及该中断源是否被屏蔽。
|
|
|
|
|
|
|
|
3. 多个中断同时申请时,需要进行优先级排队。
|
|
|
|
|
|
|
|
4. 处理器暂停当前程序,保护断点地址和处理器的当前状态,根据中断类型号,查找中断向量表,转到对应的中断服务程序。
|
|
|
|
|
|
|
|
执行具体的中断处理任务。
|
|
|
|
|
|
|
|
5. 恢复被保护的处理器状态,执行中断返回指令,回到被暂停程序的断点地址处。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 1.2. STM32中断系统
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
中断可以由硬件或者软件触发。在ARM处理器中,把能够打断当前代码执行流程的事件分为异常(exception)和中断(interrupt)两类。二者的区别在于:中断是由内核外部产生的,一般由硬件触发,比如定时器中断和外部中断等。而异常通常是内核自身产生的,大多由软件触发,比如除法出错异常,预取指失败等。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1.2.1. 嵌套向量中断控制器
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
在基于Cortex-M内核设计的ARM处理器中,提供了一个专用的硬件模块:嵌套向量中断控制器( nested vectored interrupt controller,NVIC),用来管理全部的异常和中断。通过对 NVIC的编程,可以实现中断的使能、中断优先级的设置以及中断触发方式的选择等功能。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
从表 7-1 可以看到,除了复位中断、不可屏蔽中断和类型错误中断的中断优先级是固定的外,其余中断源的中断优先级均可设置。对于每一个中断源而言,按照它在中断向量表中的位置,给出了一个默认的中断优先级,编号越小的优先级越高。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> 注意:由于 STM32 微控制器片内集成的外设较多,而中断通道的数量有限,因此会出现多个外设共享同一个中断通道的情况。对于单个外设而言,它通常具备若于个可以引起中断的中断源。比如定时器就具备更新中断、捕获中断和匹配中断等多个中断源。外设的所有中断源只能通过该外设所指定的中断通道向内核发出中断申请,在中断服务程序内部再判断是该外设的哪一种中断。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1.2.2. STM32中断优先级设置
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
中断源通过中断通道向内核发出中断申请,设置中断源的优先级实际上是设置中断通道的优先级。中断通道的优先级通过NVIC中的中断优先级寄存器NVIC_IP进行设置,该寄存器是8位,理论上可以配置256个中断优先级。STM32微控制器只使用了其中的高4位,并分成了两个优先级:抢占优先级(preempition priority)和子优先级(subpriority )。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
具体的分组情况如下:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1. 第0组:所有4位用于指定子优先级。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2. 第1组:最高1位用于指定抢占优先级,后面3位用于指定子优先级。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3. 第2组:最高2位用于指定抢占优先级,后面2位用于指定子优先级。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4. 第3组:最高3位用于指定抢占优先级,后面1位用于指定子优先级。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5. 第4组:所有4位用于指定抢占优先级。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
不同分组情况下,抢占优先级和子优先级的等级划分如表7-2所示。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
在判断一个中断的优先级时,需要综合考虑这两个优先级。当多个中断同时提出中断申请时,抢占优先级高的中断会优先得到执行。如果抢占优先级相同,则比较子优先级:子优先级高的中断会优先得到执行。如果抢占优先级和子优先级都相同的话,就根据各中断在中断向量表中的位置来确定,中断向量表中靠前的中断优先得到执行。在HAL库的初始化过程中,HAL库初始化函数HAL_Init()将优先级分组设置为第4组,即只有0~15共16级抢占式优先级,没有子优先级。编号越小的优先级越高:0号为最高,15号为最低。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 1.2.3. 外部中断控制器
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[视频](https://www.bilibili.com/video/BV1M24y1473t/?spm_id_from=333.788&vd_source=3c8e333d6657680a469ddf0238f01d6a)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> 什么是上升沿中断,什么是下降沿中断?这个就叫做边缘触发。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 外部中断
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GPIO很多,中断资源有限这么办?复用,多个物理的GPIO公用一个中断向量。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[STM32中文参考手册](../../STM32官方手册/STM32中文参考手册.pdf)的131页的中断向量也可以看到。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 2. HAL库的中断处理
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 2.1. HAL库的中断封装
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 2.2. 外部中断处理流程
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 外部中断的HAL库定义
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 3.1. 外部中断的数据类型
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 3.2. 外部中断的接口函数
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 任务实现
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 4.1. 中断方式检测按键
|