文章目录
- 一、异常类型
-
- [ 1、中断 (Interrupt)](# 1、中断 (Interrupt))
- [ 2、事件(Event):](# 2、事件(Event):)
- [ 3、总结](# 3、总结)
- 二、NVIC嵌套向量中断控制器
-
- [ NVIC结构体](# NVIC结构体)
- [ NVIC中断配置库函数](# NVIC中断配置库函数)
- [ 1、ISER中断使用寄存器](# 1、ISER中断使用寄存器)
- [ 2、ICER中断清除寄存器](# 2、ICER中断清除寄存器)
- [ 3、ISPR中断使能悬起寄存器](# 3、ISPR中断使能悬起寄存器)
- [ 4、ICPR中断清除悬起寄存器](# 4、ICPR中断清除悬起寄存器)
- [ 5、IABR中断有效位寄存器](# 5、IABR中断有效位寄存器)
- [ 6、IPRx中断优先级寄存器(8Bit wide)](# 6、IPRx中断优先级寄存器(8Bit wide))
- [ 7、STIR软件触发中断寄存器](# 7、STIR软件触发中断寄存器)
- [ 8、中断到中断变量的映射](# 8、中断到中断变量的映射)
- 三、优先级的定义
-
- [ 1、优先级寄存器NVIC_IPRx](# 1、优先级寄存器NVIC_IPRx)
- [ 2、优先级分组](# 2、优先级分组)
- 四、中断编程
-
- [ 1、编程要点:](# 1、编程要点:)
- [ 2、NVIC初始化结构体](# 2、NVIC初始化结构体)
- [ 3、编写中断服务函数](# 3、编写中断服务函数)
说明:中断即异常,异常即中断。
一、异常类型
1、中断 (Interrupt)
中断是由硬件设备或外部信号引起的,它通常是异步的,意味着它可以在任何时候发生。
中断通常用于处理紧急情况或需要立即响应的事件,例如硬件故障、设备访问错误或外部信号。
中断处理程序通常需要快速执行,以免影响系统性能。
系统异常8个(Reset和Hardfault)是10个。
系统异常清单

2、事件(Event):
事件是由软件或应用程序引发的,它通常是同步的,意味着它在执行特定代码时发生。
事件通常用于处理需要通知或响应的情况,例如用户输入、网络连接状态变化或应用程序生命周期事件。
事件处理程序可以在后台执行,以免阻塞用户界面或影响应用程序性能。
外部中断60个。
外部中断清单

3、总结
中断和事件都是处理系统中异常情况的方法,但它们的触发方式和处理方式不同。
中断通常由硬件设备或外部信号引起,需要快速处理以免影响系统性能。
事件则通常由软件或应用程序引发,可以在后台执行以免阻塞用户界面或影响应用程序性能。
二、NVIC嵌套向量中断控制器
NVIC是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。
NVIC结构体
c
typedef struct {
__IO uint32_t ISER[8]; // 中断使能寄存器
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; // 中断清除寄存器
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; // 中断使能悬起寄存器
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; // 中断清除悬起寄存器
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; // 中断有效位寄存器
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; // 中断优先级寄存器(8Bit wide)
uint32_t RESERVED5[644];
__O uint32_t STIR; // 软件触发中断寄存器
} NVIC_Type;
我们一般使用ISER、ICER和IP三个寄存器,IESR用来使能中断,ICER用来失能中断,IP用来设置中断优先级。
NVIC中断配置库函数

编程的时候很少使用,有更好的方法。
1、ISER中断使用寄存器
偏移: 0x00 - 0x0B
复位值 : 0x0000 0000

Bits 31:0 SETENA[31:0]:中断设置使能位。
0:禁用中断
1:使能中断。
2、ICER中断清除寄存器
偏移: 0x00 - 0x0B
复位值 : 0x0000 0000

Bits 31:0 CLRENA[31:0]:中断清除使能位。
0:禁用中断
1:使能中断。
3、ISPR中断使能悬起寄存器
偏移: 0x00 - 0x0B
复位值 : 0x0000 0000

Bits 31:0 SETPEND[31:0]:中断设置挂起位
写:
0:没有效果
1:将中断状态改为挂起
读:
0:中断未挂起
1:中断正在等待中
可查中断到中断变量的映射,以了解中断到每个寄存器位的对应关系。
将1写入与暂挂中断对应的ISPR位:
-没有效果。
将中断被禁用对应的ISPR位写1;
-设置该中断的状态为挂起。
4、ICPR中断清除悬起寄存器
偏移: 0x00 - 0x0B
复位值 : 0x0000 0000

Bits 31:0 CLRPEND[31:0]:中断清除等待位
写:
0:没有效果
1:移除中断的挂起状态
读:
0:中断未挂起
1:中断正在等待中
将1写入ICPR位不会影响相应中断的活动状态。
5、IABR中断有效位寄存器
偏移: 0x00 - 0x0B
复位值 : 0x0000 0000

Bits 31:0 ACTIVE[31:0]:中断活动标志
0:中断不活动
1:中断活动
如果相应的中断状态是活动的或活动的和挂起的,那么这个位读为1。
6、IPRx中断优先级寄存器(8Bit wide)
偏移: 0x00 - 0x0B
复位值 : 0x0000 0000
IPR0-IPR16寄存器为每个中断提供一个4位优先级字段。
这些寄存器是字节可访问的。
每个寄存器包含四个优先级字段,它们映射到数组中的四个元素,CMSIS中断优先级阵列IP[0]到IP[67],如图所示。

7、STIR软件触发中断寄存器
偏移: 0xE00
复位值 : 0x0000 000

Bits 31:9保留,必须保持干净。
NTID[8:0]软件产生的中断ID
写入STIR以生成软件生成中断(SGI)。要写入的值是所需SGI的中断ID,范围为0-239。例如,0b000000011表示中断IRQ3。
8、中断到中断变量的映射

三、优先级的定义
1、优先级寄存器NVIC_IPRx

用于表达优先级的4bit,又被分组成抢占优先级和子优先级。
如果有多个中断同时响应,抢占优先级高的就会抢占抢占优先级低的优先得到执行,
如果抢占优先级相同,就比较子优先级。
如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。
2、优先级分组

设置优先级分组可调用库函数NVIC_PriorityGroupConfig()实现,有关NVIC中断相关的库函数都在库文件misc.c和misc.h中。
中断优先级分组库函数NVIC_PriorityGroupConfig()
c
/**
* 配置中断优先级分组:抢占优先级和子优先级
* 形参如下:
* @arg NVIC_PriorityGroup_0: 0bit for抢占优先级
* 4 bits for 子优先级
* @arg NVIC_PriorityGroup_1: 1 bit for抢占优先级
* 3 bits for 子优先级
* @arg NVIC_PriorityGroup_2: 2 bit for抢占优先级
* 2 bits for 子优先级
* @arg NVIC_PriorityGroup_3: 3 bit for抢占优先级
* 1 bits for 子优先级
* @arg NVIC_PriorityGroup_4: 4 bit for抢占优先级
* 0 bits for 子优先级
* @注意 如果优先级分组为0,则抢占优先级就不存在,优先级就全部由子优先级控制
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
// 设置优先级分组
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
四、中断编程
1、编程要点:
1、使能外设某个中断,这个具体由每个外设的相关中断使能位控制。比如串口有发送完成中断,接收完成中断,这两个中断都由串口控制寄存器的相关中断使能位控制。
2、初始化NVIC_InitTypeDef结构体,配置中断优先级分组,设置抢占优先级和子优先级, 使能中断请求。NVIC_InitTypeDef结构体在固件库头文件misc.h中定义。
2、NVIC初始化结构体
NVIC结构体
c
typedef struct {
uint8_t NVIC_IRQChannel; // 中断源
uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
uint8_t NVIC_IRQChannelSubPriority; // 子优先级
FunctionalState NVIC_IRQChannelCmd; // 中断使能或者失能
} NVIC_InitTypeDef;
1、NVIC_IROChannel:
用来设置中断源,不同的中断中断源不一样,且不可写错,即使写错了程序也不会报错,只会导致不响应中断。
可参考stm32f10x.h头文件里面的IRQn_Type结构体定义,这个结构体包含了所有的中断源。
2、NVIC_IRQChannelPreemptionPriority:
抢占优先级,具体的值要根据优先级分组来确定, 具体参考表格 优先级分组真值表 优先级分组真值表。
3、NVIC_IRQChannelSubPriority:
子优先级,具体的值要根据优先级分组来确定, 具体参考表格 优先级分组真值表 优先级分组真值表。
4、NVIC_IRQChannelCmd:
中断使能(ENABLE)或者失能(DISABLE)。 操作的是NVIC_ISER和NVIC_ICER这两个寄存器。

3、编写中断服务函数
在启动文件startup_stm32f10x_hd.s中我们预先为每个中断都写了一个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。
实际的中断服务函数都需要我们重新编写,为了方便管理我们把中断服务函数统一写在stm32f10x_it.c这个库文件中。