2.外部中断(EXTI)

news2025/1/23 13:03:17

理论

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);
}

中断实现过程

  1. 确认中断
  2. 清除中断标志位
  3. 执行中断回调函数

图示

//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(嵌套向量中断控制器)

配置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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1978097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AI作图:奥运会游泳冠军】

画一个&#xff1a;水花&#xff0c;上半身&#xff0c;游泳冠军&#xff0c;泳池背景&#xff0c;面部明亮&#xff0c;眼神光&#xff0c;亚洲运动员&#xff0c;超高品质&#xff0c;真人&#xff0c;完美容颜&#xff0c;健美&#xff0c;健身&#xff0c;身材娇好&#xf…

Jackson常用注解详解

Hi &#x1f44b;, Im shy 有人见尘埃&#xff0c;有人见星辰 Jackson常用注解详解 文章目录 Jackson常用注解详解0. 引入依赖1. JsonProperty2. JsonIgnore3. JsonFormat4. JsonInclude5. JsonCreator6. JsonValue7. JsonIgnoreProperties结论 Jackson是Java生态系统中广泛…

例题:使用一条命令将xxx目录下除了xx子目录之外的文件全部删除(find、管道、grep、exec)

文章目录 例题&#xff1a;删除xx子目录以外的所有目录和文件需求方式一方式二 例题&#xff1a;删除xx子目录以外的所有目录和文件 需求 使用一条命令将/opt目录下除了rh子目录之外的文件全部删除 [rootlocalhost opt]# cp /var/log/vm* /opt/ [rootlocalhost opt]# mkdir …

(一)循环依赖,你真的懂了吗?万字解析循环依赖底层原理 - 什么是Bean循环依赖?Spring是如何解决的?二级缓存可以解决吗?遇到相关报错如何处理?

theme: vuepress 一、相关知识点简介 Spring Boot是基于Spring框架的一个快速开发平台&#xff0c;旨在简化Spring应用的创建和部署。通过提供一系列开箱即用的默认配置和自动化工具&#xff0c;Spring Boot使开发者能够专注于业务逻辑&#xff0c;而无需处理复杂的配置和依赖…

【Python机器学习】支持向量机——在复杂数据上应用核函数

上图中&#xff0c;数据中存在某种可以识别的模式&#xff0c;其中一个问题就是&#xff1a;我们能否想线性情况一样&#xff0c;利用强大的工具来捕捉数据中的这种模式&#xff1f; 利用核函数将数据映射到高维空间 在上图中&#xff0c;数据点处于一个圆中&#xff0c;人类…

《零散知识点 · 自定义 HandleMapping》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

[独家原创] CPO-RBF多特征分类预测 优化宽度+中心值+连接权值 (多输入单输出)Matlab代码

[独家原创] CPO-RBF多特征分类预测 优化宽度中心值连接权值 &#xff08;多输入单输出&#xff09;Matlab代码 目录 [独家原创] CPO-RBF多特征分类预测 优化宽度中心值连接权值 &#xff08;多输入单输出&#xff09;Matlab代码效果一览基本介绍程序设计参考资料 效果一览 基本…

算法--初阶

1、tips 1.1、set求交集 {1,2,3} & {2,3} & {1,2} {2} 其实就是位运算&#xff0c; 只有set可以这样使用&#xff0c; list没有这种用法 {1,2,3} | {2,3, 4} | {1,2} {1, 2, 3, 4} 并集 1.2、*与** * 序列(列表、元组)解包&#xff0c;如果是字典&#xff0c;那…

15.75.【C语言】表达式求值

目录 一.整型提升 1.定义 2. 一.整型提升 1.定义 C语言中整型算术运算总是至少以缺省&#xff08;默认&#xff09;整型类型的精度来进行的。为了获得这个精度&#xff0c;表达式中的字符和短整型操作数在使用之前被转换为普通整型&#xff0c;这种转换称为整型提升 2.整型提…

C++初学者指南-5.标准库(第二部分)--移除元素算法

