【STM32】外部中断

发布于:2025-06-30 ⋅ 阅读:(20) ⋅ 点赞:(0)

STM32 外部中断(EXTI)概述

这篇文章结合示例代码,系统性地讲述 STM32 外部中断(EXTI)实验的原理、以及配置流程。目的在于辅助读者掌握STM32F1 外部中断机制。

STM32F1xx官方资料:《STM32中文参考手册V10》-第9章 中断和事件

STM32的每个IO都可以作为外部中断输入。
STM32的中断控制器支持19个外部中断/事件请求:
线0~15:对应外部IO口的输入中断。
线16:连接到PVD输出。
线17:连接到RTC闹钟事件。
线18:连接到USB唤醒事件。

每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。

从上面可以看出,STM32供IO使用的中断线只有16个,但是STM32F10x系列的IO口多达上百个,STM32F103ZET6(112),
STM32F103RCT6(51),那么中断线怎么跟io口对应呢?

在这里插入图片描述
如图所示,

GPIOx.0映射到EXTI0
GPIOx.1映射到EXTI1
…
GPIOx.15映射到EXTI15

图20:AFIO_EXTICR 映射机制图:
每个 EXTI 线可通过 AFIO 寄存器选择映射到 GPIOA~GPIOG 的某一个引脚。
例如:EXTI3 可以绑定 PE3、PC3、PB3 等,只能绑定一个。
特性 说明
可用中断线 EXTI0 ~ EXTI15(共16条 IO 线)
+ EXTI16(PVD)、EXTI17(RTC)、EXTI18(USB)
可触发方式 上升沿、下降沿、双边沿
可配置功能 中断 / 事件
IO与EXTI映射 通过 AFIO_EXTICR 寄存器设置
中断向量数量 仅有 7 个中断服务函数(EXTI0~4,EXTI9_5,EXTI15_10)
中断线与中断函数映射关系

对于每个中断线,我们可以设置相应的触发方式(上升沿触发,下降沿触发,边沿触发)以及使能。

那么,是不是16个中断线就可以分配16个中断服务函数呢?

IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数。
在这里插入图片描述
从表中可以看出,外部中断线5~9分配一个中断向量,共用一个服务函数,
外部中断线10~15分配一个中断向量,共用一个中断服务函数。

中断线 中断服务函数 是否共享中断
EXTI0 EXTI0_IRQHandler
EXTI1 EXTI1_IRQHandler
EXTI2 EXTI2_IRQHandler
EXTI3 EXTI3_IRQHandler
EXTI4 EXTI4_IRQHandler
EXTI5~9 EXTI9_5_IRQHandler 是,需区分
EXTI10~15 EXTI15_10_IRQHandler 是,需区分

另外,补充一个知识点,线16、线17、线18 是 STM32 外部中断控制器(EXTI)中,与特定内部外设连接的特殊中断线。 它们不再对应 GPIO 引脚,而是与 STM32 内部某些模块直接相关。

EXTI 特殊中断线(EXTI16 ~ EXTI18)

EXTI16 — PVD(电源电压监测器)
EXTI17 — RTC Alarm(实时时钟闹钟)
EXTI18 — USB Wakeup(USB 唤醒)

中断线编号 来源模块 名称/用途 中断触发条件 常用用途
EXTI16 PVD(电源监测) 电压检测中断 电压低于/高于设定阈值 电源掉电、低电压预警
EXTI17 RTC(实时时钟) RTC闹钟中断 RTC 到达设定闹钟时间 定时唤醒、定时事件处理
EXTI18 USB(唤醒模块) USB 唤醒中断 USB 活动信号唤醒 MCU USB 唤醒低功耗模式

外部中断库函数设置

中断服务函数列表:

EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler

EXTI_Init函数
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
typedef struct
{
  uint32_t EXTI_Line;   //指定要配置的中断线           
  EXTIMode_TypeDef EXTI_Mode;   //模式:事件 OR中断
  EXTITrigger_TypeDef EXTI_Trigger;//触发方式:上升沿/下降沿/双沿触发
  FunctionalState EXTI_LineCmd;  //使能 OR失能
}EXTI_InitTypeDef;

 EXTI_InitStructure.EXTI_Line=EXTI_Line2;	 
 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
 EXTI_InitStructure.EXTI_LineCmd = ENABLE;
 EXTI_Init(&EXTI_InitStructure);	 	

