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

中断实现过程

  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)
  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
外部中断(External Interrupt,EXTI)是一种特殊的中断方式,它由外部信号触发。在处理器中,外部中断通常由中断控制器(Interrupt Controller)实现。 在STM32系列微控制器中,外部中断的硬件功能结构如下: 1. 输入信号:外部中断的输入信号由GPIO引脚提供,可以选择其中任何一个GPIO引脚作为外部中断输入。 2. 中断线路:输入信号经过GPIO中断线路进入中断控制器。 3. 中断控制器:中断控制器是STM32微控制器的核心部件之一,它负责管理所有中断请求,并将其分配给相应的中断服务程序(Interrupt Service Routine,ISR)进行处理。在外部中断的情况下,中断控制器会根据输入信号的来源和中断优先级等信息来确定相应的中断服务程序。 4. 中断服务程序:中断服务程序是处理中断请求的代码。当中断控制器分配一个中断请求给中断服务程序时,该程序会立即开始执行,以响应中断请求,完成相应的操作。在外部中断的情况下,中断服务程序可以读取输入信号的状态,执行相应的操作,然后返回主程序。 5. NVIC:NVIC(Nested Vectored Interrupt Controller)是STM32微控制器的中断控制器,它负责管理所有中断请求,并将其分配给相应的中断服务程序进行处理。NVIC支持嵌套中断,可以同时处理多个中断请求。在外部中断的情况下,NVIC会根据输入信号的来源和中断优先级等信息来确定相应的中断服务程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星仔_X

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值