【细说STM32】【九】外部中断

【细说STM32】【九】外部中断
⼀、外部中断/事件控制器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,最后⼀个参数就是使能中断线了。
•NVIC_Init()函数
我们设置好中断线和GPIO 映射关系,然后⼜设置好了中断的触发模式等初始化参数。既然是外部中断,涉及到中断我们当然还要设置NVIC 中断优先级。这⾥我们就接着上⾯的范例,设置中断线2 的中断优先级。
NVIC_InitTypeDefNVIC_InitStructure;
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 来定义的。
比例电磁铁1.a) ⾼优先级的抢占优先级是可以打断正在进⾏的低抢占优先级中断的。
2.b) 抢占优先级相同的中断,⾼响应优先级不可以打断低响应优先级的中断。
信用卡催收系统3.c) 抢占优先级相同的中断,当两个中断同时发⽣的情况下,哪个响应优先级⾼,哪个先执⾏。
蒸汽分水器
4.d) 如果两个中断的抢占优先级和响应优先级都是⼀样的话,则看哪个中断先发⽣就先执⾏
•EXTIx_IRQHandler函数
我们配置完中断优先级之后,接着我们要做的就是编写中断服务函数。中断服务函数的名字是在 MDK 中事先有定义的。这⾥需要说明⼀下, STM32 的 IO ⼝外部中断函数只有 6 个,分别为:
EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_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⼝复⽤时钟。
②开启IO⼝复⽤时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
③设置IO⼝与中断线的映射关系。
void GPIO_EXTILineConfig();
④初始化线上中断,设置触发条件等。
EXTI_Init();
⑤配置中断分组(NVIC),并使能中断。
NVIC_Init();
⑥编写中断服务函数。
EXTIx_IRQHandler();
⑦清除中断标志位
EXTI_ClearITPendingBit();
本例是外部按键中断,外部中断配置主要在EXTIX_Init()函数和EXTI15_10_IRQHandler()函数1)中断初始化配置
voidEXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDefGPIO_InitStructure;
// 按键端⼝初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//使能PORTE时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//KEY1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//设置成上拉输⼊
GPIO_Init(GPIOE,&GPIO_InitStructure);//初始化GPIOE
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复⽤功能时钟
//GPIOE.15中断线以及中断初始化配置下降沿触发
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource15);
EXTI_InitStructure.EXTI_Line= EXTI_Line15; //KEY1

本文发布于:2024-09-21 14:40:39,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/305940.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:中断   函数   设置   断线
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议