文章目录
一、STM32 中断概述
中断,是指处理机处理程序运行中出现的紧急事件的整个过程。程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,自动转入相应的处理程序(中断服务程序),待处理完后,再返回原来的程序运行,这整个过程称为程序中断。当处理机接受中断时,只需暂停一个或几个周期而不执行处理程序的中断,称为简单中断,中断又可分为屏蔽中断和非屏蔽中断两类。
STM32 中断非常强大,每个外设都可以产生中断,所以之后讲的很多外设都可以使用中断,在这里先总体讲解一下中断,之后讲到相应外设的时候再将每个外设的中断使用方法;
F103 在内核水平上搭载了一个异常响应系统,支持为数众多的系统异常和外部中断。其中系统异常有8 个(如果把Reset 和HardFault 也算上的话就是10 个),外部中断有60 个。除了个别异常的优先级被定死外,其它异常的优先级都是可编程的。有关具体的系统异常和外部中断可在HAL 库文件stm32f1xx.h 这个头文件查询到,在IRQn_Type 这个结构体里面包含了F103 系列全部的异常声明。
F103 系统异常清单
优先级 | 优先级类型 | 名称 | 说明 | 地址 |
---|---|---|---|---|
-3 | 固定 | Reset | 复位 | 0X0000 0004 |
-2 | 固定 | NMI | 不可屏蔽中断。RCC 时钟安全系统(CSS) 连接到NMI 向量 | 0X0000 0008 |
-1 | 固定 | HardFault | 所有类型的错误 | 0X0000 000C |
0 | 可编程 | MemManage | 存储器管理 | 0X0000 0010 |
1 | 可编程 | BusFault | 预取指失败,存储器访问失败 | 0X0000 0014 |
2 | 可编程 | UsageFault | 未定义的指令或非法状态 | 0X0000 0018 |
3 | 可编程 | SVCall | 通过SWI 指令调用的系统服务 | 0X0000 002C |
4 | 可编程 | Debug Monitor | 调试监控器 | 0X0000 0030 |
5 | 可编程 | PendSV | 可挂起的系统服务 | 0X0000 0038 |
6 | 可编程 | SysTick | 系统嘀嗒定时器 | 0X0000 003C |
F103 外部中断清单
编号 | 优先级 | 优先级类型 | 名称 | 说明 | 地址 |
---|---|---|---|---|---|
0 | 7 | 可编程 | WWDG | 窗口看门狗中断 | 0X00000040 |
1 | 8 | 可编程 | PVD | 连到EXTI 的电源电压检测(PVD) 中断 | 0X00000044 |
2 | 9 | 可编程 | TAMPER | 侵入检测中断 | 0X00000048 |
··· | |||||
57 | 64 | 可编程 | DMA2 通道2 DMA2 通道2 中断 | 0X00000124 | |
58 | 65 | 可编程 | DMA2 通道3 DMA2 通道3z 中断 | 0X0000 | |
59 | 66 | 可编程 | DMA2 通道4_5 DMA2 通道4 和通道5 中断 | 0X0000012C |
二、NVIC 简介
NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设计芯片的时候会对Cortex-M3 内核里面的NVIC 进行裁剪,把不需要的部分去掉,所以说STM32的NVIC 是Cortex-M3 的NVIC 的一个子集。
NVIC 寄存器简介
在固件库中,NVIC 的结构体定义给每个寄存器都预留了很多位。不过STM32F103 可用不了这么多,只是用了部分而已,具体使用了多少可参考《Cortex-M3 内核编程手册》NVIC 寄存器映射。
typedef struct {
__IOM uint32_t ISER[8U]; // 中断使能寄存器
uint32_t RESERVED0[24U];
__IOM uint32_t ICER[8U]; // 中断清除寄存器
uint32_t RSERVED1[24U];
__IOM uint32_t ISPR[8U]; // 中断使能悬起寄存器
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U]; // 中断清除悬起寄存器
uint32_t RESERVED3[24U];
__IOM uint32_t IABR[8U]; // 中断有效位寄存器/
uint32_t RESERVED4[56U];
__IOM uint8_t IP[240U]; // 中断优先级寄存器(8Bit wide)
uint32_t RESERVED5[644U];
__OM uint32_t STIR; // 软件触发中断寄存器
} NVIC_Type;
在配置中断的时候我们一般只用ISER、ICER 和IP 这三个寄存器,ISER 用来使能中断,ICER 用来失能中断,IP 用来设置中断优先级。
中断优先级
在NVIC 有一个专门的寄存器:中断优先级寄存器NVIC_IPRx,用来配置外部中断的优先级,IPR宽度为8bit,原则上每个外部中断可配置的优先级为0~255,数值越小,优先级越高。但是绝大多数CM3 芯片都会精简设计,以致实际上支持的优先级数减少,在F103 中,只使用了高4bit,
如下所示:
bit7 bit6 bit5 bit4 | bit3 bit2 bit1 bit0 |
---|---|
用于表达优先级 | 未使用,读回为0 |
用于表达优先级的这4bit,又被分组成抢占优先级和子优先级;
如果有多个中断同时响应,抢占优先级高的就会抢占抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级;
如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。
优先级的分组由内核外设SCB 的应用程序中断及复位控制寄存器AIRCR 的PRIGROUP[10:8] 位决定,F103 分为了5 组;
设置优先级分组可调用库函数HAL_NVIC_SetPriority() 实现,有关NVIC 中断相关的库函数都在库文件stm32f1xx_hal_cortex.c 和stm32f1xx_hal_cortex.h 中。
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority,</