如何将STM32的IO口作为外部中断输入?
外部中断/事件控制器(EXTI)由19个产生事件/中断要求的边沿检测器组成。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以被独立的屏蔽。
中断代码主要分布在固件库的stm32f10x_exti.h和stm32f10x_exti.c文件中。
每个IO都可以作为外部中断的中断输入口,STM32F103的中断控制器支持19个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
GPIO的管脚GPIOx.0~GPIOx.15(A,B,C,D,E,F,G)分别对应中断线0~15。每个中断线对应最多7个IO口,中断线每次只能连接到1个IO口上,这样就需要通过配置来决定对应的中断线配置到哪个GPIO上了。
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
EXTI_Init() ----------- 中断线上中断的初始化
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
// eg: 设置中断线4上的中断为下降沿触发
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line4; //中断线的标号,EXTI_Line0~EXTI_Line15
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; //中断模式,(中断EXTI_Mode_Interrupt和事件EXTI_Mode_Event)
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; //触发方式(上升/下降/任意电平触发)
EXTI_InitStructure.EXTI_LineCmd=ENABLE; //使能中断线
EXTI_Init(&EXTI_InitStructure);
涉及到中断就还要设置NVIC中断优先级。
eg: 设置中断线2的中断优先级
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
配置完中断优先级后,编写中断服务函数。中断服务函数的名字是在MDK中事先有定义的。STM32的IO口外部中断函数只有6个:
EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI4_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler
中断线0-4没给中断线对应一个中断函数,中断线5~9共用中断函数EXPORT EXTI9_5_IRQHandler,中断线10~15共用中断函数EXPORT EXTI15_10_IRQHandler。
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_LINE);
常用的中断服务函数格式:
void EXTI2_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3) != RESET)
{
中断逻辑.....
EXTI_ClearITPendingBit(EXTI_Line3);
}
}
ps:固件库还提供了两个函数来判断外部中断状态以及清除外部状态标志位的函数EXTI_GetFlagStatus和EXTI_ClearFlag,作用和前面的两个函数类似。 EXTI_GetFlagStatus函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而EXTI_GetITStatus直接用来判断状态标志位。