中断
概述
打断CPU执行正常的程序,转而处理紧急程序,然后返回原暂停的程序继续运行,就叫中断。
中断的作用和意义
- 实时控制:在确定时间内对相应事件作出响应,如:温度监控
- 故障处理:检测到故障,需要第一时间处理,如:电梯门夹人了
- 数据传输:不确定数据何时会来,如:串口数据接收
[!IMPORTANT]
中断的意义:高效处理紧急程序,不会一直占用CPU资源
执行流程

NVIC
基本概念
用于统一分配中断优先级和管理中断的
==Nested vectored interrupt controller==,嵌套向量中断控制器,属于内核(M3/4/7)
NVIC支持:256个中断(16内核+240外部),支持:256个优先级,允许裁剪!
| STM32型号 | 内核中断 | 外部中断 | 中断优先级 |
|---|---|---|---|
| STM32F103xx | 10 | 60 | 16 |
| STM32F407xx | 10 | 82 | 16 |
| STM32F429xx | 10 | 91 | 16 |
| STM32F750xx | 10 | 98 | 16 |
| STM32F767xx | 10 | 110 | 16 |
| STM32H743xx | 10 | 150 | 16 |
| STM32H750xx | 10 | 150 | 16 |
中断向量表
定义一块固定的内存,以字节对齐,存放各个==中断服务函数程序的首地址==。
中断向量表定义在==启动文件中==,当发生中断,CPU会自动执行对应的中断服务函数,以下有个中断向量表的例子:
| Position | Priority | Priority type | Acronym | Description | Address |
|---|---|---|---|---|---|
| 0 | - | - | MSP初值 | 主栈指针初始化地址 | 0x0000_0000 |
| 1 | -3 | fixed | Reset | 复位向量 | 0x0000_0004 |
| 2 | -2 | fixed | NMI | WKUPx中断 低功耗模式错误中断 | 0x0000_0008 |
| 3 | -1 | fixed | HardFault | HardFault中断向量 | 0x0000_000C |
| 4-10 | - | - | - | Reserved | 0x0000_0010~0x0000 002B |
| 11 | 3 | settable | SVC | SVCall系统服务请求 | 0x0000 002C |
| 12-13 | - | - | - | Reserved | 0x0000_0030~0x0000 0037 |
| 14 | 5 | settable | PendSV | 可挂起系统服务请求 | 0x0000_0038 |
| 15 | 6 | settable | Systick | 内部定时器中断向量 | 0x0000_003C |
| 16 | 7 | settable | WDT | 窗口看门狗或独立看门狗 | 0x0000_0040 |
| 17 | 8 | settable | SVD | 中断 电源监测报警中断 | 0x0000_0044 |
| 18 | 9 | settable | RTCA/RTCB | 实时时钟中断 | 0x0000_0048 |
| 19 | 10 | settable | FLASH | NVMIF中断 | 0x0000_004C |
| 20 | 11 | settable | FDET | XTLF 或XTHF停振检测 中断 系统时钟选择错误中断 | 0x0000_0050 |
| 21 | 12 | settable | ADC | ADC转换完成中断 | 0x0000_0054 |
| 22 | 13 | settable | DAC | DAC中断 | 0x0000_0058 |
| 23 | 14 | settable | SPI0 | SPI中断 | 0x0000_005C |
| 24 | 15 | settable | SPI1 | : | 0x0000_0060 |
| 25 | 16 | settable | SPI2 | : | 0x0000_0064 |
| 26 | 17 | settable | UART0 | UART中断 | 0x0000_0068 |
| 27 | 18 | settable | UART1 | : | 0x0000_006C |
| 28 | 19 | settable | UART3 | : | 0x0000_0070 |
| 29 | 20 | settable | UART4 | : | 0x0000_0074 |
| 30 | 21 | settable | UART5 | : | 0x0000_0078 |
| 31 | 22 | settable | U7816 | U7816中断 | 0x0000_007C |
| 32 | 23 | settable | LPUARTX | LPUART0/1/2中断 | 0x0000_0080 |
| 33 | 24 | settable | I2C | I2C中断 | 0x0000_0084 |
| 34 | 25 | settable | CCL | 时钟校准中断 | 0x0000_0088 |
| 35 | 26 | settable | AES | AES中断 | 0x0000_008C |
| 36 | 27 | settable | LPTIM | LPTIM16或LPTIM32中 断 | 0x0000_0090 |
| 37 | 28 | settable | DMA | DMA中断 | 0x0000_0094 |
| 38 | 29 | settable | WKUPX | WKUP引脚中断 | 0x0000_0098 |
| 39 | 30 | settable | LUT | LUT中断 | 0x0000_009C |
| 40 | 31 | settable | BSTIM | BSTIM16或BSTIM32中 断 | 0x0000_00A0 |
| 41 | 32 | settable | COMPX | COMPx中断 | 0x0000_00A4 |
| 42 | 33 | settable | GPT0,1 | 通用定时器0.1中断 | 0x0000_00A8 |
| 43 | 34 | settable | GPT2 | 通用定时器2中断 | 0x0000_00AC |
| 44 | 35 | settable | ATIM | 高级定时器中断 | 0x0000_00B0 |
| 45 | 36 | settable | VREF1p2 VREF_VREG | 1.2V 内部基准电压建立中断 VREF_VREG中断 | 0x0000_00B4 |
| 46 | 37 | settable | EXTI | 外部引脚中断 | 0x0000_00B8 |
| 47 | 38 | settable | CAN | CAN2.0中断 x0000_0OBC | 0x0000_00BC |
相关寄存器
| NVIC相关寄存器 | 位数 | 寄存器个数 | 备注 |
|---|---|---|---|
| 中断使能寄存器(ISER) | 32 | 8 | 每个位控制一个中断 |
| 中断除能寄存器(ICER) | 32 | 8 | 每个位控制一个中断 |
| 应用程序中断及复位控制寄存器(AIRCR) | 32 | 1 | 位[10:8]控制优先级分组 |
| 中断优先级寄存器 (IPR) | 8 | 240 | 8个位对应一个中断,而 STM32只使用高4位 |
NVIC还有:中断挂起,解挂,激活标志等非常有用的功能。
基本结构
NVIC是一个内核外设,是CPU的小助手

