当前位置:首页 > 单片机 > 单片机
[导读]以下总结参考原子STM32开发指南STM32F103 的中断控制器支持 19 个外部中断/事件请求。STM32F103 的19 个外部中断为:线 0~15:对应外部 IO 口的输入中断。线 16:连接到 PVD 输出。线 17:连接到 RTC 闹钟事件。线 1

以下总结参考原子STM32开发指南

STM32F103 的中断控制器支持 19 个外部中断/事件请求。STM32F103 的19 个外部中断为:

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

线 16:连接到 PVD 输出。

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

线 18:连接到 USB 唤醒事件。

每个中断线对应了最多 7 个 IO 口,以线 0 为例:它对应了 GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、 GPIOF.0、 GPIOG.0。

在库函数中,配置 GPIO 与中断线的映射关系的函数 GPIO_EXTILineConfig()来实现的:


voidGPIO_EXTILineConfig(uint8_tGPIO_PortSource,uint8_tGPIO_PinSource);


然后看一下这个函数的使用范例:


GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);//将中断线2与GPIOE映射起来


中断线上中断的初始化是通过函数 EXTI_Init()实现的。EXTI_Init()函数的定义是:


voidEXTI_Init(EXTI_InitTypeDef*EXTI_InitStruct);


我们来看看结构体 EXTI_InitTypeDef 的成员变量:


typedefstruct

{

uint32_tEXTI_Line;

EXTIMode_TypeDefEXTI_Mode;

EXTITrigger_TypeDefEXTI_Trigger;

FunctionalStateEXTI_LineCmd;

}EXTI_InitTypeDef;


第一个参数是中断线的标号,取值范围为EXTI_Line0~EXTI_Line15。


第二个参数是中断模式,可选值为中断 EXTI_Mode_Interrupt 和事件 EXTI_Mode_Event。

第三个参数是触发方式,可以是下降沿触发 EXTI_Trigger_Falling,上升沿触发 EXTI_Trigger_Rising,或者任意电平(上升沿和下降沿)触发EXTI_Trigger_Rising_Falling。

最后一个参数就是使能中断线。

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


EXTI_InitTypeDefEXTI_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

首先要讲解的是中断优先级分组函数 NVIC_PriorityGroupConfig,其函数申明如下:


voidNVIC_PriorityGroupConfig(uint32_tNVIC_PriorityGroup);


这个函数的作用是对中断的优先级进行分组,这个函数在系统中只能被调用一次,一旦分组确定就最好不要更改。


比如我们设置整个系统的中断优先级分组值为 2,那么方法是:


NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


这样就确定了一共为“2 位抢占优先级,2 位响应优先级”。


下面我们讲解一个重要的函数为中断初始化函数 NVIC_Init,其函数申明为:


voidNVIC_Init(NVIC_InitTypeDef*NVIC_InitStruct);


其中 NVIC_InitTypeDef 是一个结构体,我们可以看看结构体的成员变量:


typedefstruct

{

uint8_tNVIC_IRQChannel;

uint8_tNVIC_IRQChannelPreemptionPriority;

uint8_tNVIC_IRQChannelSubPriority;

FunctionalStateNVIC_IRQChannelCmd;

}NVIC_InitTypeDef;


NVIC_InitTypeDef 结构体中间有三个成员变量,这三个成员变量的作用是:


NVIC_IRQChannel:定义初始化的是哪个中断,这个我们可以在 stm32f10x.h 中找到每个中断对应的名字。例如 USART1_IRQn。

NVIC_IRQChannelPreemptionPriority:定义这个中断的抢占优先级别。

NVIC_IRQChannelSubPriority:定义这个中断的子优先级别。

NVIC_IRQChannelCmd:该中断是否使能。

抢占优先级的级别高于响应优先级。而数值越小所代表的优先级就越高。

这里需要注意两点:

第一,如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;第二,高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。而抢占优先级相同的中断,高优先级的响应优先级不可以打断低响应优先级的中断。

结合实例说明一下:假定设置中断优先级组为 2,然后设置中断 3(RTC 中断)的抢占优先级为 2,响应优先级为 1。中断 6(外部中断 0)的抢占优先级为 3,响应优先级为 0。中断 7(外部中断 1)的抢占优先级为 2,响应优先级为 0。那么这 3 个中断的优先级顺序为:中断 7>中断 3>中断 6。

上面例子中的中断 3 和中断 7 都可以打断中断 6 的中断。而中断 7 和中断 3 却不可以相互打断!

我们现在就可以设置中断线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);//中断优先级分组初始化


我们配置完中断优先级之后,接着我们要做的就是编写中断服务函数。中断服务函数的名字是在 MDK 中事先有定义的。这里需要说明一下,STM32 的 IO 口外部中断函数只有 6 个,分别为:


