STM32-0xx系列-外部中断

一、外部中断/事件控制器EXTI控制器的主要特性如下:
●每个中断/事件都有独立的触发和屏蔽

●每个中断线都有专用的状态位

●支持多达20个软件的中断/事件请求

●检测脉冲宽度低于APB2时钟宽度的外部信号。

在这里插入图片描述

要产生中断,必须先配置好并使能中断线。根据需要的边沿检测设置2个触发寄存器, **同时在中断屏蔽寄存器的相应位写’1’允许中断请求。**当外部中断线上发生了期待的边沿时,将产生一个中断请求,对应的挂起位也随之被置’1’。在挂起寄存器的对应位写’1’,将清除该中断请求。如果需要产生事件,必须先配置好并使能事件线。根据需要的边沿检测通过设置2个触发寄存器,同时在事件屏蔽寄存器的相应位写’1’允许事件请求。当事件线上发生了需要的边沿时,将产生一个事件请求脉冲,对应的挂起位不被置’1’。通过在软件中断/事件寄存器写’1’,也可以通过软件产生中断。

二、外部中断概述

STM32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组为一个单位的,同组间的外部中断同一时间只能使用一个。比如说,PA0,PB0,PC0,PD0,PE0,PF0,PG0这些为1组,如果我们使用PA0作为外部中断源,那么其他的就不能再使用了。在此情况下,我们只能使用类似于PB1,PC2这种末端序号不同的外部中断源。
在这里插入图片描述
STM32的中断控制器支持19个外部中断/事件请求:

线0~15:对应外部IO口的输入中断。

线16:连接到PVD输出。

线17:连接到RTC闹钟事件。

线18:连接到USB唤醒事件

每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。

每一组使用一个中断标志EXTIx。EXTI0-EXTI4这5个外部中断有着自己单独的中断响应函数,EXIT5-EXIT9共用一个中断响应函数,EXIT10-EXIT15共用一个中断响应函数。
在这里插入图片描述
三、常用库函数

①voidGPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
//设置IO口与中断线的映射关系
exp:GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);

②voidEXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
//初始化中断线:触发方式等

③ITStatusEXTI_GetITStatus(uint32_t EXTI_Line);
//判断中断线中断状态,是否发生

④voidEXTI_ClearITPendingBit(uint32_t EXTI_Line);
//清除中断线上的中断标志位
EXTI_Init()函数
EXTI_Init()函数的定义是:voidEXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);

下面我们用一个使用范例来说明这个函数的使用:
EXTI_InitTypeDef EXTI_InitStructure;

EXTI_InitStructure.EXTI_Line=EXTI_Line15;

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 寄存器
例子设置中断线15 上的中断为下降沿触发。STM32 的外设的初始化都是通过结构体来设置初始值的,结构体EXTI_InitTypeDef的成员变量:

typedef struct
{
uint32_t EXTI_Line;

EXTIMode_TypeDef EXTI_Mode;

EXTITrigger_TypeDef EXTI_Trigger;

FunctionalState EXTI_LineCmd;

}EXTI_InitTypeDef;

从定义可以看出,有4 个参数需要设置。第一个参数是中断线的标号,取值范围为EXTI_Line0~EXTI_Line15。这个函数配置的是某个中断线上的中断参数。第二个参数是中断模式,可选值为中断EXTI_Mode_Interrupt 和事件EXTI_Mode_Event。第三个参数是触发方式,可以是下降沿触发EXTI_Trigger_Falling,上升沿触发EXTI_Trigger_Rising,或者任意电平(上升沿和下降沿)触发EXTI_Trigger_Rising_Falling,最后一个参数就是使能中断线了。
我们设置好中断线和GPIO 映射关系,然后又设置好了中断的触发模式等初始化参数。既然是外部中断,涉及到中断我们当然还要设置NVIC 中断优先级。这里我们就接着上面的范例,设置中断线2 的中断优先级。

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

其结构体NVIC_InitTypeDef的成员变量:
typedefstruct
{
uint8_t NVIC_IRQChannel; //设置中断通道

uint8_t NVIC_IRQChannelPreemptionPriority;//设置响应优先级

uint8_t NVIC_IRQChannelSubPriority; //设置抢占优先级

FunctionalState NVIC_IRQChannelCmd; //使能

}NVIC_InitTypeDef;

从定义可以看出,有4 个参数需要设置。第一个参数是设置中断通道。第二个参数是设置响应优先级。第三个参数是设置抢占优先级,最后一个参数就是使能中断通道

NVIC_PriorityGroupConfig()函数
系统运行后先设置中断优先级分组。调用函数:voidNVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);整个系统执行过程中,只设置一次中断分组。针对每个中断,设置对应的抢占优先级和响应优先级:voidNVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

中断管理方法:对STM32中断进行分组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级值。该分组的设置是由SCB->AIRCR 寄存器的bit10~8 来定义的。

EXTIx_IRQHandler函数
我们配置完中断优先级之后,接着我们要做的就是编写中断服务函数。中断服务函数的名字是在 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 共用中断函数EXTI9_5_IRQHandler,中断线10-15 共用中断函数EXTI15_10_IRQHandler。

在编写中断服务函数的时候会经常使用到两个函数,第一个函数是判断某个中断线上的中断是否发生(标志位是否置位):

ITStatus EXTI_GetITStatus(uint32_tEXTI_Line);

这个函数一般使用在中断服务函数的开头判断中断是否发生。另一个函数是清除某个中断线上的中断标志位:

void EXTI_ClearITPendingBit(uint32_tEXTI_Line);

这个函数一般应用在中断服务函数结束之前, 清除中断标志位。

常用的中断服务函数格式为:

void EXTI3_IRQHandler(void)

{

if(EXTI_GetITStatus(EXTI_Line3)!=RESET)//判断某个线上的中断是否发生

{

中断逻辑…

EXTI_ClearITPendingBit(EXTI_Line3); //清除 LINE 上的中断标志位

}

}

在这里需要说明一下,固件库还提供了两个函数用来判断外部中断状态以及清除外部状态标志位的函数 EXTI_GetFlagStatus 和 EXTI_ClearFlag,他们的作用和前面两个函数的作用类似。只是在 EXTI_GetITStatus 函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而EXTI_GetFlagStatus 直接用来判断状态标志位。

四、程序

使用IO口外部中断的一般步骤:

①初始化IO口为输入。

GPIO_Init();

②开启IO口复用时钟。

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

③设置IO口与中断线的映射关系。

void GPIO_EXTILineConfig();

④初始化线上中断,设置触发条件等。

EXTI_Init();

⑤配置中断分组(NVIC),并使能中断。

NVIC_Init();

⑥编写中断服务函数。

EXTIx_IRQHandler();

⑦清除中断标志位

EXTI_ClearITPendingBit();

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值