上图为外部中断,其中的n代表一个外设可能同时占用多个中断通道,所以有n条线
NVIC只有一个输出口,NVIC根据每个中断的优先级分配中断的先后顺序,通过一个输出口告诉CPU应该处理哪个中断
中断优先级
- ==抢占优先级==(pre):高抢占优先级可以打断正在执行的低抢占优先级中断
- ==响应优先级==(sub):当抢占优先级相同时,响应优先级高的先执行,但是不能互相打断
- 抢占和响应都相同的情况下,自然优先级越高的,先执行
- ==自然优先级==:中断向量表的优先级
- 数值越小,表示优先级越高
[!IMPORTANT]
抢占优先级 > 响应优先级 > 自然优先级
NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队
| 优先级分组 | AIRCR[10:8] | IPRx bit[7:4]分 配 | 分配结果 |
|---|---|---|---|
| 0 | 111 | None : [7:4] | 0位抢占优先级,4位响应优先级 |
| 1 | 110 | [7] : [6:4] | 1位抢占优先级,3位响应优先级 |
| 2 | 101 | [7:6] : [5:4] | 2位抢占优先级,2位响应优先级 |
| 3 | 100 | [7:5] : [4] | 3位抢占优先级,1位响应优先级 |
| 4 | 011 | [7:4] : None | 4位抢占优先级,0位响应优先级 |
[!note]
特别提示:一个工程中,一般只设置一次中断优先级分组。
| 编号 | 自然优先级 | 对应外设 | 抢占 | 响应 | 执行顺序 |
|---|---|---|---|---|---|
| 3 | 10 | RTC | 2 | 1 | 2 |
| 6 | 13 | EXTI0 | 3 | 0 | 4 |
| 7 | 14 | EXTI1 | 2 | 0 | 1 |
| -1 | 6 | Systick | 3 | 0 | 3 |
[!note]
EXTI1和RTC可以打断:EXTIO和Systick的中断,获得优先执行!
EXTI
External(Extended)interrupt/event Controller,外部(扩展)中断事件控制器包含20个产生事件/中断请求的边沿检测器,即总共:20条EXTI线(F1)
中断和事件的理解:
- 中断:要进入NVIC,有相应的中断服务函数,需要CPU处理
- 事件:不进入NVIC,仅用于内部硬件自动控制的,如:TIM、DMA、ADC
产生的中断和事件都会有他们的响应函数
- 中断响应申请中断,让CPU执行中断函数
- 事件响应,外部中断信号不会通向CPU,而是通向其他外设,用来触发其他外设的操作(ADC转换、DMA等)
EXTI(Extern Interrupt)外部中断
- EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
- 支持的触发方式:上升沿/下降沿/双边沿/软件触发
- 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
- 通道数:16个GPIO Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
- 触发响应方式:中断响应/事件响应
[!tip]
当有多个中断引脚的时候,我们需要选择不同PIN的引脚,比如PA10和PB10就不能同时作为中断引脚
事件请求表
| 中断线 | F1 | F4 | F7 | H7 |
|---|---|---|---|---|
| EXTI线0~15:对应GPIO PIN 0~15 | ✔ | ✔ | ✔ | ✔ |
| EXTI线16:PVD输出 | ✔ | ✔ | ✔ | 参考H7参考手册(中文版)657页 |
| EXTI线17:RTC闹钟事件 | ✔ | ✔ | ✔ | |
| EXTI线18:USB OTG FS唤醒事件 | ✔ | ✔ | ✔ | |
| EXTI线19:以太网唤醒事件 | ✔ | ✔ | ||
| EXTI线20:USB OTG HS唤醒事件 | ✔ | ✔ | ||
| EXTI线21:RTC 入侵和时间戳事件 | ✔ | ✔ | ||
| EXTI线22:RTC 唤醒事件 | ✔ | ✔ | ||
| EXTI线23:LPTIM1 异步事件 | ✔ | |||
| … |
整体结构