EXPORTEXTI0_IRQHandler

EXPORTEXTI1_IRQHandler

EXPORTEXTI2_IRQHandler

EXPORTEXTI3_IRQHandler

EXPORTEXTI4_IRQHandler

EXPORTEXTI9_5_IRQHandler

EXPORTEXTI15_10_IRQHandler


中断线 0-4 每个中断线对应一个中断函数,中断线 5-9 共用中断函数 EXTI9_5_IRQHandler,中断线 10-15 共用中断函数 EXTI15_10_IRQHandler。 在编写中断服务函数的时候会经常使用到两个函数,第一个函数是判断某个中断线上的中断是否发生(标志位是否置位) :


ITStatusEXTI_GetITStatus(uint32_tEXTI_Line);


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


voidEXTI_ClearITPendingBit(uint32_tEXTI_Line);


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


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


voidEXTI2_IRQHandler(void)

{

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

{

中断逻辑…

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

}

}


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


下面我们再总结一下使用 IO 口外部中断的一般步骤:

1)初始化 IO 口为输入。

2)开启 IO 口复用时钟,设置 IO 口与中断线的映射关系。

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

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

5)编写中断服务函数。

通过以上几个步骤的设置,我们就可以正常使用外部中断了。

注意使用STM32外部中断需要开启AFIO时钟,开启方式为:


RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

在嵌入式开发中,STM32的时钟系统因其灵活性和复杂性成为开发者关注的焦点。然而,看似简单的时钟配置背后,隐藏着诸多易被忽视的陷阱,轻则导致系统不稳定,重则引发硬件损坏。本文从时钟源选择、PLL配置、总线时钟分配等关键环...

关键字: STM32 时钟系统

在嵌入式系统开发中,STM32系列微控制器的内部温度传感器因其低成本、高集成度特性,广泛应用于设备自检、环境监测等场景。然而,受芯片工艺差异和电源噪声影响,其原始数据存在±1.5℃的固有误差。本文从硬件配置、校准算法、软...

关键字: STM32 温度传感器

在能源效率与智能化需求双重驱动下,AC-DC转换器的数字控制技术正经历从传统模拟方案向全数字架构的深刻变革。基于STM32微控制器的PFM(脉冲频率调制)+PWM(脉冲宽度调制)混合调制策略,结合动态电压调整(Dynam...

关键字: AC-DC STM32

当前智能家居产品需求不断增长 ,在这一背景下 ,对现有浇花装置缺陷进行了改进 ,设计出基于STM32单片机的全 自动家用浇花机器人。该设计主要由机械结构和控制系统构成 ,机械结构通过麦克纳姆轮底盘与喷洒装置的结合实现机器...

关键字: STM32 麦克纳姆轮 安全可靠 通过性强

用c++编程似乎是让你的Arduino项目起步的障碍吗?您想要一种更直观的微控制器编程方式吗?那你需要了解一下Visuino!这个图形化编程平台将复杂电子项目的创建变成了拖动和连接块的简单任务。在本文中,我们将带您完成使...

关键字: Visuino Arduino ESP32 STM32

基于STM32与LoRa技术的无线传感网络凭借其低功耗、广覆盖、抗干扰等特性,成为环境监测、工业自动化等场景的核心解决方案。然而,如何在复杂电磁环境中实现高效休眠调度与动态信道优化,成为提升网络能效与可靠性的关键挑战。本...

关键字: STM32 LoRa

在实时控制系统、高速通信协议处理及高精度数据采集等对时间敏感的应用场景中,中断响应延迟的优化直接决定了系统的可靠性与性能上限。STM32系列微控制器凭借其灵活的嵌套向量中断控制器(NVIC)、多通道直接内存访问(DMA)...

关键字: STM32 DMA

数字电源技术向高功率密度、高效率与高动态响应方向加速演进,STM32微控制器凭借其基于DSP库的算法加速能力与对LLC谐振变换器的精准控制架构,成为优化电源动态性能的核心平台。相较于传统模拟控制或通用型数字控制器,STM...

关键字: STM32 数字电源

STM32微控制器凭借其针对电机控制场景的深度优化,成为高精度、高可靠性驱动系统的核心选择。相较于通用型MCU,STM32在电机控制领域的核心优势集中体现在FOC(磁场定向控制)算法的硬件加速引擎与PWM死区时间的动态补...

关键字: STM32 电机控制

无线充电技术加速渗透消费电子与汽车电子领域,基于Qi协议的无线充电发射端开发成为智能设备能量补给的核心课题。传统模拟控制方案存在响应滞后、参数调整困难等问题,而基于STM32的数字PID控制结合FOD(Foreign O...

关键字: STM32 无线充电
关闭