一、按键中断函数的编写流程(适用于其他中断函数的编写)
1、初始化要连接EXTI的GPIO
2、初始化EXTI用于产生中断/事件
3、初始化NVIC,用于处理中断
4、编写中断服务函数
二、初始化要连接EXTI的GPIO
//打开GPIOC的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
//初始化GPIO
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
GPIO_Init(GPIOC,&GPIO_InitStruct);
//打开AFIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//初始化AFIO
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);
这里我用的按键2 (PC13) GPIO初始化完成后我们还需要配置AFIO来确定要选择EXTI的信号源,要注意的是不要忘记打开AFIO的时钟。
三、初始化EXTI用于产生中断/事件
//配置EXTI
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line13;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStruct);
这里的模式我们要配置中断模式而不是事件模式,触发类型我们选择上升沿触发,因为按键按下时读取PC13口的电平是高电平(下图为按键的电路图)。
四、初始化NVIC,用于处理中断
//配置NVIC
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStruct);
这里我们要配置好NVIC对应的通道、分组、抢占优先级、响应优先级。
前三步的完整代码:
void EXTI_KEY_P13_Config(void)
{
//打开GPIOC的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
//初始化GPIO
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
GPIO_Init(GPIOC,&GPIO_InitStruct);
//打开AFIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//初始化AFIO
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);
//配置EXTI
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line13;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStruct);
//配置NVIC
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStruct);
}
五、编写中断服务函数
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetFlagStatus(EXTI_Line13)==SET) //中断的触发条件
{
LED_Green_Turn(); //执行的函数
}
EXTI_ClearITPendingBit(EXTI_Line13); //清除中断的标志位
}
到这里按键中断函数就编写完成了,最后在主函数中调用相关函数验证即可。