Skip to content

第二章 EXTI

2.1 EXTI外设简介

  • EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
  • 支持的触发方式:上升沿/下降沿/双边沿/软件触发
  • 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
  • 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
  • 触发响应方式:中断响应/事件响应

2.2 中断事件与中断线

中断/事件线 输入源
EXTI0 PX0(X可为A,B,C,D,E,F,G,H,I)
EXTI1 PX1(X可为A,B,C,D,E,F,G,H,I)
EXTI2 PX2(X可为A,B,C,D,E,F,G,H,I)
EXTI3 PX3(X可为A,B,C,D,E,F,G,H,I)
EXTI4 PX4(X可为A,B,C,D,E,F,G,H,I)
EXTI5 PX5(X可为A,B,C,D,E,F,G,H,I)
EXTI6 PX6(X可为A,B,C,D,E,F,G,H,I)
EXTI7 PX7(X可为A,B,C,D,E,F,G,H,I)
EXTI8 PX8(X可为A,B,C,D,E,F,G,H,I)
EXTI9 PX9(X可为A,B,C,D,E,F,G,H,I)
EXTI10 PX10(X可为A,B,C,D,E,F,G,H,I)
EXTI11 PX11(X可为A,B,C,D,E,F,G,H,I)
EXTI12 PX12(X可为A,B,C,D,E,F,G,H,I)
EXTI13 PX13(X可为A,B,C,D,E,F,G,H,I)
EXTI14 PX14(X可为A,B,C,D,E,F,G,H,I)
EXTI15 PX15(X可为A,B,C,D,E,F,G,H,I)
EXTI16 PVD输出
EXTI17 RTC闹钟事件
EXTI18 USB唤醒事件
EXTI19 以太网唤醒事件(只适用互联型)

AFIO引脚复用,通过引脚编号直接映射,不论是A0还是B0均使用一个EXTI0事件线

image-20240916233559097

2.3 中断相关概念

中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行

中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源

中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回

image-20240916233233740

2.4 NVIC优先级分组

  • ARM Cortex-M 使用了 8 位宽的寄存器来配置中断的优先等级,这个寄存器就是中断优先级配置寄存器。但STM32,只用了中断优先级配置寄存器的高4位 [7 : 4],所以STM32提供了最大16级的中断优先等级。
  • STM32 的中断优先级可以分为抢占优先级和子优先级, 抢占优先级 高的可以中断嵌套, 子优先级 高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队。
  • 中断优先级数值越小越优先。
优先级分组 抢占优先级 子优先级 优先级配置寄存器高 4 位
NVIC_PriorityGroup_0 0 级抢占优先级 0-15 级子优先级 0bit 用于抢占优先级,4bit 用于子优先级
NVIC_PriorityGroup_1 0-1 级抢占优先级 0-7 级子优先级 1bit 用于抢占优先级,3bit 用于子优先级
NVIC_PriorityGroup_2 0-3 级抢占优先级 0-3 级子优先级 2bit 用于抢占优先级,2bit 用于子优先级
NVIC_PriorityGroup_3 0-7 级抢占优先级 0-1 级子优先级 3bit 用于抢占优先级,1bit 用于子优先级
NVIC_PriorityGroup_4 0-15 级抢占优先级 0 级子优先级 4bit 用于抢占优先级,0bit 用于子优先级

STM32CubeMX>中对应 抢占优先级子优先级 参数配置

image-20240919222424896

2.5 STM32CubeMX配置

2.5.1 SYS配置

image-20241128110251249

image-20241128110340962

2.5.2 RCC配置

image-20241128102746910

2.5.3 GPIO配置

PB0和PB1配置为LED1、LED2

  • 默认低电平
  • PB0和PB1均配置推挽输出
  • 上拉或下拉电阻在输入模式使用,输出模式不配置
  • 输出速度按需配置
  • 用户标签,给引脚起别名,按需配置

image-20241128111221030

PB6、PB7配置为KEY1、KEY2

  • 输入模式
  • 下拉电阻

image-20241128111432549

2.5.4 EXTI配置

image-20240919222942930

使能中断触发,否则找不到EXTI4_IRQHandler等中断函数

image-20241124180308221

2.5.5 NVIC优先级配置

image-20240919223855861

2.6 代码介绍

2.6.1 中断触发函数介绍

stm32f1xx_it.c文件找到中断触发函数,内容如下

C
/**
  * @brief This function handles EXTI line4 interrupt.
  */
void EXTI4_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI4_IRQn 0 */

  /* USER CODE END EXTI4_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
  /* USER CODE BEGIN EXTI4_IRQn 1 */

  /* USER CODE END EXTI4_IRQn 1 */
}

HAL_GPIO_EXTI_IRQHandler调用的函数内容,如下

C
/**
  * @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);
  }
}

判断是否触发中断,即不为0x00u则触发中断

C
__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u

清除触发中断的**标志位**

C
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);

这是一个“弱”回调函数,用户需要在自己的代码中重写函数,所以我们需要重写这个函数实现业务

C
HAL_GPIO_EXTI_Callback(GPIO_Pin);

1.6.2 编写回调函数

这个函数位置可以放在stm32f1xx_it.cmain.c均可

一个简单示例,PB3为按键1,PB6为按键2,PB0为LED,触发中断反转灯的亮灭。

C
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)  
{  
      if (GPIO_Pin == GPIO_PIN_0)  
      {  
            if (GPIO_Pin == GPIO_PIN_3)
            {
                HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
            }
            else if (GPIO_Pin == GPIO_PIN_6)
            {
                HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
            }
      }  
}