每个GPIO端口有16个引脚,而EXTI实际上只有16个通道,所以==每个端口只能有一个中断引脚==,GPIO口加上PVD、RTC、USB、ETH等一共20个信号。
[!TIP]
注意,EXTI 5 ~ 9使用同一个中断函数,EXTI 10 ~ 15使用一个中断函数,所以在写中断函数的时候,我们需要根据标志位来区分是哪个中断
到其他外设的20个信号是事件触发时的信号
信号方向:==输入线 > 边沿检测电路(用于上升沿触发或者下降沿触发)> 检测上升沿、下降沿、双边沿及软件触发 > 出现分支==
- 中断:==如果请求挂起寄存器置1 > NVIC中断控制器==
- 事件:通过事件屏蔽寄存器做一个开关的作用 -> 脉冲发生器,给一个电平脉冲,用来触发其他外设的动作
AFIO
Alternate Function IO,即复用功能lO,主要用于重映射和外部中断映射配置
-
调试I○配置:AFIO MAPR[26:24],配置JTAG/SWD的开关状态
-
重映射配置:AFIO MAPR,部分外设IO重映射配置
-
外部中断配置:AFIO EXTICR1 ~ 4,配置EXTI中断线0 ~ 15对应具体哪个1O口
[!NOTE]
特别注意:配置AFIO寄存器之前要使能AFIO时钟,方法如下:
HAL RCC AFIO CLK ENABLE(); 对应RCC APB.2ENR寄存器位0
AFIO主要完成两个任务:
- 复用功引脚重映射
- 中断引脚选择
如将GPIO A PIN1引脚作为TIM1的引脚
EXTI和IO的对应关系

这里可以看出来一条线只能对应一个口,如不能同时使用PA0和PB0,只能从P[A~K]0中选一个
中断配置
中断配置步骤:
- 使能GPIO时钟:使能GPIO时钟
- 设置GPIO输入模式:上/下拉/浮空输入
- 使能AFIO/SYSCFGI时钟:设置AFIO/SYSCFGE时钟开启寄存器
- 设置EXTI和IO对应关系
- 设置EXTI屏蔽,上/下:设置EXTI对应通道前的屏蔽和上升沿/下降沿确发,IMR、RTSR/FTSR沿
- 设置NVIC:分3步:设置优先级分组、设置优先级、使能中断
- 设计中断服务函数:编写对应中断的中断服务函数!清中断标志!
实验
1 | void GPIO_init(){ |





