STM32外部中断(EXTI)配置指南
EXTI简介
EXTI(Extern Interrupt)外部中断
EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
支持的触发方式:上升沿/下降沿/双边沿/软件触发
支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
触发响应方式:中断响应/事件响应
EXTI基本结构
AFIO
AFIO主要用于引脚复用功能的选择和重定义
在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择
EXTI框图
EXTI配置基本步骤:
- 开启相关外设时钟时钟
- 配置GPIO,将选定的端口配置为输入模式
- 配置AFIO,选择外部中断引脚
- 配置EXTI,选择边沿触发方式,选择触发响应方式
- 配置NVIC,给中断选择一个优先级
一:开启相关外设时钟时钟:
由于NVIC和EXTI的时钟是一直开启的,所以我们只需要开启GPIO和AFIO
GPIO和AFIO都是在APB2总线上的外设,所以应该用RCC_APB2PeriphClockCmd函数
现在我们开启GPIO和AFIO的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO的时钟
二:配置GPIO
首先查询参考手册,查看EXTI外设使用GPIO时应该将GPIO配置成什么模式
现在我们配置GPIO:
GPIO_InitTypeDef GPIO_InitStruct;//GPIO初始化结构体
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;//将引脚模式配置为上拉输入
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_14;//配置Pin14口
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//设置Pin14口的最大翻转速度为50Mhz(输入模式此项不起作用)
GPIO_Init(GPIOB,&GPIO_InitStruct);//配置B14口
关于输入模式得选择:
想要检测边沿 | 输入模式 |
---|---|
低电平/下降沿 | 上拉输入 |
高电平/上升沿 | 下拉输入 |
高和低电平/双边沿 | 浮空输入/下拉输入/上拉输入 |
四:配置AFIO
我们使用GPIO_EXTILineConfig函数进行外部中断引脚选择
GPIO_EXTILineConfig函数定义:
/ * *
* @brief选择用作外部中断线的GPIO引脚。
* @param GPIO_PortSource:选择某个GPIO外设作为外部中断源。
*取值为GPIO_PortSourceGPIOx,其中x取值为(A..G)。
* @param GPIO_PinSource:指定要配置的外部中断线。
*取值为GPIO_PinSourcex,其中x可以是(0..15)。
* @retval无
* /
* void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
现在我们配置AFIO:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);//选择B14口作为外部中断线
四:配置EXTI
配置EXTI函数:
/**
* @brief 根据指定参数初始化EXTI外设
* EXTI_InitStruct中的参数。
* @param EXTI_InitStruct: 指向EXTI_InitTypeDef结构体的指针
*包含EXTI外设的配置信息。
* @retval None
*/
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
EXTI_InitStruct结构体:
typedef struct
{
uint32_t EXTI_Line; /*!< 指定要配置的外部中断线。该参数可以是@ref EXTI_Lines的任意组合*/
EXTIMode_TypeDef EXTI_Mode; //指定外部中断线的响应模式
EXTITrigger_TypeDef EXTI_Trigger; //指定外部中断的有效边沿
FunctionalState EXTI_LineCmd; //指定选择的外部中断线的新状态
}
成员 | 可选参数 |
---|---|
EXTI_Line | EXTI_Line0至 EXTI_Line15//常规外部中断 |
EXTI_Line16//连接到PVD输出 | |
EXTI_Line17//连接到RTC告警事件 | |
EXTI_Line18//连接USB设备/USB OTG FS从暂停事件中唤醒 | |
EXTI_Line19//连接到以太网唤醒事件 | |
EXTI_Mode | EXTI_Mode_Interrupt//中断模式 |
EXTI_Mode_Event//事件模式 | |
EXTI_Trigger | EXTI_Trigger_Rising//上升沿触发 |
EXTI_Trigger_Falling//下降沿触发 | |
EXTI_Trigger_Rising_Falling//上升下降沿都触发 | |
EXTI_LineCmd | ENABLE//开启 |
DISABLE//关闭 |
配置NVIC:
配置优先级分组:
NVIC_PriorityGroupConfig函数定义:
/**
* @brief 配置优先级分组: 抢占优先级和响应优先级.
* @param NVIC_PriorityGroup: 指定优先级分组比特长度。
* 此参数可以是下列值之一:
* @arg NVIC_PriorityGroup_0: 0 位抢占优先级(0)
* 4 位响应优先级(0-15)
* @arg NVIC_PriorityGroup_1: 1 位抢占优先级(0-1)
* 3 位响应优先级(0-7)
* @arg NVIC_PriorityGroup_2: 2 位抢占优先级(0-3)
* 2 位响应优先级(0-3)
* @arg NVIC_PriorityGroup_3: 3 位抢占优先级(0-7)
* 1 位响应优先级(0-1)
* @arg NVIC_PriorityGroup_4: 4 位抢占优先级(0-15)
* 0 位响应优先级(0)
* @retval None
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
现在我们配置中断优先级分组:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//将中断优先级配置为NVIC_PriorityGroup_2
配置NVIC:
NVIC_Init函数定义:
/**
* @brief 根据NVIC_InitStruct中的参数配置NVIC外设。
* @param NVIC_InitStruct: 指向NVIC_InitStruct结构体的指针
* @retval None
*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
NVIC_InitStruct结构体:
typedef struct
{
uint8_t NVIC_IRQChannel; //指定要启用或禁用的IRQ通道(对于完整的STM32设备IRQ通道列表,请参考stm32f10x.h文件)
uint8_t NVIC_IRQChannelPreemptionPriority; //指定IRQ通道的抢占优先级,这个参数可以是一个值,其取值范围由NVIC_PriorityGroupConfig函数决定
uint8_t NVIC_IRQChannelSubPriority; //指定IRQ通道的响应优先级,这个参数可以是一个值,其取值范围由NVIC_PriorityGroupConfig函数决定
FunctionalState NVIC_IRQChannelCmd; //指定是否启用在NVIC_IRQChannel中的IRQ通道
} NVIC_InitTypeDef;
成员 | 可选参数 |
---|---|
NVIC_IRQChannel(STM32c8t6,EXTI的IRQ通道) | EXTI0_IRQn//EXTI 线0中断 |
EXTI1_IRQn//EXTI 线1中断 | |
EXTI2_IRQn//EXTI 线2中断 | |
EXTI3_IRQn//EXTI 线3中断 | |
EXTI4_IRQn//EXTI 线4中断 | |
EXTI9_5_IRQn//EXTI 线5-9中断 | |
EXTI15_10_IRQn//EXTI 线10-15中断 | |
NVIC_IRQChannelPreemptionPriority | 其取值范围由NVIC_PriorityGroupConfig函数决定 |
NVIC_IRQChannelSubPriority | 其取值范围由NVIC_PriorityGroupConfig函数决定 |
NVIC_IRQChannelCmd | ENABLE//启用 |
DISABLE//禁用 |
现在配置NVIC:
NVIC_InitTypeDef NVIC_IinitStruct;//创建初始化结构体
NVIC_IinitStruct.NVIC_IRQChannel=EXTI0_IRQn;//指定EXTI0_IRQn通道
NVIC_IinitStruct.NVIC_IRQChannelCmd=ENABLE;//启用EXTI0_IRQn通道
NVIC_IinitStruct.NVIC_IRQChannelPreemptionPriority=1;//将EXTI0_IRQn通道的抢占优先级设置为一
NVIC_IinitStruct.NVIC_IRQChannelSubPriority=1;//将EXTI0_IRQn通道的响应优先级设置为一
NVIC_Init(&NVIC_IinitStruct);//根据NVIC_IinitStruct中的参数配置NVIC
EXTI中断服务函数和标志位读取函数:
中断服务函数:
在STM32中,中断服务函数的函数名是指定的,以下是EXTI的全部中断服务函数函数名:
函数名 | 对应中断 |
---|---|
EXTI0_IRQHandler | EXTI线0中断 |
EXTI1_IRQHandler | EXTI线1中断 |
EXTI2_IRQHandler | EXTI线2中断 |
EXTI3_IRQHandler | EXTI线3中断 |
EXTI4_IRQHandler | EXTI线4中断 |
EXTI9_5_IRQHandler | EXTI线9-5中断 |
EXTI15_10_IRQHandler | EXTI线15-10中断 |
标志位读取函数:
EXTI_GetITStatus函数定义:
/**
* @brief 检测指定外部中断线是否被挂起
* @param EXTI_Line: 指定要检测外部中断线
* @arg EXTI_Linex: 指定外部中断线,x可以为(0..19)
* @retval 指定外部中断线的最新状态 (SET or RESET).
*/
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)
EXTI_ClearITPendingBit函数定义:
/**
* @brief 清除指定外部中断线的挂起状态
* @param EXTI_Line: 指定要清除外部中断线
* 该参数可以是EXTI_Linex的任意组合,其中x可以是(0..19)。
* @retval None
*/
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)
中断服务函数模板:
void 中断服务函数的函数名(void)
{
if(EXTI_GetITStatus(EXTI_Line14)==SET)
{
//要进行的操作
EXTI_ClearITPendingBit(EXTI_Line14);
}
}
作者:冯雪娟_00