电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
STM32第四章-外部中断管理
分 享
扫描二维码分享
STM32第四章-外部中断管理
嵌入式
单片机
C语言
果果小师弟
关注
发布时间: 2020-06-24
丨
阅读: 1642
STM32F4 的每个 IO 都可以作为外部中断的中断输入口,这点也是 STM32F4 的强大之处。STM32F429 的中断控制器支持 22个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。 STM32F429有22个外部中断为,我们这里只看IO口的16个外部中断:**EXTI 线 0~15:对应外部 IO 口的输入中断**。 STM32F4 供 IO 口使用的中断线只有 16 个,但是 STM32F4 的 IO 口却远远不止 16 个,那么 STM32F4 是怎么把 16 个中断线和 IO 口一一对应起来的呢?于是 STM32就这样设计,GPIO 的引脚 GPIOx.0-GPIOx.15(x=A,B,C,D,E,F,G,H,I)分别对应中断线 0~15。**这样每个中断线对应了最多 9 个 IO 口**,以线 0 为例:它对应了 GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0、GPIOG.0,GPIOH.0,GPIOI.0。而中断线每次只能连接到 1 个 IO口上,这样就需要通过配置来决定对应的中断线配置到哪个 GPIO 上了。 >我举一个例子:**我们一个学校(对应一个单片机)有16个老师(对应16根中断线)。但是我们现在有9个班级(GPIOA.0-GPIOI)。每个班级有16个同学(GPIOA_0.....GPIOA_15)。如何让这16位老师负责9个班级一共9X16=144个学生呢? 现在的方法就是:让第1个老师负责每个班级的第1位同学。让第2个老师负责每个班级的第2位同学........,让第16个老师负责每个班级的第16位同学这样就可以了对吧。** 下面我们看看 GPIO跟中断线的映射关系图就容易理解多了: ![中断线的映射关系图](https://img-blog.csdnimg.cn/20200324185135292.png#pic_center) 哈哈哈 是不是通俗易懂!!! 接下来就是写程序了。 ## 程序配置: 1.第一步当然是初始化你的IO口了对吧。比如我们开始写按键的时候是这样写的。 ```c void KEY_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 GPIO_Init(GPIOC, &GPIO_InitStructure); //根据设定参数初始化GPIOC } ``` 2.初始化了IO口,接下来我们要干嘛呢?你不是要让按键按下了之后去干别的事吗?那就**打开IO口的复用功能**: 使能EXTI外设对应的时钟----注意:当使用EXTI外设时,使能的是AFIO时钟,而不是EXTI外设时钟 ```c RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); ``` 3.现在就是要**把中断线和对应的IO口的关系给连接上**! 打开**stm32f4xx_gpio.h**。就看到下面这每个班的16个学生了,整整齐齐的排在这里。因为每一个GPIO都有16个管脚,所以这里最大是从GPIO_PinSource0到GPIO_PinSource15。 ![GPIO_PinSource0-15](https://img-blog.csdnimg.cn/20200324201754760.png#pic_center) 利用**GPIO_EXTILineConfig()**将EXTI线0连接到端口GPIOA的第0个针脚上 具体代码: ``` GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); ``` >注意:如果配置的针脚是4号,那么参数必须是GPIO_PinSource4 如果配置的针脚是3号,那么参数必须是GPIO_PinSource3 4.接下来就是初始化EXTI了:**打开stm32f42x_exti.h**。就看到这16个老师高兴的站在那里,等待着他的学生(还有几个老师也站在那里但是不是负责GPIO的我们先不管他们)。我们要做的就是让第1个老师去负责第一个班级(GPIOA)的第一个同学(GPIOA_0)。因为你是第一个老师要负责第1个班级自然就是负责班级1的第1个同学啦。 ```c typedef enum { EXTI_Mode_Interrupt = 0x00, //中断触发 EXTI_Mode_Event = 0x04 //事件触发 }EXTIMode_TypeDef; typedef enum { EXTI_Trigger_Rising = 0x08, //上升沿触发 EXTI_Trigger_Falling = 0x0C, //下降沿触发 EXTI_Trigger_Rising_Falling = 0x10 //高低电平触发 }EXTITrigger_TypeDef; #define EXTI_Line0 ((uint32_t)0x00001) /@@*!< External interrupt line 0 */ #define EXTI_Line1 ((uint32_t)0x00002) /@@*!< External interrupt line 1 */ #define EXTI_Line2 ((uint32_t)0x00004) /@@*!< External interrupt line 2 */ #define EXTI_Line3 ((uint32_t)0x00008) /@@*!< External interrupt line 3 */ #define EXTI_Line4 ((uint32_t)0x00010) /@@*!< External interrupt line 4 */ #define EXTI_Line5 ((uint32_t)0x00020) /@@*!< External interrupt line 5 */ #define EXTI_Line6 ((uint32_t)0x00040) /@@*!< External interrupt line 6 */ #define EXTI_Line7 ((uint32_t)0x00080) /@@*!< External interrupt line 7 */ #define EXTI_Line8 ((uint32_t)0x00100) /@@*!< External interrupt line 8 */ #define EXTI_Line9 ((uint32_t)0x00200) /@@*!< External interrupt line 9 */ #define EXTI_Line10 ((uint32_t)0x00400) /@@*!< External interrupt line 10 */ #define EXTI_Line11 ((uint32_t)0x00800) /@@*!< External interrupt line 11 */ #define EXTI_Line12 ((uint32_t)0x01000) /@@*!< External interrupt line 12 */ #define EXTI_Line13 ((uint32_t)0x02000) /@@*!< External interrupt line 13 */ #define EXTI_Line14 ((uint32_t)0x04000) /@@*!< External interrupt line 14 */ #define EXTI_Line15 ((uint32_t)0x08000) /@@*!< External interrupt line 15 */ #define EXTI_Line16 ((uint32_t)0x10000) /@@*!< External interrupt line 16 Connected to the PVD Output */ #define EXTI_Line17 ((uint32_t)0x20000) /@@*!< External interrupt line 17 Connected to the RTC Alarm event */ #define EXTI_Line18 ((uint32_t)0x40000) /@@*!< External interrupt line 18 Connected to the USB Device/USB OTG FS Wakeup from suspend event */ #define EXTI_Line19 ((uint32_t)0x80000) /@@*!< External interrupt line 19 Connected to the Ethernet Wakeup event */ ``` 那具体的代码就是下面这样的: ```c void exti_Init(void) { EXTI_InitTypeDef EXTI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //外部中断,需要使能AFIO时钟 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//将EXTI线连接到对应的IO端口上 EXTI_InitStructure.EXTI_Line = EXTI_Line0; //常用的就是EXTI_Line0-EXTI_Line015负责gpio管脚的那几个 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中断线使能 EXTI_Init(&EXTI_InitStructure); //初始化中断 } ``` 到此为止外部中断就写好了。当然这些函数你可以放在一起,就是下面这样: ```c void key_exti_init(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //外部中断,需要使能AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA //注意:如果配置的针脚是0号,那么参数必须是GPIO_PinSource0 如果配置的针脚是3号,那么参数必须是GPIO_PinSource3 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//将EXTI线连接到对应的IO端口上 //注意:如果配置的0号针脚,那么EXTI_Line0是必须的 如果配置的针脚是3号,那么参数必须是EXTI_Line3 EXTI_InitStructure.EXTI_Line = EXTI_Line0; //常用的就是EXTI_Line0-EXTI_Line015负责gpio管脚的那几个 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //初始化中断 } ``` 你以为到次就结束了吗?当然没有。既然有了中断就要有中断优先级。同一时间你爸爸叫你吃饭,正在这时候你女朋友给你打电话。你是先去吃饭了还是先接电话?当然是先接电话对吧。但是单片机可是不知道要先去干嘛。你就必须给他配一下中断优先级。所以就引出了NVIC中断优先级。你要问我NVIC干嘛的,我就告诉你NVIC就是你在同一时间有两个事件来了先干哪一个。这回就有人说了假如我现在有100个事件同时来了先干哪一个呢?不要着急待我细细道来!!! ### 优先级的定义 在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx(在 F429 中,x=0...90)用来配置外部中断的优先级,IPR宽度为 8bit,原则上每个外部中断可配置的优先级为0~255,数值越小,优先级越高。但是绝大多数 CM4芯片都会精简设计,以致实际上支持的优先级数减少,在 F429 中,只使用了高 4bit,就是每个外部中断可配置的优先级为0-16。如下所示: ![优先级的定义](https://img-blog.csdnimg.cn/20200324213417588.png#pic_center) 用于表达优先级的这 4bit,又被分组成**抢占优先级**和**子优先级**。如果有多个中断同时响应,抢占优先级高的就会 抢占 抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。 ### 优先级的分组 ![优先级分组](https://img-blog.csdnimg.cn/20200325155056924.png#pic_center) 这里我们用**阶级来表示抢占优先级**,**用阶层来表示子优先级**,通常我们响应优先级也叫做子优先级。 1.如果我们按照NVIC_PriorityGroup_4这样分组的话,系统就分配了4位抢占优先级。0位响应优先级。就分了16个阶级(2^4=16),0个阶层。![ ](https://img-blog.csdnimg.cn/20200325162740246.png) 比如我来了一个中断叫做外部中断1(EXTI1_IRQn)。他的抢占优先级就可以设置为0-15.响应优先级就只能设置为0,假如在这个时候又来了一个中断叫做外部中断2(EXTI2_IRQn)。他的抢占优先级就可以设置为0-15.响应优先级就只能设置为0。这个个中断可以设置为一样的,也可以设置为不一样的。如果假如够设置抢占优先级为4,那么系统就看哪一个中断县发生,先发生就先执行。 ```c NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); //设置NVIC中断分组4:4位抢占优先级,0位响应优先级 NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//使能外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; //抢占优先级4 因为为分组为4 这里可以设置为0-15 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 ``` 2.如果我们按照NVIC_PriorityGroup_2这样分组的话,系统就分配了2位抢占优先级。2位响应优先级。就分了4个阶级(2^2=4),4个阶层。 ![ ](https://img-blog.csdnimg.cn/20200325163158208.png#pic_center) 比如我来了一个中断叫做外部中断1(EXTI1_IRQn)。他的抢占优先级就不能设置为0-15,范围应该是0-3,响应优先级就只能设置为0,假如在这个时候又来了一个中断叫做外部中断2(EXTI2_IRQn)。他的抢占优先级就设置范围为0-3.响应优先级范围也是0-3。同样的他们的优先级可以设置为一样的,也可以设置为不一样的。如果外部中断1的抢占优先级为2,响应优先级为1,外部中断2的抢占优先级为2,响应优先级为0。那么当两个中断同时发生的时候就会首先响应外部中断2,因为外部中断2响应优先级高于外部中断1.**数值越小优先级越高.** ```c NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//使能外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级2 因为为分组为2 这里可以设置为0-3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级2 因为为分组为4 这里可以设置为0-3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 ``` >一般情况下,系统代码执行过程中,只设置一次中断优先级分组,比如分组2,设置好分组之后一般不会再改变分组。 随意改变分组会导致中断管理混乱,程序出现意想不到的执行结果。换句话说NVIC_PriorityGroupConfig();这个函数在你的整个程序中只能设置一次,这个要切记!!! 3.上面我们说到来了一个外部中断1(EXTI1_IRQn)和外部中断2(EXTI2_IRQn)。根据我在最前面讲的一个故事也就是说,用到的管脚与中断线的序号是要一一对应的,,不管A--H用的哪一组的管脚,PIN1就要对应EXTI1.....PIN15就要对应EXTI15。同时也要对应相应的中断函数,在库函数中EXTI0_IRQn,EXTI1_IRQn,EXTI2_IRQn,EXTI3_IRQn,EXTI4_IRQn,EXTI9_5_IRQn(EXTI5-EXTI9都对应这个中断),EXTI15_10_IRQn(EXITI10-EXTI15都对应这个中断函数)。这些中断通道全都在stm32f4xx.h中用了一个枚举结构体包起来了。想用哪一个找到对应的通道写上就可以了。 ```c typedef enum IRQn { /@@****** Cortex-M4处理器异常数 ****************************************************************/ 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 特定的中断数量 **********************************************************************/ 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 */ DMA1_Stream1_IRQn = 12, /@@*!< DMA1 Stream 1 global Interrupt */ DMA1_Stream2_IRQn = 13, /@@*!< DMA1 Stream 2 global Interrupt */ DMA1_Stream3_IRQn = 14, /@@*!< DMA1 Stream 3 global Interrupt */ DMA1_Stream4_IRQn = 15, /@@*!< DMA1 Stream 4 global Interrupt */ DMA1_Stream5_IRQn = 16, /@@*!< DMA1 Stream 5 global Interrupt */ DMA1_Stream6_IRQn = 17, /@@*!< DMA1 Stream 6 global Interrupt */ ADC_IRQn = 18, /@@*!< ADC1, ADC2 and ADC3 global Interrupts */ #if defined(STM32F429_439xx) CAN1_TX_IRQn = 19, /@@*!< CAN1 TX Interrupt */ CAN1_RX0_IRQn = 20, /@@*!< CAN1 RX0 Interrupt */ CAN1_RX1_IRQn = 21, /@@*!< CAN1 RX1 Interrupt */ CAN1_SCE_IRQn = 22, /@@*!< CAN1 SCE Interrupt */ EXTI9_5_IRQn = 23, /@@*!< External Line[9:5] Interrupts */ TIM1_BRK_TIM9_IRQn = 24, /@@*!< TIM1 Break interrupt and TIM9 global interrupt */ TIM1_UP_TIM10_IRQn = 25, /@@*!< TIM1 Update Interrupt and TIM10 global interrupt */ TIM1_TRG_COM_TIM11_IRQn = 26, /@@*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */ TIM1_CC_IRQn = 27, /@@*!< TIM1 Capture Compare Interrupt */ TIM2_IRQn = 28, /@@*!< TIM2 global Interrupt */ TIM3_IRQn = 29, /@@*!< TIM3 global Interrupt */ TIM4_IRQn = 30, /@@*!< TIM4 global Interrupt */ I2C1_EV_IRQn = 31, /@@*!< I2C1 Event Interrupt */ I2C1_ER_IRQn = 32, /@@*!< I2C1 Error Interrupt */ I2C2_EV_IRQn = 33, /@@*!< I2C2 Event Interrupt */ I2C2_ER_IRQn = 34, /@@*!< I2C2 Error Interrupt */ SPI1_IRQn = 35, /@@*!< SPI1 global Interrupt */ SPI2_IRQn = 36, /@@*!< SPI2 global Interrupt */ USART1_IRQn = 37, /@@*!< USART1 global Interrupt */ USART2_IRQn = 38, /@@*!< USART2 global Interrupt */ USART3_IRQn = 39, /@@*!< USART3 global Interrupt */ EXTI15_10_IRQn = 40, /@@*!< External Line[15:10] Interrupts */ RTC_Alarm_IRQn = 41, /@@*!< RTC Alarm (A and B) through EXTI Line Interrupt */ OTG_FS_WKUP_IRQn = 42, /@@*!< USB OTG FS Wakeup through EXTI line interrupt */ TIM8_BRK_TIM12_IRQn = 43, /@@*!< TIM8 Break Interrupt and TIM12 global interrupt */ TIM8_UP_TIM13_IRQn = 44, /@@*!< TIM8 Update Interrupt and TIM13 global interrupt */ TIM8_TRG_COM_TIM14_IRQn = 45, /@@*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ TIM8_CC_IRQn = 46, /@@*!< TIM8 Capture Compare Interrupt */ DMA1_Stream7_IRQn = 47, /@@*!< DMA1 Stream7 Interrupt */ FMC_IRQn = 48, /@@*!< FMC global Interrupt */ SDIO_IRQn = 49, /@@*!< SDIO global Interrupt */ TIM5_IRQn = 50, /@@*!< TIM5 global Interrupt */ SPI3_IRQn = 51, /@@*!< SPI3 global Interrupt */ UART4_IRQn = 52, /@@*!< UART4 global Interrupt */ UART5_IRQn = 53, /@@*!< UART5 global Interrupt */ TIM6_DAC_IRQn = 54, /@@*!< TIM6 global and DAC1&2 underrun error interrupts */ TIM7_IRQn = 55, /@@*!< TIM7 global interrupt */ DMA2_Stream0_IRQn = 56, /@@*!< DMA2 Stream 0 global Interrupt */ DMA2_Stream1_IRQn = 57, /@@*!< DMA2 Stream 1 global Interrupt */ DMA2_Stream2_IRQn = 58, /@@*!< DMA2 Stream 2 global Interrupt */ DMA2_Stream3_IRQn = 59, /@@*!< DMA2 Stream 3 global Interrupt */ DMA2_Stream4_IRQn = 60, /@@*!< DMA2 Stream 4 global Interrupt */ ETH_IRQn = 61, /@@*!< Ethernet global Interrupt */ ETH_WKUP_IRQn = 62, /@@*!< Ethernet Wakeup through EXTI line Interrupt */ CAN2_TX_IRQn = 63, /@@*!< CAN2 TX Interrupt */ CAN2_RX0_IRQn = 64, /@@*!< CAN2 RX0 Interrupt */ CAN2_RX1_IRQn = 65, /@@*!< CAN2 RX1 Interrupt */ CAN2_SCE_IRQn = 66, /@@*!< CAN2 SCE Interrupt */ OTG_FS_IRQn = 67, /@@*!< USB OTG FS global Interrupt */ DMA2_Stream5_IRQn = 68, /@@*!< DMA2 Stream 5 global interrupt */ DMA2_Stream6_IRQn = 69, /@@*!< DMA2 Stream 6 global interrupt */ DMA2_Stream7_IRQn = 70, /@@*!< DMA2 Stream 7 global interrupt */ USART6_IRQn = 71, /@@*!< USART6 global interrupt */ I2C3_EV_IRQn = 72, /@@*!< I2C3 event interrupt */ I2C3_ER_IRQn = 73, /@@*!< I2C3 error interrupt */ OTG_HS_EP1_OUT_IRQn = 74, /@@*!< USB OTG HS End Point 1 Out global interrupt */ OTG_HS_EP1_IN_IRQn = 75, /@@*!< USB OTG HS End Point 1 In global interrupt */ OTG_HS_WKUP_IRQn = 76, /@@*!< USB OTG HS Wakeup through EXTI interrupt */ OTG_HS_IRQn = 77, /@@*!< USB OTG HS global interrupt */ DCMI_IRQn = 78, /@@*!< DCMI global interrupt */ CRYP_IRQn = 79, /@@*!< CRYP crypto global interrupt */ HASH_RNG_IRQn = 80, /@@*!< Hash and Rng global interrupt */ FPU_IRQn = 81, /@@*!< FPU global interrupt */ UART7_IRQn = 82, /@@*!< UART7 global interrupt */ UART8_IRQn = 83, /@@*!< UART8 global interrupt */ SPI4_IRQn = 84, /@@*!< SPI4 global Interrupt */ SPI5_IRQn = 85, /@@*!< SPI5 global Interrupt */ SPI6_IRQn = 86, /@@*!< SPI6 global Interrupt */ SAI1_IRQn = 87, /@@*!< SAI1 global Interrupt */ LTDC_IRQn = 88, /@@*!< LTDC global Interrupt */ LTDC_ER_IRQn = 89, /@@*!< LTDC Error global Interrupt */ DMA2D_IRQn = 90 /@@*!< DMA2D global Interrupt */ #endif /@@* STM32F429_439xx */ } IRQn_Type; ``` 所以我们结合EXTI和NVIC的代码,就可以整理为 ```c void key_exti_init(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //外部中断,需要使能AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA //注意:如果配置的针脚是0号,那么参数必须是GPIO_PinSource0 如果配置的针脚是3号,那么参数必须是GPIO_PinSource3 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//将EXTI线连接到对应的IO端口上 //注意:如果配置的0号针脚,那么EXTI_Line0是必须的 如果配置的针脚是3号,那么参数必须是EXTI_Line3 EXTI_InitStructure.EXTI_Line = EXTI_Line0; //常用的就是EXTI_Line0-EXTI_Line015负责gpio管脚的那几个 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //初始化中断 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//使能外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级2 因为为分组为2 这里可以设置为0-3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 } ``` 当然为了代码的美观,你可以那关于NVIC的代码,放到一起便于管理。就像这样,就可以清楚的看到响应的顺序 ![ ](https://img-blog.csdnimg.cn/20200325165204789.png) 以上就是所有关于中断和中断管理知识了。这方面不是很难理解,在遇到问题时对看看对应芯片的中文参考手册就可以了。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200325173211993.png#pic_center)
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
果果小师弟
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交