📖 第 16 章:外部中断实验(External Interrupt)

🔧 正点原子《DMF407 开发指南》V1.0 · Chapter 16
🗨️ 「中断让 CPU 不再傻等:有事叫我,没事我睡觉。」
这一章在干嘛? 外部中断实验:NVIC 优先级分组、EXTI 配置、中断服务函数、按键中断触发 LED。理解后所有外设中断(串口/TIM/ADC)都有思路。
16.1 NVIC 和 EXTI 简介16.2 硬件设计16.3 程序设计16.4 下载验证

16.1 NVIC 和 EXTI 简介

16.1.1 NVIC 嵌套向量中断控制器

Cortex-M4 内核自带 NVIC,支持 256 个中断。F407 用了 82 个:

NVIC 中断优先级:

优先级分组抢占优先级位数子优先级位数常用范围
00 bit4 bit0
11 bit3 bit0~1
22 bit2 bit0~3
33 bit1 bit0~7
44 bit0 bit0~15

原书图 16.1.1.1:NVIC 中断优先级分组
原书图 16.1.1.1:NVIC 中断优先级分组

推荐分组 2(2 bit 抢占 + 2 bit 子),既支持嵌套又不复杂。

16.1.2 EXTI 外部中断

EXTI(External Interrupt)负责把 IO 电平变化转换为 NVIC 中断。

线路来源
EXTI0~EXTI15GPIOx_Pin0~15
EXTI16PVD 输出
EXTI17RTC 闹钟
EXTI18USB OTG_FS 唤醒
EXTI21RTC Tamper / TimeStamp
EXTI22RTC Wakeup

每条 EXTI 只能连接到一个 GPIO 的一个 pin,例如 EXTI0 可绑 PA0/PB0/.../PI0 中任意一个。

16.2 硬件设计

使用 KEY0/KEY1/KEY_UP 接 PE4/PE3/PA0 作外部中断触发。LED0/LED1 接 PF9/PF10 作中断响应。

16.3 程序设计

16.3.1 编程步骤

  1. 开启 GPIOE / GPIOA / SYSCFG 时钟;
  2. 配置 GPIO 为输入模式;
  3. HAL_NVIC_EnableIRQ(EXTI4_IRQn); HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0); 设置优先级;
  4. HAL_GPIO_Init 的 Mode 设为 GPIO_MODE_IT_FALLING(下降沿触发);
  5. 中断服务函数 EXTI4_IRQHandler → 调 HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4) → 回调 HAL_GPIO_EXTI_Callback

16.3.2 关键代码

void EXTI4_IRQHandler(void) {
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    delay_ms(20);
    if (GPIO_Pin == GPIO_PIN_4) {    // KEY0
        if (KEY0 == 0) LED0_TOGGLE();
    }
}

原书图 16.3.2.1:外部中断触发流程图
原书图 16.3.2.1:外部中断触发流程图

中断里能做的事有限:不要调 HAL_Delay(SysTick 中断可能与 EXTI 中断冲突),用定时器延时;不要做耗时操作,只置标志位让 main 处理。

16.4 下载验证

按 KEY0 → LED0 翻转;KEY_UP → LED1 翻转。CPU 平时可做其他事,按下时才被「唤醒」。

中断标志位模式 最佳实践:中断回调里只 g_key0_pressed = 1; 在 main 里循环检查再处理。

🧠 小测验
抢占优先级与响应优先级的区别?
抢占可嵌套(高打断低),同抢占时响应决定顺序。
EXTI0 可以同时绑定 PA0 和 PB0 吗?
不能,每个 EXTI 编号只能绑一个 IO。
为什么中断里不能调 HAL_Delay?
HAL_Delay 依赖 SysTick 中断,而 EXTI 中断可能抢占 SysTick,导致卡死。
← 上一篇🏠 顶层目录下一篇 →