STM32之外部中斷 EXTI

STM32之外部中斷 EXTI

STM32中斷控制線支持19個外部中斷/事件請求,每個中斷都有對應狀態位和獨立的觸發與屏蔽設置。STM32F103的19個外部中斷爲:

線0-15:對應GPIO口的輸入中斷。
線16:連接到PVD輸出(掉電檢測,掉電時可立即保存重要數據作用)。
線17:連接RTC鬧鐘事件。 線18:連接到USB喚醒事件

STM32的每個IO口都可以作爲外部中斷源的輸入端,而IO口使用的中斷線只有16根,且引腳GPIOx.0~GPIOx.15(x=A~G)分別對應中斷線0-15.這樣每個中斷線對應了7個IO口。如線0對應引腳GPIOA.0/GPIOB.0/GPIOC.0/GPIOD.0/GPIOE.0/GPIOF.0/GPIOG.0,但是每個中斷線每次只能連接到1個IO口上。即同一時刻EXTIx只能響應一個端口的事件觸發,不能同時響應所有IO端口的事件,但可以分時複用。

EXTI TO GPIO

*1、GPIO與中斷映射配置通過函數來實現

void GPIO_EXTILineConfig ( uint8_t  GPIO_PortSource,uint8_t  GPIO_PinSource );

例如

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE , GPIO_PinSource2);

即外部中斷線2就和GPIOE映射起來了,顯然是GPIOE.2連接EXTI2中斷線。
設置中斷觸發方式:

void EXTI_Init( EXTI_InitTypeDef * EXTI_InitStruct )

例如設置中斷線line4的中斷爲下降沿觸發

EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line4;//選擇中斷線4,即EXTI4
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中斷模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿觸發
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中斷使能
EXTI_Init(&EXTI_InitStructure); 
//根據EXTI_InitStruct結構體中指定的參數初始化外設 EXTI 寄存器

設置好了中斷線和GPIO的映射關係,然後又設置好了中斷的觸發模式等參數,涉及到中斷,當然不能忘了設置中斷控制體NVIC的中斷優先級。

2、設置NVIC的中斷優先級

NVIC_InitTypeDef     NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能外部中斷通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; 
//搶佔優先級 2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子優先級 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中斷通道
NVIC_Init(&NVIC_InitStructure); //中斷優先級分組初始化

3、 配置完中斷優先級後,需要編寫中斷服務程序

stm32f10x_it.c文件是專門用來存放中斷服務函數的。文件中默認只有幾個關於系統異常的中斷服務函數,而且都是空函數,在需要的時候自行編寫。相信部分像我一樣的初學者會有疑問,中斷服務函數的名稱可以自己定義嗎?不行。中斷服務程序的名字必須要與啓動文件startup_stm32f10x_hd.s中的中斷向量表定義的一致。
需要注意的一點,IO口16個外部中斷只有7個函數名:

EXTI0_IRQHandler    ;EXTI Line0
EXTI1_IRQHandler    ;EXTI Line1
EXTI2_IRQHandler    ;EXTI Line2
EXTI3_IRQHandler    ;EXTI Line3
EXTI4_IRQHandler    ;EXTI Line4

EXTI9_5_IRQHandler  ;EXTI Line9..5
EXTI15_10_IRQHandler;EXTI Line15..10

中斷線在5後就不能單獨命名,如果寫成EXTI5_IRQHandler…編譯器是不會報錯的,不過中斷服務程序不能正常工作。

編寫中斷服務函數經常需要使用兩個函數

ITStatus EXTI_GetITStatus(uint32_t  EXTI_line);
//放在中斷服務程序開頭,檢測中斷標誌位
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)//放在函數的結尾

第一個是判斷某個中斷線上的中斷是否發生(即標誌位是否置位)
第二個是清除中斷線上的標誌位(即清除標誌位)

常用的外部中斷服務程序格式

格式一:

void EXTI4_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line4) != RESET)//判斷是否置位
        Dosomething();//執行中斷事件
    EXTI_ClearITpendingBit(EXTI_Line4);//清除Line4標誌位
}

格式二:

void EXTI_IRQHandler(void)
{
    if(EXTI_GetFlagStatus(EXTI_Line4) != RESET)
        Dosomething();
    EXTI_ClearFlag(EXTI_Line4);
}

EXTI_GetITStatus() 會先判斷中斷該中斷是否使能,使能了的話在判斷該標誌位是否置位;而EXTI_GetFlagStatus()會直接判斷中斷標誌位是否置位(所以顯得馬虎一點)。一般情況下首選EXTI_GetITStatus().

關於外部中斷EXTI大概就這些了,其他的還要靠自己去動手操作才能掌握更多。

                                        -- From #IRONMAN#
                                        -- 4/24/2017
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章