STM32 的每個 IO 都可以作為外部中斷的中斷輸入口,這點也是 STM32 的強大之處袜蚕。
GPIO 的管腳 GPIOx.0~GPIOx.15(x=A糟把,B,C牲剃,D遣疯,E,F(xiàn)凿傅,G)分別對應中斷線 0~15缠犀。這樣每個中斷線對應了最多 7 個 IO 口,以線 0 為例:它對應了 GPIOA.0聪舒、GPIOB.0夭坪、GPIOC.0、GPIOD.0过椎、 GPIOE.0、GPIOF.0戏仓、GPIOG.0疚宇。而中斷線每次只能連接到 1 個 IO 口上,這樣就需要通過配置來決定對應的中斷線配置到哪個 GPIO 上了赏殃。
1) 初始化 IO 口為輸入(以GPIOE.2為例)敷待。
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//使能PORTE時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //設(shè)置成上拉輸入
//輸入模式中speed取決于外部頻率,不設(shè)置
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE.2
2) 開啟 AFIO 時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能復用IO功能時鐘
3) 設(shè)置 IO 口與中斷線的映射關(guān)系仁热。
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2); //GPIOE.2與EXTI2相映射
4) 初始化線上中斷榜揖,設(shè)置觸發(fā)條件等。
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line2; //EXTI2抗蠢,取值范圍為EXTI_Line0~EXTI_Line15
EXTI_InitStructure.EXTI_Mode = EXTI_ Mode_Interrupt; //中斷模式举哟,可選值為中斷 EXTI_Mode_Interrupt 和事件 EXTI_Mode_Event
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //觸發(fā)方式,可以是下降沿觸發(fā) EXTI_Trigger_Falling迅矛,上升沿觸發(fā) EXTI_Trigger_Rising妨猩,或者任意電平(上升沿和下降沿)觸發(fā)EXTI_Trigger_Rising_Falling
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能
EXTI_Init(&EXTI_InitStructure); //根據(jù)EXTI_InitStruct中指定的參數(shù)初始化外設(shè)EXTI寄存器
關(guān)于中斷請求和事件的區(qū)別:
http://blog.csdn.net/flydream0/article/details/8208463
5) 配置中斷分組(NVIC),并使能中斷秽褒。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //在主函數(shù)main()中設(shè)置分組壶硅,設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級,2位響應優(yōu)先級
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//外部中斷2销斟,在stm32F10x.h中有定義
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //搶占優(yōu)先級為2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //響應優(yōu)先級為2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
NVIC_IRQChannel的可選參數(shù)如下(在stm32f10x.h中庐椒,不完全):
#ifdef STM32F10X_HD_VL
ADC1_IRQn = 18, /*!< ADC1 global Interrupt */
EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
TIM1_BRK_TIM15_IRQn = 24, /*!< TIM1 Break and TIM15 Interrupts */
TIM1_UP_TIM16_IRQn = 25, /*!< TIM1 Update and TIM16 Interrupts */
TIM1_TRG_COM_TIM17_IRQn = 26, /*!< TIM1 Trigger and Commutation and TIM17 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 */
RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */
CEC_IRQn = 42, /*!< HDMI-CEC Interrupt */
TIM12_IRQn = 43, /*!< TIM12 global Interrupt */
TIM13_IRQn = 44, /*!< TIM13 global Interrupt */
TIM14_IRQn = 45, /*!< TIM14 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 and DAC underrun Interrupt */
TIM7_IRQn = 55, /*!< TIM7 Interrupt */
DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */
DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */
DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */
DMA2_Channel4_5_IRQn = 59, /*!< DMA2 Channel 4 and Channel 5 global Interrupt */
DMA2_Channel5_IRQn = 60 /*!< DMA2 Channel 5 global Interrupt (DMA2 Channel 5 is
mapped at position 60 only if the MISC_REMAP bit in
the AFIO_MAPR2 register is set) */
#endif /* STM32F10X_HD_VL */
6)編寫中斷服務函數(shù)。
void EXTI2_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line2)!=RESET)//判斷EXTI2上的中斷是否發(fā)生
{
//中斷函數(shù)內(nèi)容
EXTI_ClearITPendingBit(EXTI_Line2); //清除LINE2上的中斷標志位
}
}
這里需要說明一下蚂踊,STM32 的 IO 口外部中斷函數(shù)只有 7個约谈,分別為:
//在startup_stm32f10x_hd.s中定義
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
中斷線 0-4 每個中斷線對應一個中斷函數(shù),中斷線 5-9 共用中斷函數(shù) EXTI9_5_IRQHandler,中斷線 10-15 共用中斷函數(shù) EXTI15_10_IRQHandler窗宇。
在最近的一個項目中措伐,用了很多個外部中斷線,剛開始并沒有注意外部中斷 的個數(shù)军俊,天真的以為所有IO口都可以配置為中斷侥加,然后畫板子就直接連接了19根外部中斷,等寫程序的時候發(fā)現(xiàn)粪躬,PA0 PB0 PC0這些共用一個外部中斷線担败,注意是共用,根本就不能同時存在镰官,同一時間只能有一個IO使用這個中斷線提前,初始化的時候誰是最后初始化的,那么這根中斷線就分配給了誰泳唠,這個EXTI9_5這個中斷也是那樣狈网,只不過是共用的中斷函數(shù),而不是共用一個中斷線笨腥,這個可以中斷之后查詢是哪根線觸發(fā)了拓哺,而不是PA9 PB9同時使用這根中斷線,好了脖母,這回我是用程序進行驗證的士鸥,看了很多資料,眾說紛紜谆级,這回是驗證真?zhèn)瘟丝窘福M行枰娜瞬灰霈F(xiàn)我這種低級錯誤。