STM32F4X EXTI外部中断
什么是外部中断
外部中断顾名思义就是外部给MCU一个信号,MCU就进入中断,外部中断通常是由MCU的引脚收到一个信号进行触发。
STM32F4X 外部中断引脚映射
在STM32FX中,一共有22个外部中断,具体的中断事件如下图所示
从上图中可以看到外部中断0~15对应的GPIO输入中断,但是问题就来了,STM32F4X的引脚有上百个,但是GPIO中断就只有16个,那么这些引脚是怎样跟中断线进行关联的呢,STM32F4X对此做了GPIO和外部中断的映射。具体的映射关系如下
STM32映射关系是这样的,GPIOX.0 ~ GPIOX.15分别对应EXTI0 ~ EXTI15。比如GPIOA0、GPIOB0、GPIOC0、GPIOD0、GPIOE0、GPIOF0、GPIOG0、GPIOH0对应EXTI0,以此类推。具体怎样配置是通过STM32F4X的SYSCFG寄存器进行配置。
外部中断触发条件
外部中断通常有5种触发方式,分别是上升沿触发,下降沿触发,边沿触发,高电平触发和低电平触发。
上升沿触发
上升沿就是在电平从低电平到高电平的那一瞬间,就叫上升沿。而上升沿触发的意思就是当检测到电平出现从低到高就进入触发状态。
下降沿触发
下降沿触发与上升沿触发相反,下降沿就是在电平从高电平到低电平的那一瞬间,就叫下降沿。而下降沿触发的意思就是当检测到电平出现从高到低就进入触发状态。
边沿触发
边沿触发就是结合了上升沿触发方式和下降沿触发方式。
高电平触发
高电平触发就是当检测到引脚为高电平时就进入触发状态,要注意的是如果引脚一直为高电平就会一直进入触发状态,直到引脚为低电平时才退出触发状态。
低电平触发
低电平触发就是当检测到引脚为低电平时就进入触发状态,要注意的是如果引脚一直为低电平就会一直进入触发状态,直到引脚为高电平时才退出触发状态。
STM32F4X支持上升沿触发、下降沿触发和边沿触发模式。
STM32F4X EXTI外部中断配置步骤
- 打开SYSCFG的时钟
- 设置GPIO和EXTI的对应关系
- 设置GPIO为输入模式
- 配置EXTI模式,触发方式等
- 配置NVIC
- 在中断函数里面进行业务逻辑的处理
GPIO引脚与中断线配置函数
/*
EXTI_PortSourceGPIOx:GPIO端口号
EXTI_PinSourcex:GPIO引脚
*/
void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex)
GPIO初始化函数
/*
GPIOx:GPIO端口号
GPIO_InitStruct:GPIO对象结构体
*/
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
EXTI初始化函数
/*
EXTI_InitStruct:EXTI对象结构体
*/
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
NVIC初始化函数
/*
NVIC_InitStruct:NVIC对象结构体
*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
例程代码
#include "stm32f4xx.h"
#include "misc.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_exti.h"
#include "stm32f4xx_syscfg.h"
void exti_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断分组为组2
RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOAEN,ENABLE); // 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE); // 使能SYSCFG时钟
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; // GPIO输入模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; // 引脚为GPIOA0
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // GPIO上拉
GPIO_Init(GPIOA,&GPIO_InitStruct); // 初始化GPIOA0引脚
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0); // 将GPIOA0与中断线0连接
EXTI_InitStruct.EXTI_Line = EXTI_Line0; // EXTI0
EXTI_InitStruct.EXTI_LineCmd = ENABLE; // 使能EXTI0中断
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; // 触发方式为上升沿触发
EXTI_Init(&EXTI_InitStruct); // 初始化EXTI
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; // 中断线0编号
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; // 中断使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2; // 抢占优先级2
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; // 响应优先级2
NVIC_Init(&NVIC_InitStruct); // 初始化NVIC
}
void EXTI0_IRQHandler(void) // 中断线0中断函数
{
if(EXTI_GetITStatus(EXTI_Line0) == SET) // 判断EXTI0中断是否发生
{
/*
业务逻辑代码
*/
EXTI_ClearITPendingBit(EXTI_Line0); // 清除EXTI0中断标志位
}
}