1.0 EXTI 简介
EXTI(Extern Interrupt)外部中断
EXTI 可以监测指定 GPIO 口的电平信号,当其指定的 GPIO 口产生电平变化的时候,EXTI 立即向 NVIC 发出中断申请,经过 NVIC 裁决后即可中断 CPU 主程序,使得 CPU 执行 EXTI 对应的中断程序。
其中 EXTI 支持四种不同的触发方式。
- 上升沿:数字电平从低电平 0 变化到高电平 1 的一瞬间叫做上升沿。
- 下降沿:数字电平从高电平 1 变化到低电平 0 的一瞬间叫做下降沿。
- 双边沿:上升沿和下降沿。
- 软件触发:不需要硬件触发的外部中断,而由软件触发的中断。
2.0 EXTI 特性
- EXTI 支持所有 GPIO 口,但是相同 Pin 的 IO 口不可以同时触发中断(比如PA0,PB0不能同时触发中断)。
- EXTI 支持的通道数:16个GPIO_Pin、PVD输出、RTC时钟、USB唤醒、以太网唤醒(合计20个中断线路)。
- 触发相应方式:中断响应、事件相应(事件响应不会触发中断,而是触发别的外设操作)。
3.0 STM32 标准库使用 EXTI
这里以 STM32F103C8T6
作为示例。
3.1 使能 RCC 时钟
由于NVIC和EXTI是默认开启时钟的外设,因此不需要开启这两个外设的时钟;需要开启的有GPIO时钟以及AFIO时钟。
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOx, ENABLE); // GPIO
RCC_APB2PeriphClockCmd (RCC_APB2Periph_AFIO, ENABLE); // AFIO
3.2 配置 GPIO 工作模式
由于使用EXTI外部中断,因此需要使目标 GPIO 口工作在上拉输入 (GPIO_Mode_IPU) 的模式下。
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);
3.3 配置 AFIO
通过 AFIO 将需要使用的 GPIO 口连接到 EXTI。
GPIO_EXTILineConfig (GPIO_PortSourceGPIOx, GPIO_PinSourcex);
3.4 配置 EXTI
选择中断触发方式。
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_Rising
—— 上升沿触发EXTI_Trigger_Falling
—— 下降沿触发EXTI_Trigger_Rsing_Falling
—— 双边沿触发
3.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 |
3.6 EXTI 中断函数
在 EXTI 配置完毕后,当达到中断触发条件后就会自动执行中断函数中的代码。
//中断函数
void EXTI15_10_IRQHandler(void){
if (EXTI_GetITStatus(EXTI_Linex) == SET ) { // 判断中断标志位,判断是否为想要触发中断的通道
/*
* 需要执行的函数
*/
EXTI_ClearITPendingBit(EXTI_Linex); // 清除中断标志位,防止程序重复申请中断造成死循环
}
}
评论区(暂无评论)