本篇主要介绍外部中断EXTI(Extern Interrupt),外部中断顾名思义就是由外部的某种变化引起的中断,这里外部也就是GPIO口,变化也就是GPIO口的引脚电平的变化,例如从高电平变化到低电平出现的下降沿变化,或者从低电平变化到高电平出现的上升沿变化。
当我们开启外部中断,就可以识别GPIO口的电平变化,然后EXTI就会立即向NVIC(中断管理系统)发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。
EXTI触发的方式:上升沿/下降沿/双边沿/软件触发
EXTI支持的GPIO口:所有的GPIO口都可以触发外部中断,但是相同的Pin不能同时触发中断,因为相同的Pin口是占相同的EXTI通道的,例如PA0和PB0是同样中断通道EXTI0。
EXTI通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒。
触发的响应方式:中断响应/事件响应(简单的说中断响应是直接进入中断服务函数里面的,而事件响应则是将这个电平变化带到其他外设处理上的一个信号)
对于EXTI基本结构主要是:先对GPIO进行配置,然后对AFIO中断引脚选择,然后配置EXTI边沿检测及控制,然后配置NVIC。具体配置可以依据下图:
另外说一句,在STM32中AFIO主要用于引脚复用功能的重映射、中断引脚的选择
下面来说一下对于外部中断初始化的代码配置:
void EXTI_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStructure);
}
下面就来介绍一下NVIC的优先级分组,NVIC的中断优先级是由优先级寄存器的4位(0-15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级。
抢占优先级是如果前面有正在进行的中断处理函数,那么也可以进行抢占,也就是先处理抢占优先级高的中断,这么说来抢占优先级即可进行中断嵌套。
而响应优先级不可以进行抢占,只是进行一个中断优先级的判断,如果抢占优先级相同的情况下再比较响应优先级,如果响应优先级高的中断,即可进行“插队”,优先响应响应优先级高的中断。
下面就是中断服务函数的代码:
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) == SET)
{
//这里写中断处理的一些内容:点灯或者。。
EXTI_ClearITPendingBit(EXTI_Line0);
}
}