跳转至

EXTI 外部中断

1. 简介

EXTI(Extern Interrupt)外部中断

EXTI 可以监测指定 GPIO 口的电平信号,当其指定的 GPIO 口产生电平变化的时候,EXTI 立即向 NVIC 发出中断申请,经过 NVIC 裁决后即可中断 CPU 主程序,使得 CPU 执行 EXTI 对应的中断程序。

其中 EXTI 支持四种不同的触发方式

数字电平从低电平 0 变化到高电平 1 的一瞬间叫做上升沿

数字电平从高电平 1 变化到低电平 0 的一瞬间叫做下降沿

上升沿或者下降沿。

不需要硬件触发的外部中断,而由软件触发的中断。

1.1 EXTI 特性

  • EXTI 支持所有 GPIO 口,但是相同 Pin 的 IO 口不可以同时触发中断(比如PA0PB0不能同时触发中断)。
  • EXTI 支持的通道数:16个GPIO_PinPVD输出RTC时钟USB唤醒以太网唤醒(合计20个中断线路)。
  • 触发相应方式:中断响应事件相应(事件响应不会触发中断,而是触发别的外设操作)。

2. EXIT 外部中断

2.1 开启RCC时钟

由于NVICEXTI是默认开启时钟的外设,因此不需要开启这两个外设的时钟;需要开启的有GPIO时钟以及AFIO时钟

RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOx, ENABLE);   // GPIO
RCC_APB2PeriphClockCmd (RCC_APB2Periph_AFIO, ENABLE);    // AFIO

2.2 配置GPIO口工作模式

由于使用EXTI外部中断,因此需要使目标 GPIO 口工作在上拉输入 (GPIO_Mode_IPU) 的模式下。

1
2
3
4
5
6
7
GPIO_InitTypeDef GOIO_InitStrucuture;

GOIO_InitStrucuture.GPIO_Mode = GPIO_Mode_IPU;      // GPIO 上拉输入
GOIO_InitStrucuture.GPIO_Pin = GPIO_Pin_x;          // 配置需要使用的 Pin 口
GOIO_InitStrucuture.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB,&GOIO_InitStrucuture);

2.3 配置 AFIO

通过 AFIO 将需要使用的 GPIO 口连接到 EXTI。

GPIO_EXTILineConfig (GPIO_PortSourceGPIOx, GPIO_PinSourcex);
// 将 GPIOx 连接至 AFIO 的 x 中断线路上

通过这个函数可以将指定的 GPIO 端口与指定的 EXTI 线路相连

2.4 配置EXIT

选择中断触发方式。

1
2
3
4
5
6
7
8
EXTI_InitTypeDef EXTI_InitStructure;                        // EXTI初始化结构体

EXTI_InitStructure.EXTI_Line = EXTI_Linex;                  // 选择需要配置的中断线,这个与配置AFIO时所配置的中断线相同
EXTI_InitStructure.EXTI_LineCmd = ENABLE;                   // 选择指定中断线的状态
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;         // 指定模式(EXTI_Mode_Interrupt : 中断模式)
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;     // 指定触发信号的有效边沿

EXTI_Init(&EXTI_InitStructure);

EXTI 的几种触发模式 .EXTI_Trigger

EXTI_Trigger_Rising —— 上升沿触发

EXTI_Trigger_Falling —— 下降沿触发

EXTI_Trigger_Rsing_Falling —— 双边沿触发

2.5 配置 NVIC

给中断分配一个合适的优先级

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
// 配置NCIV优先级分组(抢占优先级、响应优先级)
// 该函数在每一个芯片中只能使用一次

NVIC_TypeDef NVIC_InitStructure;                            // NCIV初始化结构体

NVIC_InitStructure.NCIV_IRQChannel = EXTI15_10_IRQn;        // 指定中断通道开启或者关闭
NVIC_InitStructure.NCIV_IRQChannelCmd = ENABLE;             // 指定通道使能还是失能(ENABLE,DISABLE)
NVIC_InitStructure.NCIV_IRQChannelPreemptionPriority =  1;  // 指定抢占优先级的优先级
NVIC_InitStructure.NCIV_IRQChannelSubPriority = 1;          // 指定响应优先级的优先级

NVIC_Init(&NVIC_InitStructure);

NVIC优先级的几种分组

NVIC_PriorityGroup 抢占优先级 相应优先级
NVIC_PriorityGroup_0 0 0-15
NVIC_PriorityGroup_1 0-1 0-7
NVIC_PriorityGroup_2 0-3 0-3
NVIC_PriorityGroup_3 0-7 0-1
NVIC_PriorityGroup_4 0-15 0

2.5 EXTI中断函数

在 EXTI 配置完毕后,当达到中断触发条件后就会自动执行中断函数中的代码。

//中断函数
void EXTI15_10_IRQHandler(void){
    if (EXTI_GetITStatus(EXTI_Linex) == SET ) {      // 判断中断标志位,判断是否为想要触发中断的通道

        /* 
         * 需要执行的函数 
        */

        EXTI_ClearITPendingBit(EXTI_Linex);         // 清除中断标志位,防止程序重复申请中断造成死循环
    }
}