STM32外部中断
一、基础概念二、配置三、总结配置步骤
四、代码初始化函数服务函数
一、基础概念
STM32 的每个 IO 都可以作为外部中断的中断输入口。STM32F103 的中断控制器支持 19 个外部中断/ 事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。 STM32F103 的 19 个外部中断为: 线 0~15:对应外部 IO 口的输入中断。 线 16:连接到PVD输出。 线 17:连接到RTC 闹钟事件。 线 18:连接到USB唤醒事件。
STM32 的16 个中断线是如何与 IO 口一一对应起来的呢? GPIO 的管脚 GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 0~15。这样每个中 断线对应了最多 7 个 IO 口。 以线 0 为例:它对应了GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、 GPIOE.0、GPIOF.0、GPIOG.0。而中断线每次只能连接到 1 个 IO 口上,这样就需要通过配置 来决定对应的中断线配置到哪个GPIO上了。下面我们看看GPIO跟中断线的映射关系图:
二、配置
配置GPIO与中断线的映射关系的函数GPIO_EXTILineConfig()来实现的:
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
该函数将GPIO端口与中断线映射起来,使用范例是:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
中断线上中断的初始化是通过函数EXTI_Init()实现的。EXTI_Init()函数的定义是:
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
如:
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line4; //中断线的标号
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //触发方式EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据 EXTI_InitStruct 中指定的
//参数初始化外设 EXTI 寄存器
通过以上两个步骤,已经设置好了中断线和GPIO映射关系,以及中断的触发模式等初始化参数,因为是外部中断,所以还要设置 NVIC 中断优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
配置完中断优先级之后,接着要做的就是编写中断服务函数。 STM32 的 IO 口外部中断函数只有 6 个,中断线 0-4 每个中断线对应一个中断函数,中断线 5-9 共用中断函数EXTI9_5_IRQHandler,中 断线 10-15 共用中断函数EXTI15_10_IRQHandler。
4.中断服务函数
判断中断是否发生
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
清除某个中断线上 的中断标志位
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
常用的中断服务函数格式为:
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line4
)!=RESET
)
{
中断逻辑…
EXTI_ClearITPendingBit(EXTI_Line4
);
}
}
三、总结
配置步骤
1)初始化 IO 口为输入。 2)开启AFIO时钟 (使能复用功能时钟) 3)设置 IO 口与中断线的映射关系。 4)初始化线上中断,设置触发条件等。 5)配置中断分组(NVIC),并使能中断。 6)编写中断服务函数。
四、代码
初始化函数
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure
;
NVIC_InitTypeDef NVIC_InitStructure
;
KEY_Init();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO
,ENABLE
);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE
,GPIO_PinSource3
);
EXTI_InitStructure
.EXTI_Line
=EXTI_Line3
;
EXTI_InitStructure
.EXTI_Mode
= EXTI_Mode_Interrupt
;
EXTI_InitStructure
.EXTI_Trigger
= EXTI_Trigger_Falling
;
EXTI_Init(&EXTI_InitStructure
);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE
,GPIO_PinSource4
);
EXTI_InitStructure
.EXTI_Line
=EXTI_Line4
;
EXTI_Init(&EXTI_InitStructure
);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA
,GPIO_PinSource0
);
EXTI_InitStructure
.EXTI_Line
=EXTI_Line0
;
EXTI_InitStructure
.EXTI_Trigger
= EXTI_Trigger_Rising
;
EXTI_Init(&EXTI_InitStructure
);
NVIC_InitStructure
.NVIC_IRQChannel
= EXTI0_IRQn
;
NVIC_InitStructure
.NVIC_IRQChannelPreemptionPriority
= 0x02;
NVIC_InitStructure
.NVIC_IRQChannelSubPriority
= 0x03;
NVIC_InitStructure
.NVIC_IRQChannelCmd
= ENABLE
;
NVIC_Init(&NVIC_InitStructure
);
NVIC_InitStructure
.NVIC_IRQChannel
= EXTI3_IRQn
;
NVIC_InitStructure
.NVIC_IRQChannelPreemptionPriority
= 0x02;
NVIC_InitStructure
.NVIC_IRQChannelSubPriority
= 0x01;
NVIC_InitStructure
.NVIC_IRQChannelCmd
= ENABLE
;
NVIC_Init(&NVIC_InitStructure
);
NVIC_InitStructure
.NVIC_IRQChannel
= EXTI4_IRQn
;
NVIC_InitStructure
.NVIC_IRQChannelPreemptionPriority
= 0x02;
NVIC_InitStructure
.NVIC_IRQChannelSubPriority
= 0x00;
NVIC_InitStructure
.NVIC_IRQChannelCmd
= ENABLE
;
NVIC_Init(&NVIC_InitStructure
);
}
服务函数
void EXTI0_IRQHandler(void)
{
delay_ms(10);
if(WK_UP
==1)
{
BEEP
=!BEEP
;
}
EXTI_ClearITPendingBit(EXTI_Line0
);
}
void EXTI3_IRQHandler(void)
{
delay_ms(10);
if(KEY1
==0)
{
LED1
=!LED1
;
}
EXTI_ClearITPendingBit(EXTI_Line3
);
}
void EXTI4_IRQHandler(void)
{
delay_ms(10);
if(KEY0
==0)
{
LED0
=!LED0
;
LED1
=!LED1
;
}
EXTI_ClearITPendingBit(EXTI_Line4
);
}