EXTI 外部中断配置步骤(官方流程)

外部中断的一般配置步骤:

① 初始化IO口为输入。
GPIO_Init();
② 开启IO口复用时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
③ 设置IO口与中断线的映射关系。
void GPIO_EXTILineConfig();
④ 初始化线上中断,设置触发条件等。
EXTI_Init();
⑤ 配置中断分组(NVIC),并使能中断。
NVIC_Init();
⑥ 编写中断服务函数。
EXTIx_IRQHandler();
⑦ 清除中断标志位
EXTI_ClearITPendingBit();

EXTI线通过 AFIO_EXTICR1~4 映射 GPIO 引脚

  • EXTI0 可映射 PA0 ~ PG0
  • EXTI15 可映射 PA15 ~ PG15

在这里插入图片描述
在这里插入图片描述

中断向量表图说明:
	仅为 EXTI0~4、EXTI9_5、EXTI15_10 提供中断服务函数。
	多线共享的服务函数需在函数内判断是哪条线路触发。
🌟 配置步骤详解(以 KEY1 按键连接 PE3 → EXTI3 为例):

① 配置 GPIO 为输入模式

GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); // 使能GPIOE时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;             // PE3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;         // 上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure);

② 使能 AFIO(复用功能模块)时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

③ 配置 EXTI 线映射(将 PE3 映射到 EXTI3)

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);

④ 配置 EXTI 中断线

EXTI_InitTypeDef EXTI_InitStructure;

EXTI_InitStructure.EXTI_Line = EXTI_Line3;                  // EXTI3
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;         // 中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;     // 下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;                   // 使能
EXTI_Init(&EXTI_InitStructure);

⑤ 配置 NVIC 中断优先级并使能中断

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;   // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;          // 响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             // 使能
NVIC_Init(&NVIC_InitStructure);

⑥ 编写中断服务函数 EXTI3_IRQHandler

void EXTI3_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line3) != RESET)
    {
        // 中断处理逻辑,比如点亮 LED
        LED1_TOGGLE();  // 示例函数,用户自定义

        EXTI_ClearITPendingBit(EXTI_Line3); // 清除中断标志位
    }
}

按键的硬件连接

战舰:
在这里插入图片描述
精英:
在这里插入图片描述
mini:
在这里插入图片描述
原理图说明(KEY0 ~ KEY2 与 PA0、PE3、PE4)(对照图解说明)

按键名称 接口引脚 对应 EXTI 线 中断函数
KEY0 PE4 EXTI4 EXTI4_IRQHandler
KEY1 PE3 EXTI3 EXTI3_IRQHandler
KEY2 PE2 EXTI2 EXTI2_IRQHandler
WK_UP PA0 EXTI0 EXTI0_IRQHandler
多个引脚使用同一个中断线时的处理(共享中断)

如图所示:
EXTI9_5_IRQHandler 处理 EXTI5EXTI9
EXTI15_10_IRQHandler 处理 EXTI10EXTI15

处理多个中断线:

void EXTI9_5_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line7) != RESET)
    {
        // 处理 EXTI7 对应按键
        EXTI_ClearITPendingBit(EXTI_Line7);
    }

    if (EXTI_GetITStatus(EXTI_Line6) != RESET)
    {
        // 处理 EXTI6 对应按键
        EXTI_ClearITPendingBit(EXTI_Line6);
    }
}

完整按键中断实验总结

📋 总体代码结构:

void KEY_Interrupt_Init(void)
{
    // 1. 初始化 GPIO
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOE, &GPIO_InitStructure);

    // 2. 映射 EXTI 线
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);

    // 3. 配置 EXTI
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line3;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    // 4. 配置 NVIC
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

综上。

步骤
1️⃣ 配置 GPIO 为输入模式(上拉/下拉)
2️⃣ 使能 AFIO 时钟
3️⃣ 使用 GPIO_EXTILineConfig() 设置 EXTI 映射
4️⃣ 使用 EXTI_Init() 配置中断线触发方式
5️⃣ 使用 NVIC_Init() 设置中断优先级与使能
6️⃣ 编写 EXTIx_IRQHandler() 并清除中断标志位

以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!


网站公告

今日签到

点亮在社区的每一天
去签到