STM32之外部中断 EXTI

STM32之外部中断 EXTI

STM32中断控制线支持19个外部中断/事件请求,每个中断都有对应状态位和独立的触发与屏蔽设置。STM32F103的19个外部中断为:

线0-15:对应GPIO口的输入中断。
线16:连接到PVD输出(掉电检测,掉电时可立即保存重要数据作用)。
线17:连接RTC闹钟事件。 线18:连接到USB唤醒事件

STM32的每个IO口都可以作为外部中断源的输入端,而IO口使用的中断线只有16根,且引脚GPIOx.0~GPIOx.15(x=A~G)分别对应中断线0-15.这样每个中断线对应了7个IO口。如线0对应引脚GPIOA.0/GPIOB.0/GPIOC.0/GPIOD.0/GPIOE.0/GPIOF.0/GPIOG.0,但是每个中断线每次只能连接到1个IO口上。即同一时刻EXTIx只能响应一个端口的事件触发,不能同时响应所有IO端口的事件,但可以分时复用。

EXTI TO GPIO

*1、GPIO与中断映射配置通过函数来实现

void GPIO_EXTILineConfig ( uint8_t  GPIO_PortSource,uint8_t  GPIO_PinSource );

例如

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE , GPIO_PinSource2);

即外部中断线2就和GPIOE映射起来了,显然是GPIOE.2连接EXTI2中断线。
设置中断触发方式:

void EXTI_Init( EXTI_InitTypeDef * EXTI_InitStruct )

例如设置中断线line4的中断为下降沿触发

EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line4;//选择中断线4,即EXTI4
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的中断优先级。

2、设置NVIC的中断优先级

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); //中断优先级分组初始化

3、 配置完中断优先级后,需要编写中断服务程序

stm32f10x_it.c文件是专门用来存放中断服务函数的。文件中默认只有几个关于系统异常的中断服务函数,而且都是空函数,在需要的时候自行编写。相信部分像我一样的初学者会有疑问,中断服务函数的名称可以自己定义吗?不行。中断服务程序的名字必须要与启动文件startup_stm32f10x_hd.s中的中断向量表定义的一致。
需要注意的一点,IO口16个外部中断只有7个函数名:

EXTI0_IRQHandler    ;EXTI Line0
EXTI1_IRQHandler    ;EXTI Line1
EXTI2_IRQHandler    ;EXTI Line2
EXTI3_IRQHandler    ;EXTI Line3
EXTI4_IRQHandler    ;EXTI Line4

EXTI9_5_IRQHandler  ;EXTI Line9..5
EXTI15_10_IRQHandler;EXTI Line15..10

中断线在5后就不能单独命名,如果写成EXTI5_IRQHandler…编译器是不会报错的,不过中断服务程序不能正常工作。

编写中断服务函数经常需要使用两个函数

ITStatus EXTI_GetITStatus(uint32_t  EXTI_line);
//放在中断服务程序开头,检测中断标志位
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)//放在函数的结尾

第一个是判断某个中断线上的中断是否发生(即标志位是否置位)
第二个是清除中断线上的标志位(即清除标志位)

常用的外部中断服务程序格式

格式一:

void EXTI4_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line4) != RESET)//判断是否置位
        Dosomething();//执行中断事件
    EXTI_ClearITpendingBit(EXTI_Line4);//清除Line4标志位
}

格式二:

void EXTI_IRQHandler(void)
{
    if(EXTI_GetFlagStatus(EXTI_Line4) != RESET)
        Dosomething();
    EXTI_ClearFlag(EXTI_Line4);
}

EXTI_GetITStatus() 会先判断中断该中断是否使能,使能了的话在判断该标志位是否置位;而EXTI_GetFlagStatus()会直接判断中断标志位是否置位(所以显得马虎一点)。一般情况下首选EXTI_GetITStatus().

关于外部中断EXTI大概就这些了,其他的还要靠自己去动手操作才能掌握更多。

                                        -- From #IRONMAN#
                                        -- 4/24/2017
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章