STM32的每個IO都可以作為外部中斷的中斷輸入口。
STM32F103的中斷控制器支持19個外部中斷/事件請求。每個中斷設有狀態為,每個中斷/事件都有獨立的觸發和屏蔽設置。
STM32F103的19個外部中斷為:
EXTI線0~15:對應外部IO口的輸入中斷。
EXTI線16:連接到PVD輸出。(Programmable?Votage?Detector?可編程電壓監測器。連到EXTI的電源電壓檢測(PVD)中斷)
EXTI線17:連接到RTC鬧鐘事件。
EXTI線18:連接到USB喚醒事件。
?
STM32供IO口使用的中斷線只有16個,而STM32的IO口遠超16個。
所以STM32的GPIOx.0~GPIOX.15(x=A,B,C,D,E,F,G)分別對應中斷線0~15。
以線0為例,對應了GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0、GPIOG.0。
從《STM32中文參考手冊》里可以看到映像,如下圖:
但是中斷線每次只能連接到1個IO口上,需要通過配置來指定中斷線配置到哪個GPIO上。
在標準函數庫中,該配置函數為:
/*** @brief Selects the GPIO pin used as EXTI Line.* @param GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines.* This parameter can be GPIO_PortSourceGPIOx where x can be (A..G).* @param GPIO_PinSource: specifies the EXTI line to be configured.* This parameter can be GPIO_PinSourcex where x can be (0..15).* @retval None*/
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
配置示例:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);
GPIO_PinSource2即為EXTI2的線,在庫里定義命名為EXTI_Line2。
EXTI_Line2相關配置如下:
EXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_Line = EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
接著需要配置中斷的優先級:
NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
配置結束后就要編寫中斷服務函數。
需要注意的是,中斷線0~4每個中斷線各自對應一個中斷服務函數
EXPORT EXTI0_IRQHandler [WEAK]
EXPORT EXTI1_IRQHandler [WEAK]
EXPORT EXTI2_IRQHandler [WEAK]
EXPORT EXTI3_IRQHandler [WEAK]
EXPORT EXTI4_IRQHandler [WEAK]
中斷線5~9共用一個中斷服務函數
EXPORT EXTI9_5_IRQHandler [WEAK]
中斷線10~15共用一個中斷服務函數
EXPORT EXTI15_10_IRQHandler [WEAK]
在中斷服務函數里,經常需要使用兩個函數。
1、判斷某個中斷線上的中斷是否發生(即相關標志位是否置位);
2、清除某個中斷線上的中斷標志位。
示例:
void EXTI2_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line2) != RESET){ ...EXTI_ClearITPendingBit(EXTI_Line2);}
}
除了EXTI_GetITStatus之外函數庫還提供了EXTI_GetFlagStatus,兩者的區別是EXTI_GetITStatus會先判斷這種中斷是否使能,使能了才去判斷中斷標志位,而EXTI_GetFlagStatus直接用來判斷狀態標志位。