2.外部中断(EXTI)
理论
NVIC:嵌套向量中断控制器(解释教程)
外部通用中断线(EXTI0~EXTI15):每个GPIO设置成中断模式,与中断控制器连接的线
外部中断触发方式
上升沿触发、下降沿触发、双边沿触发
外部中断触发函数
在stm32f1xx_it.c文件里(大概204行)
| 中断触发函数 |
|---|
| EXTI0_IRQHandler |
| EXTI1_IRQHandler |
| EXTI2_IRQHandler |
| EXTI3_IRQHandler |
| EXTI4_IRQHandler |
| EXTI9_5_IRQHandler |
| EXTI15_10_IRQHandler |
解析
解析初始化中断过程
//gpio.c中58/*Configure GPIO pins : PEPin PEPin */GPIO_InitStruct.Pin = EXTI_Key1_Pin|EXTI_Key2_Pin;GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); //将上面三行代码的数据传入这个函数解析初始化//stm32f1xx_hal_gpio.c中286
/*--------------------- EXTI Mode Configuration ------------------------*/
/* Configure the External Interrupt or event for the current IO */
if ((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
{
/* Enable AFIO Clock */
__HAL_RCC_AFIO_CLK_ENABLE(); //打开复用时钟
temp = AFIO->EXTICR[position >> 2u];
CLEAR_BIT(temp, (0x0Fu) << (4u * (position & 0x03u)));
SET_BIT(temp, (GPIO_GET_INDEX(GPIOx)) << (4u * (position & 0x03u)));
AFIO->EXTICR[position >> 2u] = temp; //把固定引脚设置成复用模式(如复用成外部中断)//配置上升沿还是下降沿
/* Enable or disable the rising trigger */
if ((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
{SET_BIT(EXTI->RTSR, iocurrent);
}
else
{CLEAR_BIT(EXTI->RTSR, iocurrent);
}/* Enable or disable the falling trigger */
if ((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
{SET_BIT(EXTI->FTSR, iocurrent);
}
else
{CLEAR_BIT(EXTI->FTSR, iocurrent);
}/* Configure the event mask */
if ((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
{SET_BIT(EXTI->EMR, iocurrent);
}
else
{CLEAR_BIT(EXTI->EMR, iocurrent);
}//打开或关闭中断
/* Configure the interrupt mask */
if ((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
{SET_BIT(EXTI->IMR, iocurrent);
}
else
{CLEAR_BIT(EXTI->IMR, iocurrent);
}
中断实现过程
- 确认中断
- 清除中断标志位
- 执行中断回调函数

//stm32f1xx_it.:大概204行
void EXTI3_IRQHandler(void) //中断入口函数
{/* USER CODE BEGIN EXTI3_IRQn 0 *//* USER CODE END EXTI3_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(EXTI_Key1_Pin); //在库函数不能写/* USER CODE BEGIN EXTI3_IRQn 1 *//* USER CODE END EXTI3_IRQn 1 */
}void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) //stm32f1xx_hal_gpio.c:大概546行
{/* EXTI line interrupt detected */if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u) //判断有没有中断触发(有:1,没:0){__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); //若进来则为1,为1则清除中断标志位HAL_GPIO_EXTI_Callback(GPIO_Pin); //回调函数(Callback),执行函数}
}//stm32f1xx_hal_gpio.h中190
#define __HAL_GPIO_EXTI_GET_IT(__EXTI_LINE__) (EXTI->PR & (__EXTI_LINE__)) //挂起寄存器(EXTI_PR)(参考手册140) 有没有中断触发//stm32f1xx_hal_gpio.h中198
#define __HAL_GPIO_EXTI_CLEAR_IT(__EXTI_LINE__) (EXTI->PR = (__EXTI_LINE__)) //赋值,(参考手册140)//调用这个函数,__weak:弱声明,若别文件也有相同的函数,优先调用没有弱声明
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //stm32f1xx_hal_gpio.c:大概561行
{/* Prevent unused argument(s) compilation warning */UNUSED(GPIO_Pin);/* NOTE: This function Should not be modified, when the callback is needed,the HAL_GPIO_EXTI_Callback could be implemented in the user file*/
}
若相同有一个PA0设置了中断,别的PB0等等都不能设置成中断

代码编写
实验:按键PE3控制蜂鸣器(PB8)、按键PE4控制LED灯(PB5)
Cube IDE代码
Cube IDE中编写
LED灯、蜂鸣器、按键配置
LED灯、蜂鸣器配置,上一篇已经说过,地址
按键设置下降沿触发(也可上升沿触发),GPIO Pull-up/Pull-down:设置上拉,空闲状态为高电平
按键没按下时高电平,按下时有下降沿和上升沿,所以两个触发都可,按键这里是中断触发功能,不是GPIO输入功能

配置NVIC(嵌套向量中断控制器)

调节不同中断优先级(数字越小优先级越高)
若抢占优先级相同,比较子优先级

调节多少bit对应代码在:
HAL_Init(); //main.c(74)//HAL_StatusTypeDef HAL_Init(void)中的
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); //stm32f1xx_hal.c(157)
代码
main.c:144行(在mian函数外任意一个 /* USER CODE BEGIN / / USER CODE END */中)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{//若需要延时需要将延时中断优先级比外部中断优先级高,优先级高才可以打断低优先级HAL_Delay(10);if(HAL_GPIO_ReadPin(EXTI_Key1_GPIO_Port, EXTI_Key1_Pin) == 0) //读引脚,相同=0,不同=1{HAL_GPIO_TogglePin(BEEP_GPIO_Port, BEEP_Pin);}if(HAL_GPIO_ReadPin(EXTI_Key2_GPIO_Port, EXTI_Key2_Pin) == 0){HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);}
}
中断处理程序要少用延时的原因
中断处理的要求是即时处理,尽快退出。如果在中断中使用延时函数或者使用IO阻塞函数,会影响到系统的实时性。如果下次中断来临,延时或者阻塞还没结束,那么就永远在中断里死循环了。
因此,对于中断处理程序的要求是:
短小精悍,不要处理过多任务
不使用延时函数或者IO阻塞的函数
Keil代码
需要修改的地方如下:
mian.c(144)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{//若需要延时需要将延时中断优先级比外部中断优先级高,优先级高才可以打断低优先级HAL_Delay(10);if(HAL_GPIO_ReadPin(EXTI_Key1_GPIO_Port, EXTI_Key1_Pin) == 0) //读引脚,相同=0,不同=1{HAL_GPIO_TogglePin(BEEP_GPIO_Port, BEEP_Pin);}if(HAL_GPIO_ReadPin(EXTI_Key2_GPIO_Port, EXTI_Key2_Pin) == 0){HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);}
}
main.h(60)
#define EXTI_Key1_Pin GPIO_PIN_3
#define EXTI_Key1_GPIO_Port GPIOE
#define EXTI_Key1_EXTI_IRQn EXTI3_IRQn
#define EXTI_Key2_Pin GPIO_PIN_4
#define EXTI_Key2_GPIO_Port GPIOE
#define EXTI_Key2_EXTI_IRQn EXTI4_IRQn
#define LED1_Pin GPIO_PIN_5
#define LED1_GPIO_Port GPIOB
#define BEEP_Pin GPIO_PIN_8
#define BEEP_GPIO_Port GPIOB
gpio.c(42)
void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOE_CLK_ENABLE();__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);/*Configure GPIO pins : PEPin PEPin */GPIO_InitStruct.Pin = EXTI_Key1_Pin|EXTI_Key2_Pin;GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);/*Configure GPIO pins : PBPin PBPin */GPIO_InitStruct.Pin = LED1_Pin|BEEP_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* EXTI interrupt init*/HAL_NVIC_SetPriority(EXTI3_IRQn, 5, 0);HAL_NVIC_EnableIRQ(EXTI3_IRQn);HAL_NVIC_SetPriority(EXTI4_IRQn, 5, 0);HAL_NVIC_EnableIRQ(EXTI4_IRQn);
}
stm32f1xx_hal_it.c(204)
void EXTI3_IRQHandler(void)
{/* USER CODE BEGIN EXTI3_IRQn 0 *//* USER CODE END EXTI3_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(EXTI_Key1_Pin);/* USER CODE BEGIN EXTI3_IRQn 1 *//* USER CODE END EXTI3_IRQn 1 */
}void EXTI4_IRQHandler(void)
{/* USER CODE BEGIN EXTI4_IRQn 0 *//* USER CODE END EXTI4_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(EXTI_Key2_Pin);/* USER CODE BEGIN EXTI4_IRQn 1 *//* USER CODE END EXTI4_IRQn 1 */
}
修改延时中断优先级
HAL_Init(); //main.c(74)//HAL_StatusTypeDef HAL_Init(void)中的
HAL_InitTick(TICK_INT_PRIORITY); //stm32f1xx_hal.c(160)//进入参数里修改
#define TICK_INT_PRIORITY 1U //stm32f1xx_hal_conf.h(132)
相关文章:
2.外部中断(EXTI)
理论 NVIC:嵌套向量中断控制器(解释教程) 外部通用中断线(EXTI0~EXTI15):每个GPIO设置成中断模式,与中断控制器连接的线 外部中断触发方式 上升沿触发、下降沿触发、双边沿触发 外部中断触发函数 在stm32f1xx_it.c文件…...
Python | SyntaxError: invalid syntax 深度解析
Python | SyntaxError: invalid syntax 深度解析 在Python编程中,SyntaxError: invalid syntax是一个常见的错误,它表明Python解释器在尝试解析代码时遇到了语法问题。这个错误通常是由于代码中存在拼写错误、缺少符号(如括号、冒号或逗号&a…...
付费进群系统源码原版最新修复全开源版
付费进群,和平时所见到的别人拉你进群是不一样的,付费进群需要先缴费以后,才会看到群的二维码,扫码进群或者是长按二维码图片识别进群,付费进群这个功能广泛应用于拼多多的砍价群,活动的助力群,…...
Docker容器部署的SpringBoot项目jar包,上传文件但是找不到路径的问题
在docker容器内部署的jar包运行后,请求访问都没有问题,在文件上传时,发现上传图片接口响应成功,但是图片路径报404错误,发现找不到路径。 在服务器上查看也没有找到相关图片。 原因: 启动docker镜像时没…...
云计算学习——5G网络技术
系列文章目录 提示:仅用于个人学习,进行查漏补缺使用。 Day1 网络参考模型 Day2 网络综合布线与应用 Day3 IP地址 Day4 华为eNSP网络设备模拟器的基础安装及简单使用 Day5 交换机的基本原理与配置 Day6 路由器的原理与配置 Day7 网络层协议介绍一 Day8 传…...
matlab仿真 信道编码和交织(上)
(内容源自详解MATLAB/SIMULINK 通信系统建模与仿真 刘学勇编著第八章内容,有兴趣的读者请阅读原书) clear all N10;%信息比特的行数 n7;%hamming码组长度n2^m-1 m3;%监督位长度 [H,G]hammgen(m);%产生(n,n-…...
基于YOLOv8的高压输电线路异物检测系统
基于YOLOv8的高压输电线路异物检测系统 (价格88) 包含 【“鸟窝”,“风筝”,“气球”,“垃圾”】 4个类 通过PYQT构建UI界面,包含图片检测,视频检测,摄像头实时检测。 (该系统可以根据数…...
23款奔驰GLS450加装原厂电吸门配置,提升车辆舒适性和便利性
今天是一台22款奔驰GLS450,车主是佛山的 以前被不良商家坑了 装了副厂的电吸门 刚开始就很正常 用了半年之后 就开始开不了门,被锁在里面,刚开始车主以为是零件坏了 后来越来越频繁,本来是为了家里老人小孩关门方便而升级的&#…...
git操作流程笔记
1、在本地项目文件夹右击鼠标点击Git Bash Here 2、输入git init,这个目录变成git可以管理的仓库,会出现一个.git文件夹,如果没出现的话需要选择“显示隐藏文件”(不会的同学自行百度一下) 3、绑定本地仓库与远程仓库…...
【QT】常用控件-上
欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 目录 👉🏻QWidgetenabledgeometryrect制作上下左右按钮 window frame 的影响window titlewindowIcon代码示例: 通过 qrc 管理图片作为图标 windowOpacitycursor使用qrc自…...
帮助网站提升用户参与度的5个WordPress插件
仅靠编写精彩的内容、设计精美的图像和创建简化的客户旅程不足以提高网站参与度。您需要让用户在首次访问后继续与您的网站互动并成为回访者,才能真正吸引您所追求的兴趣。 幸运的是,对于 WordPress 用户来说,有数百种工具可用于提高用户参与…...
理解 Python 中的 @wraps:保留函数元数据
一.介绍 在本文中,我们将了解 wraps。在 Python 中使用装饰器时,您可能会遇到原始函数的元数据丢失的情况。这时,functools 模块中的 wraps 装饰器就可以派上用场了。让我们深入了解 wraps 的作用及其重要性。 二.简单装饰器的问题 首先&a…...
cjson
文章目录 概述编译cjson_test 小结 概述 在网络传输中,网络数据序列化,常用的有那么几种,json,protobuf都是很常用的,这一篇来写下json。 Json常用的有几个,rapidjson,jsoncpp,还有…...
Docker data root 目录更改
有时候受限于系统根目录空间的限制,需要将 docker data root 目录更改为其它目录,如单独挂载一个磁盘或存储。本篇文章介绍如何操作。 修改docker 工作目录 修改配置文件/etc/docker/daemon.json(在19.x 版本之前使用grapth) {&q…...
[CR]厚云填补_SEGDNet
Structure-transferring edge-enhanced grid dehazing network Abstract 在过去的二十年里,图像去雾问题在计算机视觉界受到了极大的关注。在雾霾条件下,由于空气中水汽和粉尘颗粒的散射,图像的清晰度严重降低,使得许多计算机视觉…...
图-基础概念
是什么 图是一种抽象的数据类型,在图中的数据元素通常称作节点,V是所以定点的集合,E是所有边的集合 图的分类 有向图 如果两个订单v,w,只能由v向w,而不能w向v,那么我们就把何种情况叫做一个从…...
Javascript前端基础面试(十)
MVVM Vue MVVM这一篇就够啦!_vue r mvvm-CSDN博客 点容器内的图标,图标边框变成border 1px solid red,点空白处重置 <div id"container"> <img src"icon.png" alt"Icon" class"icon"> <!…...
书生大模型实战营闯关记录----第五关:LlamaIndex+Internlm2 RAG实践Demo:效果对比,文档加载,向量库构建,检索器,模型推理
文章目录 1. 前置知识RAG背景RAG 效果比对 2. 环境、模型准备2.1 配置基础环境2.2 安装 Python环境和依赖包2.3 下载 Sentence Transformer 模型2.4 下载 NLTK 相关资源 3. LlamaIndex HuggingFaceLLM4. LlamaIndex RAG加载文档构建向量存储索引库检索器RAG代码 5. LlamaIndex …...
如何使用极狐GitLab CI/CD Component Catalog?【上】
极狐GitLab 是 GitLab 在中国的发行版,专门面向中国程序员和企业提供企业级一体化 DevOps 平台,用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规,而且所有的操作都是在一个平台上进行,省事省心省钱。可以一键安装极狐GitL…...
详解Xilinx FPGA高速串行收发器GTX/GTP(3)--GTX的时钟架构
目录 1、参考时钟 2、时钟方案 2.1、单个外部参考时钟驱动单个QUAD中的多个transceiver 2.2、单个外部参考时钟驱动多个QUAD中的多个transceiver 2.3、同一个Quad中,多个GTX Transceiver使用多个参考时钟 2.4、不同Quad中,多个GTX Transceiver 使用多个参考时钟 3、QP…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
