/*
* 本文中的相关图片来自火哥的教程,只作为随笔记录,无侵权之意
* 21:25:46, 2017-04-08
*/
EXTI:外部中断/事件控制器。STM32F429共有23根,其中EXTI0~EXTI15,分别对应GPIO中的PX0 ~ PX15,另外7根线有如下用途:
(中间省略了EXTI1 ~ EXTI15)
EXTI功能框图如下所示:
按照图中的序号标识,可以清晰的看出外部GPIO引脚上的电平变化是如何传递到内核,即GPIO -> EXTI -> NVIC,并触发相应的中断/事件。NVIC属于内核上的外设,EXTI和GPIO同属于STM32F4XX的片上外设。
举例:按键触发中断控制LED亮灭
分析:分别从GPIO, EXTI以及NVIC和最后的ISR部分,来构建整个程序的功能
如果我们需要使用EXTI和GPIO这两个外设,第一步就需要中RCC(Reset & Clock Control)相关寄存器中使能(ENABLE)相应的时钟,因此需要分别使能实际用到的GPIOA-I中的一个或多个端口时钟;使能EXTI时钟
RCC_AHB1PeriphClockCmd (KEY2_GPIO_CLK, ENABLE); RCC_APB2PeriphClockCmd (RCC_APB2Periph_SYSCFG, ENABLE);
接下来需要配置GPIO的引脚各寄存器,比如输入输出,上下拉等,之后可以调用固件库函数GPIO_Init(Init_Struct)进行初始化。
现在,引脚的相关工作模式已经配置好,如何把PIN与EXTI进行关联?STM32F4有如下说明:
即通过配置寄存器SYSCFG_EXTICRx,可以实现GPIO与EXTI的映射,参考stm32f4xx_syscfg.c Example:
SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE);
接下来就是需要初始化EXTI相关的寄存器,同样最后也是调用EXTI_Init函数对EXTI寄存器进行初始化。
1 // EXTI_DeInit(); 2 EXTI_KEY1_InitStruct.EXTI_Line = EXTI_Line0; 3 EXTI_KEY1_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; 4 EXTI_KEY1_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; 5 EXTI_KEY1_InitStruct.EXTI_LineCmd = ENABLE; 6 7 /*Initiallize the EXTI*/ 8 EXTI_Init(&EXTI_KEY1_InitStruct);
之后进行NVIC初始化,NVIC是嵌套向量中断控制器,掌管着包括内核异常(EXCEPTION)和外部中断(INTERRPUT)在内的相关功能。其中初始化部分,主要包括:确定中断源,确定抢占优先级,确定子优先级,是否使能NVIC_IRQChannel中指定的中断源。
@note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig() function should be called before NVIC_Init() function.
1 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 2 3 NVIC_InitStruct ->NVIC_IRQChannel = EXTI0_IRQn; 4 NVIC_InitStruct ->NVIC_IRQChannelPreemptionPriority = 1; 5 NVIC_InitStruct ->NVIC_IRQChannelSubPriority = 1; 6 NVIC_InitStruct ->NVIC_IRQChannelCmd = ENABLE; 7 8 /* 调用固件库NVIC初始化函数 - misc.c */ 9 NVIC_Init(NVIC_InitStruct);
最后需要装stm32f4xx_it.c中编写相应的ISR
1 /** 2 * @brief This function handles EXTI0 Handler 3 * @param None 4 * @retval None 5 */ 6 void EXTI0_IRQHandler(void){ 7 if(EXTI_GetITStatus(EXTI_Line0) != RESET){ 8 LED1_TOGGLE; 9 EXTI_ClearITPendingBit(EXTI_Line0); 10 } 11 }
附:bsp_exti.c
1 #include "bsp_exti.h" 2 #include "stm32f4xx.h" 3 4 /** 5 * Four Steps to Config A Key Related EXTI Interrupt 6 * S1: Initiallize the GPIOA, PA0 7 * S2: 8 * S3: 9 * S4: 10 * 11 */ 12 13 14 /** 15 * @brief S1: Initiallize the KEY1: PA0. 16 * Initiallize the Key2: PC13 17 * 18 * @note . 19 * 20 * @note . 21 * 22 * @param NONE 23 * This parameter can be one of the following values: 24 * @arg 25 * @arg 26 * 27 * @retval None 28 */ 29 void EXTI_KEY_Config(void){ 30 EXTI_InitTypeDef EXTI_KEY1_InitStruct; 31 GPIO_InitTypeDef GPIO_InitStructure; 32 33 /*?a??KEY1, KEY2 ?à1?μ?GPIOíaéèê±?ó*/ 34 RCC_AHB1PeriphClockCmd (KEY1_GPIO_CLK, ENABLE); 35 RCC_AHB1PeriphClockCmd (KEY2_GPIO_CLK, ENABLE); 36 RCC_APB2PeriphClockCmd (RCC_APB2Periph_SYSCFG, ENABLE); 37 38 /*S3: Initiallize NVIC for EXTI0*/ 39 EXTI_NVIC_Config(); 40 41 /*????òa????μ?GPIOòy??*/ 42 GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN; 43 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; 44 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 45 46 /*μ÷ó??aoˉêy£?ê1ó?é???????μ?GPIO_InitStructure3?ê??ˉGPIO*/ 47 GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure); 48 49 /* Init PC13 for KEY2*/ 50 GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN; 51 GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure); 52 53 /* 54 * Set the SYSCFG_EXTICR1: Connects PA0 with EXTI0 55 * Connects PC13 with EXTI13 56 */ 57 SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); 58 SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); 59 60 /*S2: Initiallize the EXTI for KEY1 which connects to PA0*/ 61 62 // EXTI_DeInit(); 63 EXTI_KEY1_InitStruct.EXTI_Line = EXTI_Line0; 64 EXTI_KEY1_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; 65 EXTI_KEY1_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; 66 EXTI_KEY1_InitStruct.EXTI_LineCmd = ENABLE; 67 68 /*Initiallize the EXTI*/ 69 EXTI_Init(&EXTI_KEY1_InitStruct); 70 71 // EXTI_DeInit(); 72 EXTI_KEY1_InitStruct.EXTI_Line = EXTI_Line13; 73 EXTI_KEY1_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; 74 75 EXTI_KEY1_InitStruct.EXTI_LineCmd = ENABLE; 76 EXTI_Init(&EXTI_KEY1_InitStruct); 77 78 }/*END --EXTI_KEY_Config--*/ 79 80 81 /** 82 * @brief S3: Initiallize the NVIC in order to handle the interrupt 83 * 84 * @note .1 ê1?ü?D?????ó£¨í¨3£óéíaéè?à1???′??÷éè??£? 85 * .2 ?????D??ó??è??·?×飨NVIC_IPRX, SCB->AIRCR£? 86 * .3 3?ê??ˉNVIC_InitTypeDef 87 * .4 ±àD′ISR 88 * @note . 89 * 90 * @param NONE 91 * This parameter can be one of the following values: 92 * @arg 93 * @arg 94 * 95 * @retval None 96 */ 97 static void EXTI_NVIC_Config(void){ 98 99 NVIC_InitTypeDef NVIC_INIT_S; 100 NVIC_InitTypeDef *NVIC_InitStruct = &NVIC_INIT_S; 101 102 /* .2 */ 103 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 104 105 NVIC_InitStruct ->NVIC_IRQChannel = EXTI0_IRQn; 106 NVIC_InitStruct ->NVIC_IRQChannelPreemptionPriority = 1; 107 NVIC_InitStruct ->NVIC_IRQChannelSubPriority = 1; 108 NVIC_InitStruct ->NVIC_IRQChannelCmd = ENABLE; 109 110 /* .3 */ 111 NVIC_Init(NVIC_InitStruct); 112 113 /*Following is for KEY2 PC13*/ 114 NVIC_InitStruct ->NVIC_IRQChannel = EXTI15_10_IRQn; 115 NVIC_Init(NVIC_InitStruct); 116 } 117 118 /** 119 * @brief 120 * 121 * @note . 122 * 123 * @note . 124 * 125 * @param NONE 126 * This parameter can be one of the following values: 127 * @arg 128 * @arg 129 * 130 * @retval None 131 */