STM32有些系列(比如STM32F407)的外部中断5-9是共用一个中断处理函数EXTI9_5_IRQHandler(),外部中断10-15共用中断函数EXTI15_10_IRQHandler(),所以很多人(包括我自己)刚开始时对于这些外部中断线的设置以及判断都不是弄得很清楚,下面就直接贴出中断引脚的配置、中断配置以及进入中断之后的判断处理程序。
外部中断引脚的IO初始化:
voidGPIOX_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOE,ENABLE);//使能GPIOB,GPIOE时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN;//普通输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_DOWN;//下拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN;//普通输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100Ms
GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE7
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
GPIO_InitStructure.GPIO_Speed =GPIO_Speed_100MHz;//100M
GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_DOWN;//下拉
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE9
}这个GPIOX_Init()初始化函数主要是对PB5、PE7、PE9初始化,其中PE7外部有上拉电阻,也就是平时保持高电平状态,PB5和PE9外部是下拉电阻,平时保持低电平状态。
外部中断初始化函数:
//外部中断初始化
void EXTIX_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//使能SYSCFG时钟
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource5);//PB5连接到中断线5
/*配置EXTI_Line5 */
EXTI_InitStructure.EXTI_Line =EXTI_Line5;//LINE5
EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE5
EXTI_Init(&EXTI_InitStructure);//配置
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource7);//PE7连接到中断线7
/*配置EXTI_Line7 */
EXTI_InitStructure.EXTI_Line =EXTI_Line7;//LINE7
EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE0
EXTI_Init(&EXTI_InitStructure);//配置
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource9);//PE9连接到中断线9
/*配置EXTI_Line9 */
EXTI_InitStructure.EXTI_Line =EXTI_Line9;//LINE9
EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger =EXTI_Trigger_Rising_Falling; //电平变化触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE0
EXTI_Init(&EXTI_InitStructure);//配置
NVIC_InitStructure.NVIC_IRQChannel =EXTI9_5_IRQn;//外部中断5
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0x01;//
NVIC_InitStructure.NVIC_IRQChannelCmd =ENABLE;//使能外部通道
NVIC_Init(&NVIC_InitStructure);//配置
}
首先要了解一点,外部中断5-9的中断优先级设置是没办法单独给外部中断5或者外部中断7设置,这几个是统一设置,也就是说,当有外部中断5-9其中的一个引起触发时,就会进入中断函数EXTI9_5_IRQHandler(),进入该函数之后再判断到底是哪个触发,然后再做相应的处理。其中PB5触发方式为上升沿触发,PE7为下降沿触发,PE9为电平变化触发,就是有上升沿或者下降沿都会触发。
中断处理函数:
voidEXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line5)!=RESET)
{
//中断处理,自行添加
EXTI_ClearITPendingBit(EXTI_Line5);
}
if(EXTI_GetITStatus(EXTI_Line7)!=RESET)
{
//中断处理,自行添加
EXTI_ClearITPendingBit(EXTI_Line7);
}
if(EXTI_GetITStatus(EXTI_Line9)!=RESET)
{
if(Bit_SET == GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_9))
{
//上升沿中断处理,自行添加
}
else if(Bit_RESET ==GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_9))
{
//下降沿中断处理,自行添加
}
EXTI_ClearITPendingBit(EXTI_Line9);
}
}
在外中断9的中断处理中,对IO口的电平做了判断,主要是为了处理在电平由低到高或者由高到低变化时情况。以上三种处理方式都是可以行的,如果觉得外中断5或者外中断7的中断处理不够保险,也可以向外中断9一样增加一个IO口电平判断。对于外部中断10-15,引脚配置、中断配置和中断处理函数都可以参照以上的方法。