关闭单个通道的中断
问题的本质NVIC 是粗粒度的STM32F4 有 16 条 EXTI 线EXTI0~EXTI15但 NVIC 只把它们合并成 7 个中断号EXTI0 → EXTI0_IRQn (1根线独享) EXTI1 → EXTI1_IRQn (1根线独享) EXTI2 → EXTI2_IRQn (1根线独享) EXTI3 → EXTI3_IRQn (1根线独享) EXTI4 → EXTI4_IRQn (1根线独享) EXTI5~9 → EXTI9_5_IRQn (5根线共享) EXTI10~15 → EXTI15_10_IRQn (6根线共享)你原来的Exit_Disable()用的是HAL_NVIC_DisableIRQ(EXTI15_10_IRQn)——这一关就把 bit10~bit15 全部 6 根线都瘫痪了。这就是关一个通道影响 12 个通道的原因。STM32 硬件其实有一个逐线开关在 EXTI 硬件到 NVIC 之间有一个寄存器叫IMRInterrupt Mask Register中断掩码寄存器EXTI-IMR 是一个 32 位寄存器每位对应一根 EXTI 线 bit15 bit14 bit13 bit12 bit11 bit10 bit9 bit8 ... bit0 ┌───┬───┬───┬───┬───┬───┬───┬───┐ │ 1 │ 0 │ 1 │ 0 │ 0 │ 0 │ 0 │ 0 │ ... └───┴───┴───┴───┴───┴───┴───┴───┘ ↑ ↑ ↑ │ │ └── bit131: EXTI13 放行 │ └────── bit140: EXTI14 拦截不进 NVIC └────────── bit151: EXTI15 放行每根线有自己独立的 1 bit 开关。关掉 bit14 只影响 EXTI14 这一根线EXTI15 照样能通过。这就是绕过 NVIC 共享问题的核心武器。代码里三层是怎么配合的上电时MX_GPIO_Init()第 157 行cGPIO_InitStruct.Mode GPIO_MODE_INPUT; // ← 改成普通输入把所有 16 个 INT 引脚配成INPUT。此时引脚是高阻输入能读电平但不连 EXTI 边沿检测电路EXTI 硬件根本不知道引脚上有上升沿IMR 全部为 0默认NVIC 只设了 Priority 但没 Enable结果上电后 16 路全部死的不管传感器怎么发 INT 都不会触发中断。开启通道 NExit_Init(N)第 243~264 行三步操作层层打开// 第一步把 GPIO 从 INPUT 改成 IT_RISING // → 引脚接入 EXTI 边沿检测电路能检测上升沿了 GPIO_InitStruct.Mode GPIO_MODE_IT_RISING; HAL_GPIO_Init(MIR3DA_MAP_INT[num].Port, GPIO_InitStruct); // HAL_GPIO_Init 内部会自动把 EXTI-IMR 对应 bit 置 1 // 第二步清除之前可能积攒的 pending 位 // → 假如之前有上升沿产生了但被 IMR 拦着现在开了会立刻触发——不行先清掉 __HAL_GPIO_EXTI_CLEAR_IT(pin); // 第三步使能 NVIC // → 把 CPU 的响应开关也打开如果已经开着重复调用无害 HAL_NVIC_EnableIRQ(MIR3DA_MAP_INT[num].IRQn);三层全开只有通道 N 能产生中断。其他 15 路的 GPIO 还是 INPUTEXTI 边沿检测电路根本不工作。关闭通道 NExit_Disable(N)第 272~288 行三步操作从三层全部切断// 第一步关 IMR 对应 bit // → 即使引脚上还有上升沿EXTI 硬件也不会往 NVIC 发请求了 EXTI-IMR ~pin; // 第二步清 pending 位 // → 如果之前已经有一个 pending 挂着没处理清掉它防止下次开 NVIC 时突然爆发 EXTI-PR pin; // 第三步GPIO 改回 INPUT // → 从源头切断——连边沿检测电路都不接了彻底静默 GPIO_InitStruct.Mode GPIO_MODE_INPUT; HAL_GPIO_Init(MIR3DA_MAP_INT[num].Port, GPIO_InitStruct);具体例子采通道5 时通道7 在发 INT通道5 PD15 → EXTI15通道7 PD14 → EXTI14两个共用EXTI15_10_IRQn。通道5 INT 上升沿: PD15 → EXTI 边沿检测GPIOIT_RISING ✅ → EXTI15 PR 置位 → IMR bit151 → 放行 → EXTI15_10_IRQn → NVIC已 Enable → CPU 进 EXTI15_10_IRQHandler → HAL_GPIO_EXTI_IRQHandler(INT15_Pin) 检查 PR → 有 → HAL_GPIO_EXTI_Callback → IntFlag1 ✅ 通道7 INT 上升沿: PD14 → EXTI 边沿检测GPIOINPUT ❌ 不接 → 边沿检测电路不工作 → PR 不置位 → 不进 IMR、不进 NVIC、不进 CPU ❌通道7 的信号在第一层GPIO 模式就被挡住了连 EXTI 硬件都不知道它有上升沿。退一步说即使 GPIO 是 IT_RISING比如Exit_Init之前被其他代码配过第二层 IMR bit140 也能拦住——pending 位不会传到 NVIC。一句话NVIC 是总线开关一关关一片EXTI-IMR 是分线开关一关关一根GPIO 模式是总闸从源头断开。三层叠加关通道时三层全断开通道时三层全通所以即使 NVIC 被多个通道共享也能做到只开关一个通道。svg viewBox0 0 680 560 width100% roleimg xmlnshttp://www.w3.org/2000/svg titleSTM32 EXTI 中断三层控制机制/title desc展示 GPIO 模式、EXTI-IMR 逐线掩码、NVIC 共享 IRQ 三层如何协同实现单通道中断开关/desc defs marker idarrow viewBox0 0 10 10 refX8 refY5 markerWidth6 markerHeight6 orientauto-start-reverse path dM2 1L8 5L2 9 fillnone strokecontext-stroke stroke-width1.5 stroke-linecapround stroke-linejoinround/ /marker marker idarrowStop viewBox0 0 10 10 refX8 refY5 markerWidth6 markerHeight6 orientauto-start-reverse path dM2 1L8 5L2 9 fillnone stroke#E24B4A stroke-width1.5 stroke-linecapround stroke-linejoinround/ /marker /defs !-- Title -- text x340 y26 text-anchormiddle font-size15 font-weight500 fill#26215CSTM32 EXTI 中断三层控制为什么能做到只开关一个通道/text !-- Layer 1: GPIO Mode -- rect x40 y48 width600 height86 rx12 fill#EEEDFE stroke#534AB7 stroke-width0.5/ text x56 y70 font-size13 font-weight500 fill#3C3489第一层GPIO 模式寄存器MODER/PUPDR/text rect x56 y82 width270 height42 rx8 fill#CECBF6 stroke#7F77DD stroke-width0.5/ text x68 y100 font-size12 fill#26215CGPIO_MODE_INPUT/text text x68 y115 font-size11 fill#534AB7引脚不连 EXTI 边沿检测电路/text rect x354 y82 width270 height42 rx8 fill#CECBF6 stroke#7F77DD stroke-width0.5/ text x366 y100 font-size12 fill#26215CGPIO_MODE_IT_RISING/text text x366 y115 font-size11 fill#534AB7引脚接入 EXTI 上升沿检测/text !-- Layer 2: EXTI-IMR -- rect x40 y148 width600 height86 rx12 fill#E1F5EE stroke#0F6E56 stroke-width0.5/ text x56 y170 font-size13 font-weight500 fill#04342C第二层EXTI-IMR 逐线掩码每根 EXTI 线独立 1 bit/text rect x56 y182 width270 height42 rx8 fill#9FE1CB stroke#1D9E75 stroke-width0.5/ text x68 y200 font-size12 fill#04342CEXTI-IMR | pin/text text x68 y215 font-size11 fill#0F6E56该线中断请求 → 放行/text rect x354 y182 width270 height42 rx8 fill#9FE1CB stroke#1D9E75 stroke-width0.5/ text x366 y200 font-size12 fill#04342CEXTI-IMR amp; ~pin/text text x366 y215 font-size11 fill#0F6E56该线中断请求 → 拦截其他线不受影响/text !-- Layer 3: NVIC -- rect x40 y248 width600 height86 rx12 fill#FAECE7 stroke#993C1D stroke-width0.5/ text x56 y270 font-size13 font-weight500 fill#4A1B0C第三层NVIC IRQ 使能多根 EXTI 线共享一个 IRQ 号/text rect x56 y282 width270 height42 rx8 fill#F5C4B3 stroke#D85A30 stroke-width0.5/ text x68 y300 font-size12 fill#4A1B0CHAL_NVIC_EnableIRQ(IRQn)/text text x68 y315 font-size11 fill#993C1DCPU 响应该 IRQ影响同组所有线/text rect x354 y282 width270 height42 rx8 fill#F5C4B3 stroke#D85A30 stroke-width0.5/ text x366 y300 font-size12 fill#4A1B0CHAL_NVIC_DisableIRQ(IRQn)/text text x366 y315 font-size11 fill#993C1DCPU 不响应该 IRQ同组全部瘫痪/text !-- Arrows between layers -- path dM340 134L340 148 fillnone stroke#534AB7 stroke-width1 marker-endurl(#arrow)/ path dM340 234L340 248 fillnone stroke#0F6E56 stroke-width1 marker-endurl(#arrow)/ !-- Example section -- rect x40 y350 width600 height190 rx12 fill#F1EFE8 stroke#888780 stroke-width0.5/ text x56 y372 font-size13 font-weight500 fill#2C2C2A举例采通道5PD15 → EXTI15时通道7PD14 → EXTI14也在产生 INT/text !-- Ch5 active -- rect x56 y384 width262 height56 rx8 fill#E1F5EE stroke#1D9E75 stroke-width0.5/ text x68 y402 font-size12 font-weight500 fill#04342C通道5 (PD15)/text text x68 y420 font-size11 fill#0F6E56IMR bit15 1 (开) | NVIC on/text text x68 y434 font-size11 fill#0F6E56INT 上升沿 → CPU 响应 → IntFlag1 ✅/text !-- Ch7 blocked at IMR -- rect x358 y384 width262 height56 rx8 fill#FAECE7 stroke#D85A30 stroke-width0.5/ text x370 y402 font-size12 font-weight500 fill#4A1B0C通道7 (PD14)/text text x370 y420 font-size11 fill#993C1DIMR bit14 0 (关) | NVIC on/text text x370 y434 font-size11 fill#993C1DINT 上升沿 → IMR 拦截 → 不进 CPU ❌/text !-- Key point -- rect x56 y452 width564 height76 rx8 fill#E6F1FB stroke#378ADD stroke-width0.5/ text x68 y472 font-size12 font-weight500 fill#042C53关键NVIC第三层虽然开着但 IMR第二层把通道7 拦截了/text text x68 y490 font-size11 fill#0C447CEXTI15_10_IRQn 同时覆盖 bit10~bit15但每根线有独立的 IMR 位/text text x68 y506 font-size11 fill#0C447C关 bit14 不影响 bit15 —— 这就是逐线掩码实现单通道控制的核心/text text x68 y522 font-size11 fill#0C447CExit_Disable 还额外把 GPIO 改回 INPUT从源头切断边沿检测/text /svg