NVIC and EXTI
这两个是 STM32 中断系统的**“哼哈二将”**。
如果你想让单片机对外部信号(比如按键按下、传感器信号到来)做出反应,必须让这两个模块配合工作。
简单的分工是:
- EXTI (External Interrupt/Event Controller): 负责 “发现” 事情。(前哨兵)
- NVIC (Nested Vectored Interrupt Controller): 负责 “通报” 事情。(大管家)
我们用一个**“CEO 办公室”**的比喻来彻底讲清楚它们的关系。
1. EXTI:门口的保安(前哨兵)
全称: 外部中断/事件控制器。 位置: 在芯片的外围(Peripheral),连接着 GPIO 引脚。
它的工作:
想象单片机是一个大公司,GPIO 引脚是公司的大门。EXTI 就是守在大门口的保安。
- 只管门外: 保安手里拿着一张单子(设置),上面写着:“如果有**穿红衣服的人(上升沿)进来,或者穿绿衣服的人(下降沿)**进来,就立刻报告。”
- 不管决策: 保安不负责处理问题,他只负责监测信号的变化。
- 关键限制(通道共享): STM32 只有 16-20 个 EXTI 通道(保安)。但是 GPIO 引脚有上百个。
- 规则:
PA0,PB0,PC0它们公用 EXTI_Line0。 - 后果: 你不能同时让 PA0 和 PB0 产生中断,因为保安 0 号分身乏术,同一时间只能盯着一个“0号门”。(你需要用 AFIO 数据选择器来告诉保安盯着谁)。
- 规则:
2. NVIC:CEO 的贴身秘书(大管家)
全称: 嵌套向量中断控制器。 位置: 在 Cortex-M3 内核 里(属于 ARM 公司设计的核心部分,权力极大)。
它的工作:
CPU 是CEO,正在专心处理主营业务(main 函数里的 while(1))。NVIC 是坐在 CEO 旁边的秘书长。
- 统管一切: 不光是门口保安(EXTI)会打电话进来,内部的定时器(TIM)、串口(USART)、DMA 都会打电话给秘书。
- 排优先级(Priority):
- 如果是“送外卖的”(低优先级)来了,秘书会让他在旁边等着,等 CEO 忙完手里的活。
- 如果是“消防报警”(高优先级)响了,秘书会立刻打断 CEO,说:“别干了,先救火!”
- 嵌套(Nested):
- 如果 CEO 正在接待“送外卖的”(处理低优先级中断),突然“消防栓”(高优先级中断)爆了。
- NVIC 秘书有权让 CEO 暂停接待外卖员,转头先去处理消防栓,处理完了回来接见外卖员,最后再回到主线工作。这就叫中断嵌套。
3. 完整的“按键中断”流程图
当你的手指按下按键(PA0 引脚产生下降沿)时,发生了这一连串的连锁反应:
- GPIO (大门): PA0 电平由高变低。
- AFIO (摄像头切换): 确认连接的是 PA0 而不是 PB0。
- EXTI (保安): 检测到了下降沿!
- 保安立刻把 EXTI_Line0 的标志位置 1(挂起寄存器)。
- 保安拿起红色电话,直接打给 NVIC。
- NVIC (秘书): 电话响了!
- 秘书看了一眼备忘录(优先级寄存器)。
- 判定:这个中断比当前干的活重要。
- 动作:拍一下 CPU 的肩膀,说:“去执行
EXTI0_IRQHandler那个函数!”
- CPU (CEO):
- 停下
main函数里的活(压栈,保护现场)。 - 跳到
EXTI0_IRQHandler函数里执行代码。 - 干完后,回到
main函数继续干活。
- 停下
4. 代码里的体现
在写代码时,你必须分别配置这两个家伙:
1. 配置 EXTI (告诉保安怎么看门)
C
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line14; // 盯着第14号线
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 模式是中断
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
EXTI_Init(&EXTI_InitStructure);这步只是让保安看到人会报警,但秘书那边还没开通权限。
2. 配置 NVIC (告诉秘书这个电话很重要)
C
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; // 允许接入 EXTI10~15 的电话线
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级(插队能力)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 响应优先级(排队能力)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 开启通道
NVIC_Init(&NVIC_InitStructure);这步之后,中断通路才真正打通。
总结
- EXTI 是来源:它解决了“有没有事发生”的问题(硬件触发)。
- NVIC 是管理:它解决了“先处理谁”以及“能不能打断 CPU”的问题(内核调度)。
**没有 EXTI,NVIC 根本收不到 GPIO 的信号;**没有 NVIC,EXTI 就算喊破喉咙,CPU 也听不到。