当前位置: 首页 > 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.lryc.cn/news/575375.html

相关文章:

  • 【C++11】右值引用和移动语义
  • gRPC 使用(python 版本)
  • 2025学年湖北省职业院校技能大赛 “信息安全管理与评估”赛项 样题卷(五)
  • Axure版TDesign 组件库-免费版
  • MQTT 和 HTTP 有什么本质区别?
  • 如何将 Memfault 固件 SDK 集成到使用 Nordic 的 nRF Connect SDK(NCS)的项目中
  • 数据结构进阶 - 第四,五章 串、数组和广义表
  • Docker 入门教程(一):从概念到第一个容器
  • 水质指数预测模型R²偏低的原因分析与优化策略
  • 2-深度学习挖短线股-1-股票范围选择
  • uniapp微信小程序:editor组件placeholder字体样式修改
  • vue3 + elementPlus 封装hook,检测form表单数据修改变更;示例用 script setup 语法使用
  • SpringBoot项目快速开发框架JeecgBoot——Web处理!
  • 一次开发,多端适配!全面掌握Dioxus跨平台开发框架!
  • 远程玩3A大作要多少帧?ToDesk、向日葵、UU远程性能对决
  • 面试破局:告别流水账,用“故事思维”重塑自我介绍
  • rocketmq中broker和namesrv的区别和联系?
  • 川翔云电脑全新上线:三维行业高效云端算力新选择
  • 智能化监管:微算法科技(NASDAQ:MLGO)比特币社区分类器助力加密货币市场规范发展
  • CRON表达式编辑器与定时任务实现技术文档
  • 阿里云ACP-检索分析服务
  • fnm node包管理器
  • 《解锁FFmpeg - python:开启多媒体处理新时代》
  • GNSS位移监测站在大坝安全中的用处
  • Lynx vs React Native vs Flutter 全面对比:三大跨端框架实测分析
  • PAT A 1052 Linked List Sorting
  • 解决uniapp vue3版本封装组件后:deep()样式穿透不生效的问题
  • ZYNQ GP总线深度实战:智能灯光控制器的PS-PL交互艺术
  • Python 惰性求值实战:用生成器重构 Sentence 类
  • 从HTML4到HTML5+CSS3,如何快速掌握?(有老版HTML基础或经验)