EXTI (外部中断)
它的核心任务只有两件事:
- 选路: 决定去监视哪一个引脚。
- 甚至: 决定什么样的信号才算“异常情况”(上升沿/下降沿)。
我们需要解决三个核心问题:“边沿检测” 、“线路冲突” 和 “中断与事件的区别”。
三大关键特性
边沿检测
EXTI 不关心现在的电压是高是低,它只关心电压改变的那一瞬间。
- 上升沿 (Rising Edge): 电压从 0 -> 1 的瞬间(比如松开按键)。
- 下降沿 (Falling Edge): 电压从 1 -> 0 的瞬间(比如按下按键)。
- 双边沿 (Both Edges): 只要变了就触发。
STM32 虽然有 GPIOA, GPIOB, GPIOC... 这么多组端口,但 EXTI 只有 16 条独立的线路 (Line 0 ~ Line 15)。
线路冲突 (GPIO 的 16 路复用)
这是 EXTI 最坑、也是新手最容易犯错的地方。
STM32 有很多 GPIO 口(PA, PB, PC... 每个都有 0~15 号引脚)。但是,EXTI 只有 16 个主要通道 (EXTI0 ~ EXTI15)。
这就意味着:资源是不够分的。
- 规则: 所有端口的 同号引脚,共用一条 EXTI 线路。
- PA0, PB0, PC0, PD0 ... -> 只能选 1 个 连接到 EXTI0。
- PA1, PB1, PC1, PD1 ... -> 只能选 1 个 连接到 EXTI1。
- 比喻:
- EXTI 是只有 16 个屏幕的监控室。
- 屏幕 #0 只能显示一个画面。你可以让它显示 正门(PA0) 的画面,也可以显示 后门(PB0) 的画面,但不能同时显示!
- 这就需要 AFIO (复用功能 IO) 这个“视频切换器”来决定把哪路信号接到屏幕上。
结论: 你无法同时开启 PA0 和 PB0 的外部中断。如果你需要两个中断,请把硬件连接改到 PA0 和 PB1(不同号即可)。
- Line 0: 只能接 PA0 或者 PB0 或者 PC0...
- Line 1: 只能接 PA1 或者 PB1 或者 PC1...
你无法在同一时刻,既开启 PA0 的中断,又开启 PB0 的中断。它们会打架。你需要用 AFIO (复用功能 IO) 这个“路由器”来决定让谁连上 EXTI Line 0。
中断 vs 事件
中断 (Interrupt):
通向 CPU。触发软件回调函数 (
IRQHandler)。 -> 这是你 99% 情况下用的。- 路径: EXTI -> NVIC -> CPU。
- 动作: 打断 CPU,让 CPU 停下手里的活,去跑一段软件代码(中断服务函数)。
- 比喻: 门铃响了,你(CPU)必须放下手里的游戏,去开门。
事件 (Event):
通向 其他外设(如 ADC、DMA)。不惊动 CPU,硬件之间自己搞定(比如:按钮一按 -> 触发 ADC 采集电压,CPU 全程不知道)。
- 路径: EXTI -> 脉冲发生器 -> 其他外设 (DMA/ADC)。
- 动作: 不打断 CPU。它直接发一个硬件信号给旁边的兄弟模块。
- 比喻: 门口装了感应灯。人来了(EXTI),灯自动亮了(触发其他外设)。你(CPU)在屋里打游戏,根本不知道这事,也不需要你操心。
新手只要关注“中断”模式即可,“事件”模式通常用于低功耗唤醒或高级触发。
流程
当你在 PB14 上按了一下:
要让一个按键(比如接在 PA0)产生中断,你需要像“闯关”一样打通以下关节:
开启时钟:
- 开启
GPIOA时钟(因为要用 IO 口)。 - 关键:开启
AFIO时钟!(很多人忘了这个,导致中断没反应。因为需要 AFIO 来选引脚)。
- 开启
配置 GPIO:
- 设为输入模式(上拉/下拉/浮空)。
配置 AFIO (视频切换):
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);- 意思: 告诉 AFIO,把 PA0 连通到 EXTI0 线路。
配置 EXTI (保安设定):
- 线路:
EXTI_Line0 - 模式:
EXTI_Mode_Interrupt(中断模式) - 触发:
EXTI_Trigger_Falling(下降沿) - 使能:
ENABLE
- 线路:
配置 NVIC (秘书通报):
- 通道:
EXTI0_IRQn - 优先级:设一个级别。
- 使能:
ENABLE
- 通道:
GPIO (PB14): 感知到电压从 3.3V 变成了 0V。
AFIO: 确认当前 Line 14 连的是 GPIOB。
EXTI (Line 14): 检测到是一个 下降沿,符合设定,且中断没被屏蔽。
NVIC: 给这个中断排个号(优先级),告诉 CPU:“别睡了,有急事!”
CPU: 暂停当前的主程序,跳转到
EXTI15_10_IRQHandler函数执行代码。你: 在函数里翻转了 LED。
一句话总结:EXTI 就是让 GPIO 具备了“主动报警”的能力。