STM32第四章-外部中断管理

STM32F4 的每一个 IO 均可以做为外部中断的中断输入口,这点也是 STM32F4 的强大之处。STM32F429 的中断控制器支持 22个外部中断/事件请求。每一个中断设有状态位,每一个中断/事件都有独立的触发和屏蔽设置。markdown

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 上了。ui

我举一个例子:咱们一个学校(对应一个单片机)有16个老师(对应16根中断线)。可是咱们如今有9个班级(GPIOA.0-GPIOI)。每一个班级有16个同窗(GPIOA_0.....GPIOA_15)。如何让这16位老师负责9个班级一共9X16=144个学生呢? 如今的方法就是:让第1个老师负责每一个班级的第1位同窗。让第2个老师负责每一个班级的第2位同窗........,让第16个老师负责每一个班级的第16位同窗这样就能够了对吧。spa

下面咱们看看 GPIO跟中断线的映射关系图就容易理解多了: 中断线的映射关系图 哈哈哈 是否是通俗易懂!!!设计

接下来就是写程序了。3d

程序配置

1.第一步固然是初始化你的IO口了对吧。好比咱们开始写按键的时候是这样写的。code

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外设时钟orm

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
复制代码

3.如今就是要把中断线和对应的IO口的关系给链接上! 打开stm32f4xx_gpio.h。就看到下面这每一个班的16个学生了,整整齐齐的排在这里。由于每个GPIO都有16个管脚,因此这里最大是从GPIO_PinSource0到GPIO_PinSource15。 GPIO_PinSource0-15 利用**GPIO_EXTILineConfig()**将EXTI线0链接到端口GPIOA的第0个针脚上 具体代码:事件

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
复制代码

注意:若是配置的针脚是4号,那么参数必须是GPIO_PinSource4 若是配置的针脚是3号,那么参数必须是GPIO_PinSource3ip

4.接下来就是初始化EXTI了:打开stm32f42x_exti.h。就看到这16个老师高兴的站在那里,等待着他的学生(还有几个老师也站在那里可是不是负责GPIO的咱们先无论他们)。咱们要作的就是让第1个老师去负责第一个班级(GPIOA)的第一个同窗(GPIOA_0)。由于你是第一个老师要负责第1个班级天然就是负责班级1的第1个同窗啦。

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 */
复制代码

那具体的代码就是下面这样的:

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); //初始化中断
}
复制代码

到此为止外部中断就写好了。固然这些函数你能够放在一块儿,就是下面这样:

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。以下所示: 优先级的定义 用于表达优先级的这 4bit,又被分组成抢占优先级子优先级。若是有多个中断同时响应,抢占优先级高的就会 抢占 抢占优先级低的优先获得执行,若是抢占优先级相同,就比较子优先级。若是抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。

优先级的分组

优先级分组 这里咱们用阶级来表示抢占优先级用阶层来表示子优先级,一般咱们响应优先级也叫作子优先级。 1.若是咱们按照NVIC_PriorityGroup_4这样分组的话,系统就分配了4位抢占优先级。0位响应优先级。就分了16个阶级(2^4=16),0个阶层。 好比我来了一个中断叫作外部中断1(EXTI1_IRQn)。他的抢占优先级就能够设置为0-15.响应优先级就只能设置为0,假如在这个时候又来了一个中断叫作外部中断2(EXTI2_IRQn)。他的抢占优先级就能够设置为0-15.响应优先级就只能设置为0。这个个中断能够设置为同样的,也能够设置为不同的。若是假如够设置抢占优先级为4,那么系统就看哪个中断县发生,先发生就先执行。

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个阶层。 好比我来了一个中断叫作外部中断1(EXTI1_IRQn)。他的抢占优先级就不能设置为0-15,范围应该是0-3,响应优先级就只能设置为0,假如在这个时候又来了一个中断叫作外部中断2(EXTI2_IRQn)。他的抢占优先级就设置范围为0-3.响应优先级范围也是0-3。一样的他们的优先级能够设置为同样的,也能够设置为不同的。若是外部中断1的抢占优先级为2,响应优先级为1,外部中断2的抢占优先级为2,响应优先级为0。那么当两个中断同时发生的时候就会首先响应外部中断2,由于外部中断2响应优先级高于外部中断1.数值越小优先级越高.

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中用了一个枚举结构体包起来了。想用哪个找到对应的通道写上就能够了。

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的代码,就能够整理为

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的代码,放到一块儿便于管理。就像这样,就能够清楚的看到响应的顺序 以上就是全部关于中断和中断管理知识了。这方面不是很难理解,在遇到问题时对看看对应芯片的中文参考手册就能够了。

相关文章
相关标签/搜索