cubemx—EXTI外部中断

文章详细介绍了如何在STM32系统中配置GPIO外部中断EXTI,包括选择中断线、触发模式(下降沿、上升沿或两者),以及NVIC中断优先级设置。在HAL库中,通过HAL_GPIO_EXTI_Callback()回调函数处理中断事件,提供了一种统一处理多个中断的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 EXTI外部中断

1.在 System Core 中选择 GPIO 设置。

请添加图片描述
在右边图中找到按键对应引脚,选择 GPIO_EXTIx。
这里的 x 是指挂载在中断线几上,如 GPIO_EXTI0 就是挂载在中断线0上。请添加图片描述
开启下降沿触发中断:即在 按下按键时 电平由高变为低时触发,则在 GPIO mode 中选择 External Interrupt Mode with Falling edge trigger detection

开启上升沿触发中断:即在 按下按键后松开时 电平由低变为高时触发,则在 GPIO mode 中选择 External Interrupt Mode with Rising edge trigger detection

开启下降沿上升沿都触发中断:即在 按下时触发,松开时再次触发,则在 GPIO mode 中选择 External Interrupt Mode with Rising/Falling edge trigger detection

如果硬件上已外部上拉或下拉,则在GPIO Pull-up/Pull-down 中选择 No pull-up and no pull-down 既不上拉也不下拉。

如果硬件外部没有上拉,则在GPIO Pull-up/Pull-down 中选择 Pull-up 内部上拉电阻。
请添加图片描述
配置 NVIC
中断优先级分组规则 Priority Group 默认为4个比特位,一般情况下不改。
勾选刚刚配置的外部中断线0和13,并配置抢占优先级 Preemption Priority 和响应优先级 Sub Priority。

抢占优先级,数字越小,优先级越高
若抢占优先级相同,判断子优先级,同样,数字越小,优先级越高
请添加图片描述

配置 NVIC

中断优先级分组规则 Priority Group 默认为4个比特位,一般情况下不改。
勾选刚刚配置的外部中断线0和13,并配置抢占优先级 Preemption Priority 和响应优先级 Sub Priority。

抢占优先级,数字越小,优先级越高
若抢占优先级相同,判断子优先级,同样,数字越小,优先级越高

打开 stm32f1xx_it.c 中断服务函数文件,找到 EXTI0 中断的服务函数 EXTI0_IRQHandler()
中断服务函数里面就调用了 GPIO 外部中断处理函数 HAL_GPIO_EXTI_IRQHandler()

请添加图片描述
打开 stm32f1xx_hal_gpio.c 文件,找到外部中断处理函数原型 HAL_GPIO_EXTI_IRQHandler(),其主要作用就是判断是几号线中断,清除中断标识位,然后调用中断回调函数 HAL_GPIO_EXTI_Callback()。请添加图片描述
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/

HAL_GPIO_EXTI_Callback() 按照官方提示我们应该再次定义该函数,__weak 是一个弱化标识,带有这个的函数就是一个弱化函数,就是你可以在其他地方写一个名称和参数都一模一样的函数,编译器就会忽略这一个函数,而去执行你写的那个函数;而 UNUSED(GPIO_Pin) ,这就是一个防报错的定义,当传进来的GPIO端口号没有做任何处理的时候,编译器也不会报出警告。其实我们在开发的时候已经不需要去理会中断服务函数了,只需要找到这个中断回调函数并将其重写即可而这个回调函数还有一点非常便利的地方这里没有体现出来,就是当同时有多个中断使能的时候,STM32CubeMX会自动地将几个中断的服务函数规整到一起并调用一个回调函数,也就是无论几个中断,我们只需要重写一个回调函并判断传进来的端口号即可。

接下来我们就在 stm32f1xx_it.c 这个文件的最下面添加 HAL_GPIO_EXTI_Callback()

/* USER CODE BEGIN 1 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin==KEY1_Pin)
	{
        // 自定义应用程序
        HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
	}
}
/* USER CODE END 1 */

2.3 HAL库与标准库代码比较
STM32CubeMX 使用 HAL 库生成的代码:

#define KEY2_Pin GPIO_PIN_13
#define KEY2_GPIO_Port GPIOC
#define KEY2_EXTI_IRQn EXTI15_10_IRQn
#define KEY1_Pin GPIO_PIN_0
#define KEY1_GPIO_Port GPIOA
#define KEY1_EXTI_IRQn EXTI0_IRQn

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    /*Configure GPIO pin : KEY2_Pin */
    GPIO_InitStruct.Pin = KEY2_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStruct);

    /*Configure GPIO pin : KEY1_Pin */
    GPIO_InitStruct.Pin = KEY1_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);

    /* EXTI interrupt init*/
    HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);

    HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}

/**
  * @brief This function handles EXTI line0 interrupt.
  */
void EXTI0_IRQHandler(void)
{
    /* USER CODE BEGIN EXTI0_IRQn 0 */

    /* USER CODE END EXTI0_IRQn 0 */
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
    /* USER CODE BEGIN EXTI0_IRQn 1 */

    /* USER CODE END EXTI0_IRQn 1 */
}

/**
  * @brief This function handles EXTI line[15:10] interrupts.
  */
void EXTI15_10_IRQHandler(void)
{
    /* USER CODE BEGIN EXTI15_10_IRQn 0 */

    /* USER CODE END EXTI15_10_IRQn 0 */
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
    /* USER CODE BEGIN EXTI15_10_IRQn 1 */

    /* USER CODE END EXTI15_10_IRQn 1 */
}

/**
  * @brief  This function handles EXTI interrupt request.
  * @param  GPIO_Pin: Specifies the pins connected EXTI line
  * @retval None
  */
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
    /* EXTI line interrupt detected */
    if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
    {
        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
        HAL_GPIO_EXTI_Callback(GPIO_Pin);
    }
}


使用 STM32 标准库的代码:

#define KEY1_INT_GPIO_PORT         GPIOA
#define KEY1_INT_GPIO_CLK          (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN          GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE    GPIO_PinSource0
#define KEY1_INT_EXTI_LINE         EXTI_Line0
#define KEY1_INT_EXTI_IRQ          EXTI0_IRQn

#define KEY1_IRQHandler            EXTI0_IRQHandler


#define KEY2_INT_GPIO_PORT         GPIOC
#define KEY2_INT_GPIO_CLK          (RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN          GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE    GPIO_PinSource13
#define KEY2_INT_EXTI_LINE         EXTI_Line13
#define KEY2_INT_EXTI_IRQ          EXTI15_10_IRQn

#define KEY2_IRQHandler            EXTI15_10_IRQHandler

 /**
  * @brief  配置嵌套向量中断控制器NVIC
  * @param  无
  * @retval 无
  */
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* 配置中断源:按键1 */
  NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* 配置中断源:按键2,其他使用上面相关配置 */  
  NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
  NVIC_Init(&NVIC_InitStructure);
}

 /**
  * @brief  配置 IO为EXTI中断口,并设置中断优先级
  * @param  无
  * @retval 无
  */
void EXTI_Key_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 
	EXTI_InitTypeDef EXTI_InitStructure;

	/*开启按键GPIO口的时钟*/
	RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
												
	/* 配置 NVIC 中断*/
	NVIC_Configuration();
	
    /*--------------------------KEY1配置-----------------------------*/
	/* 选择按键用到的GPIO */	
    GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
    /* 配置为浮空输入 */	
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);

	/* 选择EXTI的信号源 */
    GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); 
    EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
	
    /* EXTI为中断模式 */
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    /* 上升沿中断 */
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    /* 使能中断 */	
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
	
    /*--------------------------KEY2配置-----------------------------*/
    /* 选择按键用到的GPIO */	
    GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
    /* 配置为浮空输入 */	
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);

    /* 选择EXTI的信号源 */
    GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); 
    EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
	
    /* EXTI为中断模式 */
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    /* 下降沿中断 */
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    /* 使能中断 */	
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
}

void KEY1_IRQHandler(void)
{
    //确保是否产生了EXTI Line中断
	if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 
	{
		// LED1 取反		
		LED1_TOGGLE;
        //清除中断标志位
		EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
	}  
}

void KEY2_IRQHandler(void)
{
    //确保是否产生了EXTI Line中断
	if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) 
	{
		// LED2 取反		
		LED2_TOGGLE;
        //清除中断标志位
		EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     
	}  
}


__HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); 对应 RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK,ENABLE);
HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct); 对应 GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI0_IRQn); 对应 NVIC_Init(&NVIC_InitStructure); EXTI_Init(&EXTI_InitStructure);
__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) 对应 EXTI_GetITStatus(KEY1_INT_EXTI_LINE)
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin) 对应
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值