目录
前言
外部中断(External Interrupt,简称EXTI)是微控制器用于响应外部事件的一种方式,当外部事件发生时(如按键按下、传感器信号变化等),微控制器会暂时停止当前正在执行的程序,转而执行相应的中断服务程序(ISR),处理完中断后再回到原来的程序继续执行。STM32的外部中断是STM32微控制器中一个重要的功能,用于接收和处理来自外部设备的信号或事件,在一定程度上提升了系统的实时性能。STM32的每个GPIO(通用输入输出)端口都支持外部中断功能,这使得STM32能够灵活地处理各种外部事件。
对中断概念不清晰的可以参考:什么是中断-CSDN博客
一、外部中断基础知识
STM32 的每个 IO 都可以作为外部中断 的中断输入口,在STM32F103 的中断控制器支持 19 个外部中断/ 事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。STM32F103 的 19 个外部中断分别为:
线 0~15:对应外部 IO 口的输入中断。
线 16:连接到 PVD 输出。
线 17:连接到 RTC 闹钟事件。
线 18:连接到 USB 唤醒事件。
外部的GPIO引脚与线0~15对应,16条中断线都可以映射给GPIO口,但是每条线只能映射给一个个端口,如0线已经映射给 PA0端口,则就不能再映射给Px0端口(x为B、C、D、E、F等),如下图所示:
STM32中断具有以下特性:
1、每个中断/事件都有独立的触发和屏蔽:可以独立配置每个中断/事件的触发条件和屏蔽状态。
2、每个中断线都有专用的状态位:可以方便地查询和清除中断请求的状态。
3、支持多达20个软件的中断/事件请求:STM32F1系列等型号具有丰富的外部中断资源。
4、 检测脉冲宽度低于APB2时钟宽度的外部信号:能够准确检测快速变化的外部信号。
二、使用步骤
初始化 IO 口为输入:将需要用作外部中断的GPIO口配置为输入模式,并设置合适的上下拉电阻(如果需要)。
开启 AFIO 时钟 :使能GPIO和外部中断控制器的时钟。STM32的外部中断控制器的时钟通常挂载在APB2时钟组下。
设置 IO 口与中断线的映射关系:通过配置AFIO(模拟功能输入输出)的寄存器,将GPIO口与外部中断线连接起来。STM32的GPIO端口号与外部中断号之间存在对应关系,如所有GPIO组的0管脚对应外部中断0。
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
// 如,把PA0与中断线line0连接起来
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
配置中断触发方式:设置外部中断的触发方式(上升沿触发、下降沿触发或上升下降沿触发)。
typedef struct
{
uint32_t EXTI_Line; // 中断线选择,EXTI_Line0~EXTI_Line15
EXTIMode_TypeDef EXTI_Mode; //中断模式,可选值为中断 EXTI_Mode_Interrupt 和事件EXTI_Mode_Event
EXTITrigger_TypeDef EXTI_Trigger; //触发方式,EXTI_Trigger_Falling,EXTI_Trigger_Rising,EXTI_Trigger_Rising_Falling。
FunctionalState EXTI_LineCmd; //是否使能中断线
}EXTI_InitTypeDef;
初始化NVIC(嵌套向量中断控制器):配置中断分组,配置中断的优先级和使能中断。STM32支持抢占式优先级和子优先级,可以根据需要配置中断的优先级。
编写中断服务函数:编写与中断号对应的中断服务函数,并在其中处理中断逻辑,在多条线共用的中断函数中需要添加具体判断。
EXPORT EXTI0_IRQHandler
EXPORT EXTI1_IRQHandler
EXPORT EXTI2_IRQHandler
EXPORT EXTI3_IRQHandler
EXPORT EXTI4_IRQHandler
EXPORT EXTI9_5_IRQHandler
EXPORT EXTI15_10_IRQHandler
三、固件库实现
配置PA0引脚为外部中断,下降沿触发中断。
//外部中断0配置
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE); //使能 PORTA,PORTE 时钟和使能 AFIO 时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IUP; //PA0 设置成输入,上拉
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA0
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line=EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure); //初始化 EXTI 寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级 2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);//初始化 NVIC
}
中断服务函数:
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0)!=RESET)//判断某个线上的中断是否发生
{
//中断任务
EXTI_ClearITPendingBit(EXTI_Line0); //清除 LINE0 上的中断标志位
}
}
其他相关函数:
中断优先级分组,但凡涉及到中断,必须进行中断优先级分组,系统才能进行中断优先级的设定。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置 NVIC 中断分组 2
四、STM32CubeMX实现
同样配置上面固件库的内容。
配置完成后,生成Keil工程,然后在其中编写中断服务函数。
可以在Keil中的任何地方实现该函数,系统会自动搜索识别,如下:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0)
{
//中断任务实现
}
}
在这里,不需要在进行中断标志位的清除,系统已经帮我们处理好了(如上图所示),我们只需要完成中断任务的功能即可,但是我们需要判断中断线,即GPIO端口。
五、总结
1、在配置外部中断时,需要确保GPIO口已经正确配置为输入模式,并且已经使能了相应的时钟。
2、外部中断的触发方式(上升沿、下降沿或上升下降沿)需要根据实际应用场景进行选择。
3、在中断服务函数中,需要尽快处理完中断逻辑并清除中断标志位,以避免中断嵌套或重复触发。
4、中断服务函数应该快进快出,避免长时间在中断里跳不出来,影响系统实时性。
5、尽量不要在中断服务函数里进行延时,特别是HAL_Delay()函数,具体原因请查阅:为什么在中断里调用HAL_Delay时会出现卡死的情况?
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » STM32——外部中断(EXTI)
发表评论 取消回复