芯片型号:STM32F103RC
软件开发包:标准外设库
一、中断系统
-
中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理处理中断程序,处理完成后又返回原来被暂停的位置继续运行。
-
中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源。
-
中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回。
中断执行流程:
二、STM32中断
-
68(F1系列最多的中断数量)个可屏蔽中断通道,包含 EXTI、TIM、ADC、USART、SPI、I2C、RTC 等多个外设。
-
使用 NVIC 统一管理中断,每个中断通道都拥有 16 个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和子优先级。
2.1 NVIC简介
NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。
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 这三个寄存器,ISER 用来使能中断,ICER 用来失能中断,IP 用来设置中断优先级。
2.2 NVIC基本结构
NVIC 是 STM32 用来管理中断、分配优先级的,有很多输入口,可以接多个中断线路,但 NVIC 只有一个输出口,根据每个中断的优先级分配中断的先后顺序,将要执行的那个中断传递给CPU,进行处理。
2.3 NVIC优先级分组
-
在F103中,NVIC 的中断优先级由优先级寄存器 NVIC_IPRx 的高 4 位决定,这 4 位可以进行切分,分为高 n 位的抢占优先级和低 4-n位的子优先级,数值越小,优先级越高。
-
抢占优先级高的可以中断嵌套,子优先级高的可以优先排队,抢占优先级和子优先级均相同的按中断号排队。
分组方式 | 抢占优先级 | 子优先级 |
---|---|---|
分组0 | 0位,取值为0 | 4位,取值为0~15 |
分组1 | 1位,取值为0~1 | 3位,取值为0~7 |
分组2 | 2位,取值为0~3 | 2位,取值为0~3 |
分组3 | 3位,取值为0~7 | 1位,取值为0~1 |
分组4 | 4位,取值为0~15 | 0位,取值为0 |
2.4 中断编程
1. 使能中断请求,这个具体由每个外设的相关中断使能位控制;
2. 配置中断优先级分组;
设置优先级分组可调用库函数NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
实现;
3. 初始化NVIC_InitTypeDef
结构体;
该结构体成员如下:
typedef struct
{
uint8_t NVIC_IRQChannel; // 指定中断请求通道,参数为对应的中断号
uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
uint8_t NVIC_IRQChannelSubPriority; // 子优先级
FunctionalState NVIC_IRQChannelCmd; // 使能或者失能中断请求通道
} NVIC_InitTypeDef;
4. 编写中断服务函数。
在启动文件 startup_stm32f10x_hd.s 中我们预先为每个中断都写了一个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,为了方便管理我们可以把中断服务函数统一写在stm32f10x_it.c 这个库文件中。
关于中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量表中找不到中断服务函数的入口,直接跳转到启动文件里面预先写好的空函数,并且在里面无限循环,实现不了中断。
参考视频源于B站up主: 野火科技、江协科技
参考文档:《STM32库开发实战指南——基于野火MINI开发板》