08-STM32外部中断
一、STM32 的外部中断
1. 基本概念
EXTI,即外部中断/事件控制器,是微控制器中一个至关重要的组成部分,它共计包含23个独立的外部中断/事件通道。这些通道各自配备了一个高精度的内部边沿检测器,这一设计使得EXTI能够精准地识别并响应外部信号的变化。无论是信号的上升沿还是下降沿,EXTI都能进行准确的检测,从而触发相应的动作。
每个EXTI通道都具备产生事件或中断的能力,这为用户提供了极大的灵活性。事件模式通常用于需要快速响应但不希望打断当前程序执行流程的场景,而中断模式则适用于需要立即处理外部事件,以确保系统稳定性和响应速度的情况。通过配置EXTI的相关寄存器,用户可以轻松地设定每个通道的检测边沿类型(上升沿、下降沿或两者皆检测)、触发方式(事件或中断)以及优先级等参数。这种高度可配置性使得EXTI能够适应各种不同的应用场景,从简单的按钮按下检测到复杂的外部信号同步,EXTI都能游刃有余地应对。此外,EXTI还支持中断请求的屏蔽和挂起功能,这有助于用户更有效地管理中断资源,避免中断冲突和优先级反转等问题。
总的来说,EXTI以其强大的功能和灵活性,成为了微控制器中不可或缺的一部分,为外部信号的检测和响应提供了可靠而高效的解决方案。
2、中断引脚
多达 140 个 GPIO(STM32F405xx/07xx 和 STM32F415xx/17xx)通过以下方式连接到 16 个外部中断/事件线。(中文参考手册P243) 例如:PA0占用了EXTI0,其他PB0~PI0是不能使用的。EXTIx,其中的x是由引脚决定的
注意:每个GPIO引脚都可以配置为外部中断,必须把GPIO引脚配置为输入模式。和GPIO相关的外部中断线一共有16根,分别为EXTI0~EXTI15。
3、KEY按中断程序设计
把EXTI外设的源文件以及SYSCFG外设的源文件添加到项目工程中,操作如下:
1. 理解KEY电路原理图
KEY0连接PA0
PA0---EXTI0
选择下降沿触发
2.使能GPIOA端口时钟(因为KEY0按键对应的引脚PA0)以及SYSCFG外设时钟(映射)
//使能GPIOA组时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能SYSCFG组时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
3、配置GPIOA端口PA0引脚的模式为输入模式,因为需要利用该引脚检测外部事件
//配置引脚PA0
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //引脚0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; //输入模式
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //根据外面电路来设置即可
GPIO_Init(GPIOA, &GPIO_InitStructure);
4、利用SYSCFG外设的寄存器对GPIOA端口的引脚PA0以及EXTI0建立映射关系(自动建立)
//连接EXTI0到PA0SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
5、定义EXTI外设的结构体变量,对结构体成员进行初始化(编号+模式+边沿+状态)
//配置外部中断控制器EXTI_InitStructure.EXTI_Line = EXTI_Line0; //外部中断线0EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中断线使能EXTI_Init(&EXTI_InitStructure);
6、配置EXTI外设的中断,需要使用NVIC外设管理中断的通道以及中断的优先级
NVIC_InitTypeDef NVIC_InitStructure;//NVIC配置,外部中断线0的通道编号,可在 stm32f4xx.h中查看NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //响应优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道使能NVIC_Init(&NVIC_InitStructure);
7、编写中断服务函数(类似于系统编程中的信号捕获回调函数)
按下按键key0时点亮3led0的灯
void EXTI0_IRQHandler(void)
{//判断中断线状态,如果有中断,中断位标志为1if(EXTI_GetITStatus(EXTI_Line0) == SET){GPIO_ToggleBits(GPIOF, GPIO_Pin_9);//清空中断线EXTI_ClearITPendingBit(EXTI_Line0);}
}
4、NVIC
NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)是ARM Cortex-M4内核的一个关键组件,用于管理中断和异常。STM32F4系列微控制器基于Cortex-M4内核,因此也使用NVIC来处理中断。
中断优先级用于控制中断的执行顺序,出现多个中断请求申请、CPU在服务低优先级的中断服务函数时,出现更高优先级的中断请求,但是不能同时处理,需要有先后顺序之分,要根据实际上的运行环境优先处理重要的中断。
STM32支持两种类型的中断优先级:抢占优先级(pre-emption priority)和响应优先级(subpriority),两者区别如下:
1、抢占优先级与子优先级
抢占优先级:
- 抢占优先级决定了中断之间能否相互抢占。
- 如果一个高抢占优先级的中断发生时,它可以打断一个正在执行的低抢占优先级中断的服务程序。
- 相同抢占优先级的中断之间不能相互抢占。
响应优先级:
- 响应优先级是在相同抢占优先级的中断之间使用的。
- 如果两个中断具有相同的抢占优先级,那么它们将按照响应优先级的高低顺序来执行。
- 子优先级较高的中断不可以打断正在执行的响应优先级较低的中断服务程序。
总结:
抢占优先级 & 响应优先级区别: 抢占优先级重要程度 > 响应优先级
情况1:高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
情况2:抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
情况3:抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
情况4:如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;
2、中断优先级的范围
抢占优先级和子优先级作为任务调度中的关键参数,其设定范围通常都是0-15之间的整数,这一设计既简洁又高效。在这个体系中,数字0被赋予了最高的优先级,它代表着系统中最紧急、最重要、需要立即得到处理的任务。这样的任务往往与系统的稳定性、安全性或实时性紧密相关,因此它们会被系统优先调度执行,以确保系统的正常运行和响应速度。
相反,数字15则代表着最低的优先级,它通常用于那些不那么紧急、可以延后处理的任务。这些任务可能包括一些后台作业、数据整理、日志记录等,它们对系统的即时响应要求不高,因此可以在系统资源充足时再进行处理。
在0-15的优先级范围内,数字越小,优先级越高;数字越大,优先级越低。这种设计使得系统管理员可以根据任务的紧急程度和重要性,为不同的任务分配不同的优先级,从而实现任务的合理调度和资源的高效利用。
此外,抢占优先级和子优先级之间也存在一定的关系。抢占优先级主要用于决定任务在竞争CPU资源时的先后顺序,而子优先级则用于在具有相同抢占优先级的任务之间进一步细分处理的顺序。这种设计使得系统能够更加精细地控制任务的执行顺序,提高系统的整体性能和响应速度。
3、中断优先级的配置
在STM32中,中断优先级通常是通过NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)来配置的。以下是配置中断优先级的基本步骤:
(1)定义优先级分组:STM32允许用户定义中断优先级组,以确定抢占优先级和子优先级的位数分配。优先级组的设置决定了可用的抢占优先级和子优先级的数量。
(2)设置中断优先级:为每个中断设置抢占优先级和子优先级。
4、优先级组的配置
STM32 对中断优先级进行分组,共 5 组,组 0~4,这些分组是用于指定当前M4支持多少级抢占优先级和多少个子(响应)优先级。STM32提供了不同的优先级组配置,如下所示:
优先级组的选择取决于具体的应用需求。例如,如果应用程序需要更多的抢占优先级级别,则可以选择优先级组4,如果需要更多子优先级,则可以选择优先级组0。
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
5、中断通道
中断通道分为外部中断通道与内部中断通道,中断通道由NVIC进行,只有在NVIC当中使能中断通道,CPU才能响应中断
在代码头文件STM32F4xx.h中176行可查看到中断的通道编号
typedef enum IRQn
{
/****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */
/****** STM32 specific Interrupt Numbers **********************************************************************/WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */FLASH_IRQn = 4, /*!< FLASH global Interrupt */RCC_IRQn = 5, /*!< RCC global Interrupt */EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt ...} IRQn_Type;
6、中断嵌套
看上图是有两个中断,若中断函数2比中断函数的优先级高(这里的优先级说的抢占优先级),当代码执行中断函数0时,又响应了中断函数2,则会先执行2的函数,完后再去执行函数1。
总结:
STM32的中断优先级机制允许开发者精细控制中断的执行顺序,这对于实现高效的实时系统非常关键。通过合理配置中断优先级,可以确保重要的中断能够在适当的时候得到及时处理,从而提高系统的响应速度和稳定性。
- 对EXTI中断通道配置完成后,需要编写对应的中断服务函数,中断服务函数的格式固定,如下图:
7、应用场景如:
1.触摸屏点击实时响应
2.手机/电脑的关机键、音量键、静音键