一总线复用AFIO相同的pin引脚无法同时触发中断我们需要先了解 EXTI 的“线路共享”机制。1. 背后的硬件原理总线复用STM32 的 EXTI外部中断控制器只有16 条中断线Line 0 到 Line 15。但是芯片上有A、B、C、D...​ 等多个 GPIO 端口。为了让这 16 条线能监控所有端口的引脚STM32 采用了复用设计Pin 0 共用PA0、PB0、PC0、PD0 ... 全部连接到EXTI Line 0。Pin 1 共用PA1、PB1、PC1、PD1 ... 全部连接到EXTI Line 1。...以此类推直到 Pin 15。2. 为什么“不能同时触发”既然这些引脚共用同一条 EXTI 线比如 EXTI Line 0它们就必须遵守“资源共享”的规则互斥性这条线上只能有一个“活跃”的信号源。如果 PA0 正在触发中断此时 PB0 也来了个上升沿系统是无法分辨也不允许两者同时进入中断程序的。配置唯一在初始化代码中你通常只能选择一个具体的引脚如GPIO_Pin_0连接到 EXTI Line 0。如果你试图把 PA0 和 PB0 同时配置给 Line 0后初始化的那个会覆盖前一个或者导致配置失败。3. 实际开发中的影响这个限制直接决定了代码的写法。如果你想监控多个引脚的状态通常只有两种方案方案一错开 Pin 号最常用利用“不同 Pin 可以共用 Line”的特性。例如你可以用PA0(Line 0)、PA1(Line 1)、PA2(Line 2) 来触发三个不同的中断互不影响。方案二同一 Pin 号轮流查轮询法如果你非要用PA0和PB0两个引脚且都需要即时响应因为 EXTI 做不到你就只能在中断发生后用if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))去读取寄存器判断到底是谁触发的。总结这句话的意思是在同一个时刻同名的引脚如 0 号脚只能有一个连接到 EXTI 中断线上。这是由硬件线路复用决定的因此在写代码时你不能把 PA0 和 PB0 同时设为外部中断输入这个过程是通过AFIO实现的。二图中PVDRTCUSB,ETH是怎么通过gpio触发中断的举例工业实例一般怎么用的在介绍具体实例之前必须先纠正一个看图时最容易产生的关键误区这些模块PVD、RTC、USB、ETH并不是通过 GPIO 引脚来触发中断的。1. 核心误区纠正内部信号 vs 外部引脚左侧的 GPIO代表外部物理引脚。信号需要从芯片外面穿过引脚进入芯片内部。这中间必须路过红色的 AFIO中断引脚选择​ 模块由 AFIO 决定到底是PA0还是PB0连接到 EXTI 线上。下方的 PVD/RTC/USB/ETH代表芯片内部的硬件外设。它们产生中断信号完全是内部事件不需要经过外部的引脚和 AFIO 模块而是直接通过内部连线“递交给”橙色的 EXTI边沿检测及控制​ 模块。它们之所以出现在这张图里是因为 STM32 的 EXTI 控制器总共有 20 个输入源除了 16 个给 GPIO 用剩下的 4 个Line 16~19正好被分配给了这四个内部外设。2. 这些内部中断在工业场景中怎么用虽然它们不走 GPIO但它们在工业设计中的“戏份”往往比普通按键还要重。以下是典型的工业应用实例①PVD (可编程电压检测器) —— 工业设备的“保命符”它是干嘛的它像一个高精度的“电源哨兵”实时盯着芯片的供电电压VDD。一旦电压掉到危险线以下它会立刻拉响警报。工业痛点工业现场经常有大型电机启动这会导致瞬间电压骤降俗称“晃电”。应用场景假设一台工业控制器正在控制一台重型机床。突然电网波动导致电压急剧下降。如果在电压彻底崩溃导致单片机复位前PVD 提前发出了中断信号CPU 就能利用这宝贵的几百毫秒时间紧急刹车把机床停稳或者把当前的加工进度、故障代码死死保存到 Flash 里。如果没有 PVD设备可能直接黑屏重启导致半成品报废甚至引发安全事故。②RTC (实时时钟) —— 无人值守的“闹钟”它是干嘛的提供精准的时间和日历功能。工业痛点很多工业设备如远程水泵站、环境监控箱是放在野外或无人车间常年运行的不可能派个人天天去按开关。应用场景定时任务。比如利用 RTC 的闹钟中断EXTI Line 17设置在每天凌晨 2:00 系统负载最低时让单片机自动醒来采集一次传感器数据并通过 4G 模块上传到云端然后再乖乖睡去从而实现极致的低功耗③USB ETH (USB 与以太网) —— 通讯的“唤醒键”它是干嘛的这两个模块通常作为“唤醒源”存在。工业痛点为了省电工业网关在空闲时通常会进入深度休眠Stop/Standby 模式此时 CPU 是不工作的。但厂家又希望能随时远程唤醒它去升级程序或查看状态。应用场景WOL 网络唤醒这就是工业物联网IIoT的标配。比如一个工厂里有一排 STM32 控制的智能电表处于休眠状态。此时工程师在远端服务器上向这排电表发送一个特定的“魔术数据包”Magic Packet。网口ETH收到后硬件电路自动触发中断EXTI Line 19瞬间将整个主板从深度睡眠中“喊醒”CPU 随即开始执行数据采集任务。三EXTI中的中断响应和事件响应的区别。这是一个非常关键的问题也是 STM32 中断系统里最容易混淆的概念。结合你老师给的那张框图我们可以把“中断响应”​ 和事件响应​ 的区别用一句话先总结中断响应是“找 CPU 干活”事件响应是“让硬件自己干活”。✅中断响应EXTI →NVIC​ →CPU✅事件响应EXTI →Pulse​ →硬件外设1中断响应Interrupt Response2事件响应Event Response实现工业自动化事件响应入门系列用的不多。3工业实例四外部中断EXTI的一个小demo#include stm32f10x.h // Device header uint16_t Count; void Exti_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;//外部中断设为上拉输入是人为引起引脚的电平变化 GPIO_InitStructure.GPIO_PinGPIO_Pin_13; GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz; GPIO_Init(GPIOB,GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13); //实现了GPIO-AFIO-EXTI的链接 EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_LineEXTI_Line13; EXTI_InitStructure.EXTI_LineCmdENABLE; EXTI_InitStructure.EXTI_ModeEXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_TriggerEXTI_Trigger_Rising; EXTI_Init(EXTI_InitStructure); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择中断向量组2 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannelEXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmdENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority1; NVIC_InitStructure.NVIC_IRQChannelSubPriority1; NVIC_Init(NVIC_InitStructure); } void EXTI15_10_IRQHandler(void)//每一个中断函数都有自己的名字不能改的在start中找 { if(EXTI_GetITStatus(EXTI_Line13)SET)//判断我们的中断是从线13进来的而不是其余的中断口 { Count; EXTI_ClearITPendingBit(EXTI_Line13);//清除中断标志位 } } uint16_t Count_Return (void) { return Count; }五中断函数名字查找在启动文件中给每一个中断函数均分配了一个名字。六两个中断易混淆函数EXTI_GetFlagStatus(uint32_t EXTI_Line);EXTI_GetITStatus(uint32_t EXTI_Line);EXTI_ClearFlag(uint32_t EXTI_Line);EXTI_ClearITPendingBit(uint32_t EXTI_Line);1EXTI_GetFlagStatus(uint32_t EXTI_Line);使用这类“查询/轮询Polling”函数EXTI_GetFlagStatus如果不做特殊处理CPU 确实会被一直占用无法执行其他任务这正是“中断Interrupt”技术诞生的原因。我们来详细看看这两种模式对 CPU 的影响1. 轮询模式CPU 的“死盯战术”如果你在主循环里写这样的代码while(1) { if (EXTI_GetFlagStatus(EXTI_Line1) ! RESET) { EXTI_ClearFlag(EXTI_Line1); } }工作状态CPU 就像个尽职的保安眼睛死死盯着红灯。哪怕红灯没亮它也在不停地看消耗算力。后果CPU不能休眠无法做其他复杂计算。如果系统里有别的任务比如刷屏幕、算数据这种死盯会严重影响整体性能。2. 中断模式CPU 的“守株待兔”工作机制CPU 平时根本不管门铃。只有当硬件强制打断它时它才停下来去处理。优势CPU利用率极高。没事的时候它能休息有急事中断来了才工作。3.如何优化“轮询”以减少 CPU 占用可以用一个小技巧——加延时让它“喘口气”Delay_ms(10); // 让 CPU 睡 10 毫秒这段时间不查询效果虽然还是会占用 CPU但占用量从100%​ 降到了大概10%剩下的 90% 在 Delay 里休眠。代价按键会有 10ms 的延迟。所以现代高级的单片机编程极其推崇使用中断EXTI_GetITStatus尽量让 CPU 在没有事情的时候“睡觉”这样既能省电又能留出算力给其他复杂任务。