STM32F1的外部中断资源:
STM32F103 的中断控制器支持 19 个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
STM32F103 的19 个外部中断为:
线 0~15:对应外部 IO 口的输入中断。
线 16:连接到 PVD 输出。
线 17:连接到 RTC 闹钟事件。
线 18:连接到 USB 唤醒事件。
STM32 供 IO 口使用的中断线只有 16 个,但是 STM32 的 IO 口却远远不止 16 个,那么 STM32 是怎么把 16 个中断线和 IO 口一一对应起来的呢?
GPIO 的管脚GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 0~15。这样每个中断线对应了最多 7 个 IO 口,而中断线每次只能连接到 1 个 IO 口上,这样就需要通过配置来决定对应的中断线配置到哪个 GPIO 上了。GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
固件库 stm32f10x_exti.h 和 stm32f10x_exti.c
实验代码(按下按键,产生下降沿外部中断):
1 void EXIT_Config(void) 2 { 3 //定义结构体变量 4 GPIO_InitTypeDef GPIO_InitStructure; 5 EXTI_InitTypeDef EXTI_InitStructure; 6 7 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); 9 10 11 NVIC_Config(); //中断优先级配置 12 13 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; 14 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 15 GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC 16 17 //选择EXTI的信号源 18 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//ENABLE AFIO clock外部中断必须打开此时钟 19 20 /* Configure EXTI4 line */ 21 EXTI_InitStructure.EXTI_Line = EXTI_Line5; 22 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 23 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 24 EXTI_InitStructure.EXTI_LineCmd = ENABLE; 25 EXTI_Init(&EXTI_InitStructure); 26 27 GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);/* Connect EXTI0 Line to Pe4pin */ 28 //清除中断标志,防止一打开中断通道就进入中断 29 EXTI_ClearITPendingBit(EXTI_Line5); 30 NVIC_EnableIRQ(EXTI9_5_IRQn);//使能中断 31 } 32 33 34 35 void NVIC_Config(void) 36 { 37 NVIC_InitTypeDef NVIC_InitStructure; 38 39 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//第二组 40 41 NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;//中断源--key2 42 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;//抢占优先级 43 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //响应优先级 44 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能中断通道 45 NVIC_Init(&NVIC_InitStructure); 46 } 47 48 49 //中断服务函数 50 void EXTI9_5_IRQHandler(void) 51 { 52 if(EXTI_GetITStatus(EXTI_Line5)==SET) 53 { 54 // if(!GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_5)) 55 // { 56 // GPIOD->ODR ^= GPIO_Pin_2; 57 // delay_ms(500); 58 // } 59 60 //要服务的函数 61 EXTI_ClearITPendingBit(EXTI_Line5); 62 } 63 }
PS:
EXTI_GetFlagStatus 和EXTI_GetITStatus 函数的区别:
EXTI_GetFlagStatus 和 EXTI_ClearFlag两个函数用来判断外部中断状态以及清除外部状态标志位的函数
EXTI_GetITStatus/EXTI_ClearITPendingBit 函数中会先判断这种中断是否使能,使能了才去判断中断标志位/清除标志位
EXTI_GetFlagStatus/EXTI_ClearFlag 直接用来判断状态标志位 /清除标志位