一、外部中断 基础知识
1. 什么是外部中断
普通程序是顺序执行、循环轮询:单片机一直死循环挨个检测引脚电平,浪费 CPU 资源、响应还慢。
外部中断 :单片机正常跑自己的主程序,不去主动检测引脚 ;当外部引脚电平发生变化(高变低 / 低变高),硬件自动触发,立刻暂停当前主程序,跳转到专门的中断函数里执行,执行完再回到原来断点继续运行。
一句话:轮询是单片机主动一直盯着;中断是引脚有事主动通知单片机。
2. 外部中断能触发的信号类型
三种触发边沿,固定就这三种:
- 下降沿触发:高电平 → 低电平 瞬间触发
- 上升沿触发:低电平 → 高电平 瞬间触发
- 双边沿触发:上升、下降任意一种变化都触发
3. STM32 外部中断线路规则
STM32F1 系列有 16 根外部中断线 EXTI0 ~ EXTI15对应引脚编号 0~15:
- EXTI0 对应 所有 GPIO 的第 0 脚:PA0/PB0/PC0...
- EXTI1 对应 所有 GPIO 的第 1 脚:PA1/PB1/PC1...
- ......
- EXTI15 对应 所有 GPIO 的第 15 脚
重点规则 同一条中断线,同一时刻只能用一个引脚;比如 EXTI0 用了 PA0,就不能再同时用 PB0、PC0 做外部中断。
4. 外部中断整体工作流程
引脚电平变化 → 触发 EXTI 外设 → 申请中断 → NVIC 裁决是否放行 → 进入中断服务函数执行。
二、复用功能 AFIO
1. 什么是 GPIO 复用功能
STM32 的每个 GPIO 引脚不只有普通输入 / 普通输出这一种功能;一个引脚可以有多种身份:
- 普通 GPIO 输入输出
- 串口收发
- SPI、I2C
- 定时器 PWM
- 外部中断输入
这种一个引脚具备多种硬件功能 ,就叫 复用功能(Alternate Function)。
2. 为什么外部中断必须用到 AFIO
普通 GPIO 输入只做普通电平读取;要把 GPIO 引脚切换成外部中断功能 ,不属于普通 GPIO 模式,属于复用功能 ,必须由 AFIO 外设 来管理配置。
3. 关键必记知识点
- 只要用外部中断,必须开启 AFIO 外设时钟
- AFIO 不负责高低电平读取,只负责:
- 引脚中断线选择
- 引脚功能重映射
- 没有开启 AFIO 时钟,外部中断配置再对也进不去中断。
三、重映射(引脚映射 / 中断线映射)
1. 什么是重映射
前面说了:PA0、PB0、PC0...... 都共用 EXTI0 这一根中断线。
单片机不知道你到底想用哪一个端口的第 0 脚 做中断;我们需要手动指定:把哪一个 GPIO 端口的引脚,绑定到对应的 EXTI 中断线上 这个指定绑定的过程,就叫重映射。
2. 重映射的作用
- 选择同一中断线下具体用哪个引脚(PAx / PBx / PCx)
- 可以把部分外设功能切换到其他引脚(引脚功能重映射)
- 解决引脚不够、布线不方便的问题
3. 核心逻辑
中断线是固定的 EXTI0~EXTI15;引脚是灵活的,可以通过重映射,任选同编号的一个 GPIO 引脚挂到这条中断线上。
4. 重映射和普通 GPIO 的区别
普通 GPIO:直接配置模式即可;外部中断:除了配 GPIO 模式,必须多一步重映射,把引脚关联到 EXTI 中断线。
四、中断嵌套控制器 NVIC
1. 什么是 NVIC
NVIC 是单片机内核自带的 嵌套向量中断控制器,是所有中断的 "大管家"。
EXTI 只是负责检测电平、产生中断请求 ;能不能响应、谁先响应、能不能插队,全部由 NVIC 说了算。
2. NVIC 管哪三件事
- 开启 / 关闭 某个中断通道
- 设置中断优先级
- 处理中断嵌套(高优先级打断低优先级)
3. 两个优先级概念(重点,必须懂)
STM32 中断优先级分两层:
-
抢占优先级 级别高的中断,可以打断正在执行的低优先级中断,实现中断嵌套。数字越小,优先级越高。
-
子优先级 多个中断同时一起到来,谁先执行;不能打断别人,只做排队顺序。
4. 中断嵌套是什么意思
低优先级中断正在运行,此时来了一个抢占优先级更高 的中断;NVIC 允许高优先级插队,暂停当前低优先级,先执行高优先级中断,执行完再回来继续原来的。这就叫中断嵌套。
5. NVIC 配置的意义
哪怕 EXTI 配置全对、引脚配置全对;NVIC 不开启通道、不设优先级,中断永远进不去。
五、STM32 外部中断 EXTI 标准配置步骤
1、提前必配:中断分组(程序开头只调用一次)
放在 main 最开头,整个工程统一分组,只用这一种:
// 设置中断分组2:2位抢占优先级,2位子优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
第 1 步:开启 GPIO 时钟
所有 GPIO 外设必须先开时钟,才能工作,这是 STM32 所有外设的通用规则。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
替换:GPIOA → GPIOB/GPIOC
第 2 步:开启 AFIO 时钟
外部中断属于GPIO 复用功能 ,必须依赖 AFIO 外设;不开 AFIO 时钟,后面重映射、中断线配置全部无效,进不了中断。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
所有外部中断,这一句必加,不能省
第 3 步:配置 GPIO 输入模式
外部中断引脚只能配置为三种输入模式:
-
上拉输入
-
下拉输入
-
浮空输入不能配成输出、复用输出,否则无法检测电平边沿变化。
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; // 填你要用的引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
// 可选:GPIO_Mode_IPD 下拉输入 / GPIO_Mode_IN_FLOATING 浮空输入GPIO_Init(GPIOA, &GPIO_InitStruct); // 对应端口
第 4 步:GPIO 中断线重映射
作用:把 某一组 GPIO 的某一号引脚,指定绑定到对应的 EXTIx 中断线上。规则:引脚编号 x 只能绑定 EXTIx 中断线,不能跨号绑定。
// 把 GPIOA Pin0 映射到 EXTI0 中断线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
规则:
PinSource0只能配EXTI0- 引脚号和中断线号必须一致
第 5 步:配置 EXTI 外设
配置三件事:
-
选择触发方式:上升沿 / 下降沿 / 双边沿
-
选择工作模式:中断模式(不是事件模式)
-
使能对应 EXTI 中断线,允许它发出中断请求
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line0; // 对应中断线
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
// 可选:EXTI_Trigger_Rising 上升沿 / EXTI_Trigger_Rising_Falling 双边沿
EXTI_InitStruct.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStruct);
第 6 步:配置 NVIC 中断控制器
配置三件事:
-
选择对应的中断通道
-
设置抢占优先级 、子优先级
-
使能该中断通道,允许内核响应这个中断
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; // 对应中断通道
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; // 子优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);
第7步:中断服务函数模板(固定函数名,不能自己乱改)
写在任意 .c 文件里,不用声明,自动响应中断:
void EXTI0_IRQHandler(void)
{
// 检查是不是对应中断线触发
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
// 这里写中断触发后要执行的代码
// 必须清除中断标志位,否则一直重复进中断
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
2、配置完硬件后必做一步
在工程里自行编写 中断服务函数固定规则:
- 函数名不能自己乱起,要匹配芯片启动文件里的中断函数名
- 函数内部写中断触发后要执行的逻辑
- 不需要手动调用,硬件触发自动跳转执行
3、浓缩口诀
开 GPIO → 开 AFIO → 配输入 → 做重映射 → 配 EXTI → 配 NVIC → 写中断服务函数。
4、补充两个必记硬性规则
- 所有同编号引脚(PAx、PBx、PCx)共用一条 EXTIx 中断线,同一时间只能用一个。
- 外部中断缺一不可:AFIO 时钟 + 重映射 + EXTI 配置 + NVIC 配置,少任何一步都进不去中断。
附:常用中断线 对应通道 & 函数名 对照表
| 中断线 | NVIC 通道名 | 中断服务函数名 |
|---|---|---|
| EXTI0 | EXTI0_IRQn | EXTI0_IRQHandler |
| EXTI1 | EXTI1_IRQn | EXTI1_IRQHandler |
| EXTI2 | EXTI2_IRQn | EXTI2_IRQHandler |
| EXTI3 | EXTI3_IRQn | EXTI3_IRQHandler |
| EXTI4 | EXTI4_IRQn | EXTI4_IRQHandler |
| EXTI5~9 | EXTI9_5_IRQn | EXTI9_5_IRQHandler |
| EXTI10~15 | EXTI15_10_IRQn | EXTI15_10_IRQHandler |