C初学者指南-5.标准库(第二部分)–移除元素算法 文章目录 C初学者指南-5.标准库(第二部分)--移除元素算法remove / remove_ifremove_copy / remove_copy_ifunique / unique_copyerase / erase_if相关内容 不熟悉 C 的标准库算法&#xff1f; ⇒ 简介 remove / remove…

还有谁分不清Oracle认证里的OCA、OCP、OCM?

在IT行业&#xff0c;Oracle认证是许多专业人士提升技能和职业竞争力的重要途径。 Oracle认证是一套由Oracle公司提供的全球认可的专业资格认证体系&#xff0c;旨在证明个人在Oracle数据库及相关技术领域的专业技能和知识水平。 Oracle认证作为数据库认证中的天花板&#xff0…

目标检测——GDXray数据集转为YOLO格式

关于该数据集的介绍可以看我写的另一篇博客&#xff1a;链接 论文题目&#xff1a;《GDXray: The Database of X-ray Images for Nondestructive Testing》论文链接&#xff1a;https://link.springer.com/article/10.1007/s10921-015-0315-7 Github链接&#xff1a; https:…

JavaScript小本本|JavaScript 对象方法定义的演变

在微信中阅读&#xff0c;欢迎关注公众号&#xff1a;CodeFit。 创作不易&#xff0c;如果你觉得这篇文章对您有帮助&#xff0c;请不要忘了 点赞、分享 和 关注&#xff0c;为我的 持续创作 提供 动力&#xff01; 欢迎订阅《Vue 3.x 必修课&#xff5c;2024》&#xff1a;htt…

JAVA项目基于SpringBoot的外卖点餐管理系统

目录 一、前言 二、技术介绍 三、系统实现 四、论文参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着生活节…

C++20中的模块

大多数C项目使用多个翻译单元(translation units)&#xff0c;因此它们需要在这些单元之间共享声明和定义(share declarations and definitions)。headers的使用在这方面非常突出。模块(module)是一种language feature&#xff0c;用于在翻译单元之间共享声明和定义。它们是某些…

追问试面试系列:Dubbo

欢迎来到Dubbo系列,在面试中被问到Dubbo相关的问题时,大部分都是简历上写了Dubbo,或者面试官想尝试问问你对Dubbo是否了解。 本系列主要是针对面试官通过一个点就使劲儿往下问的情况。 面试官:说说你们项目亮点 好的面试官 我们这个项目的技术亮点在于采用了Spring Cloud…

正点原子imx6ull-mini-Linux驱动之Linux I2C 驱动实验(21)

I2C 是很常用的一个串行通信接口&#xff0c;用于连接各种外设、传感器等器件&#xff0c;在裸机篇已经对 I.MX6U 的 I2C 接口做了详细的讲解。本章我们来学习一下如何在 Linux 下开发 I2C 接口器件 驱动&#xff0c;重点是学习 Linux 下的 I2C 驱动框架&#xff0c;按照指定的…

人工智能深度学习系列—探索Jaccard相似度损失:图像分割领域的新利器

文章目录 1. 背景介绍2. Loss计算公式3. 使用场景4. 代码样例5. 总结 1. 背景介绍 在深度学习的各种应用中&#xff0c;图像分割是一项极具挑战性的任务。Jaccard相似度损失&#xff08;Jaccard Similarity Loss&#xff09;&#xff0c;又称为IoU损失&#xff08;Intersectio…

计算机基本理论与程序运行原理概述

目录 计算机的基本表示方法 计算机的组成 程序运行的原理 指令执行的流水线 编译原理 个人理解 面试题总结 计算机的基本表示方法 计算机系统使用高、低电平来表示逻辑1和0。数据在计算机中的存储、传输和处理均以二进制形式进行。数据通过总线作为电信号进行传输&…

Es6常用的一些数组处理方法

在平时的开发中&#xff0c;我们很多时候用到数组结构数据&#xff0c;那么如何高效处理数组是可以提高开发效率的&#xff0c;现在越来越多人使用es6&#xff0c;那么它的很多方法简化了我们对数据的操作&#xff0c;比如以前数组循环用for循环写比较多的代码&#xff0c;现在…