一、外部中断介绍:
STM32 的每个 IO 都可以作为外部中断 的中断输入口,这点也是 STM32 的强大之处。STM32F103 的中断控制器支持 19 个外部中断/ 事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
STM32F103 的 19 个外部中断为: 线 0~15:对应外部 IO 口的输入中断;
线 16:连接到 PVD 输出;
线 17:连接到 RTC 闹钟事件;
线 18:连接到 USB 唤醒事件;
二、中断通道对应的IO口
GPIO 的管教 GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 0~15
三、中断函数的映射关系
也就是说对于中断线(A、B、C、D、E、F)0~4,每个中断线对应一个单独的中断函数
中断线(A、B、C、D、E、F)5~9,对应中断函数EXTI9_5_IRQHander
中断线(A、B、C、D、E、F)10~15,对应中断函数EXTI15_10_IRQHander
可能有些不太好理解,举个例子,我使用的是PB12、PB13、PB14、PB15,这三个IO口产生中断时都会进入中断函数EXTI15_10_IRQHander中,然后在中断函数内部在判断具体是那个IO口引发的中断即可。
四、外部中断的配置流程
1、首先配置需要使用外部中断的IO口
例:KEY0→PB12 KEY1→PB13 KEY2→PB14 KEY3→PB15
void KEY_Init(void) //IO初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK,ENABLE);//使能PORTB 时钟
GPIO_InitStructure.GPIO_Pin = KEY0_GPIO_PIN | KEY1_GPIO_PIN | KEY2_GPIO_PIN | KEY3_GPIO_PIN;//KEY0-4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure); //初始化GPIO
}
2、配置对应的中断线 及 中断通道设置
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource12);
EXTI_InitStructure.EXTI_Line=EXTI_Line12; //PB12 对应 EXTI_Line12
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //(选择中断 还是 事件)产生中断
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
EXTI_Init(&EXTI_InitStructure);
//GPIOB.13 中断线以及中断初始化配置 下降沿触发 //KEY1
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource13);
EXTI_InitStructure.EXTI_Line=EXTI_Line13;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
//GPIOB.14 中断线以及中断初始化配置 下降沿触发 //KEY2
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);
EXTI_InitStructure.EXTI_Line=EXTI_Line14;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
//GPIOB.14 中断线以及中断初始化配置 下降沿触发 //KEY3
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource15);
EXTI_InitStructure.EXTI_Line=EXTI_Line15;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //使能按键WK_UP所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
四、中断函数:
void EXTI15_10_IRQHandler(void)
{
if(KEY0 == 0)
{
exti_flag=1;
EXTI_ClearITPendingBit(EXTI_Line12); //清除LINE0上的中断标志位
while(KEY0==0);
}
if(KEY1 == 0)
{
exti_flag=2;
EXTI_ClearITPendingBit(EXTI_Line13); //清除LINE0上的中断标志位
while(KEY1==0);
}
if(KEY2 == 0)
{
exti_flag=3;
EXTI_ClearITPendingBit(EXTI_Line14); //清除LINE0上的中断标志位
while(KEY2==0);
}
if(KEY3 == 0)
{
exti_flag=4;
EXTI_ClearITPendingBit(EXTI_Line15); //清除LINE0上的中断标志位
while(KEY3==0);
}
}