当前位置: 首页 > news >正文

【STM32】外部中断

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分配一个中断向量,共用一个中断服务函数。

中断线中断服务函数是否共享中断
EXTI0EXTI0_IRQHandler
EXTI1EXTI1_IRQHandler
EXTI2EXTI2_IRQHandler
EXTI3EXTI3_IRQHandler
EXTI4EXTI4_IRQHandler
EXTI5~9EXTI9_5_IRQHandler是,需区分
EXTI10~15EXTI15_10_IRQHandler是,需区分

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

EXTI 特殊中断线(EXTI16 ~ EXTI18)

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

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

外部中断库函数设置

中断服务函数列表:

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){// 中断处理逻辑,比如点亮 LEDLED1_TOGGLE();  // 示例函数,用户自定义EXTI_ClearITPendingBit(EXTI_Line3); // 清除中断标志位}
}

按键的硬件连接

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

按键名称接口引脚对应 EXTI 线中断函数
KEY0PE4EXTI4EXTI4_IRQHandler
KEY1PE3EXTI3EXTI3_IRQHandler
KEY2PE2EXTI2EXTI2_IRQHandler
WK_UPPA0EXTI0EXTI0_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. 初始化 GPIORCC_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. 配置 EXTIEXTI_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. 配置 NVICNVIC_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() 并清除中断标志位

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

http://www.xdnf.cn/news/1070605.html

相关文章:

  • 【Linux】基础开发工具(2)
  • java枚举enum的使用示例
  • 大厂测开实习和小厂开发实习怎么选
  • Java设计模式->责任链模式的介绍
  • [AI]从0到1通过神经网络训练模型
  • python+requests接口自动化测试
  • 《规则怪谈》合集
  • [特殊字符]️ 用 Python 绘制专业风玫瑰图:从气象数据到可视化的全流程指南
  • vscode ssh远程连接到Linux并实现免密码登录
  • Apipost和Postman对比
  • 缓存与加速技术实践-MongoDB数据库应用
  • 【RESTful接口设计规范全解析】URL路径设计 + 动词名词区分 + 状态码 + 返回值结构 + 最佳实践 + 新手常见误区汇总
  • Python打卡:Day37
  • 算法打卡 day4
  • Spring Boot 项目中同时使用 Swagger 和 Javadoc 的完整指南
  • Selenium+Pytest自动化测试框架实战
  • 快速傅里叶变换(FFT)是什么?
  • uniapp微信小程序:editor组件placeholder字体样式修改
  • GC 学习笔记
  • 新手向:Neo4j的安装与使用
  • ubuntu22.04系统kubeadm部署k8s高可用集群
  • Redis核心知识详解:从全局命令到高级数据结构
  • 多相机人脸扫描设备如何助力高效打造数字教育孪生体?
  • 第一章-人工智能概述-机器学习基础与应用(1/36)
  • 地震资料处理——(七)地震偏移处理
  • spring-ai 1.0.0 (1)模型调用能力
  • Linux命令与脚本:高效系统管理的双刃剑
  • 自动化测试--app自动化测试之给手机设置锁屏图案
  • 【stm32】HAL库开发——CubeMX配置外部中断和配置PWM
  • 多租户多会话隔离存储架构的完整实现方案