STM32F103ZET6外部中斷


1、EXTI功能

  外部中斷/事件控制器EXTI管理了STM32的20個中斷/事件線。

  EXTI的功能框圖如下:

  在功能框圖中,可以看到很多在信號線上打了一個斜杠並標注“20”的字樣,這是表示在STM32內部類似的信號線路有20個,也就是EXTI的20個中斷/事件線。

  EXTI可以分為兩大部分功能:

  產生中斷:如功能圖中的紅色線。

  產生事件:如功能圖中的綠色線。

  EXTI中斷功能說明:

  電路1:  

  在功能框圖中,電路1是腳位輸入線,EXTI19個中斷/事件輸入線,這些輸入線可以通過外部中斷配置寄存器AFIO_EXTI1~AFIO_EXTI2設置為任意一個GPIO,也可以是一些外設的事件。輸入線一般是電平變化的信號。

電路2:

  電路2是邊沿檢測電路。該邊沿檢測電路是根據EXTI_RTSR上升沿觸發選擇寄存器和EXTI_FTSR下降沿選擇寄存器的設置來控制信號觸發。

  如果檢測到與EXTI_RTSR和EXTI_FTSR寄存器設置相對應的邊沿跳變信號,就出輸出有效信號到電路3。通過EXTI_RTSR和EXTI_FTSR寄存器,可以設置觸發的信號為:上升沿觸發、下降沿觸發、電平變化觸發(即上升沿和下降沿都可以觸發)。 

電路3:

  電路3是一個或們電路,兩路輸入只要有一路輸入有效信號,則輸出有效信號。

  從功能圖中可以看出,電路3的一路輸入來自電路2的輸出,另一路來自EXTI_SWIER軟件中斷事件寄存器。

  EXTI_SWIER寄存器可以通過程序控制啟動中斷/事件線,即只要在程序中將EXTI_SWIER寄存器的對應位設置為1,那么電路3就會輸出有效信號,這樣就可以實現軟件模擬中斷或事件。

電路4:

  電路4是一個門電路,只有當兩路都輸入有效信號時,電路4才會輸出有效信號。

  電路4的輸入一路來自電路3的輸出,一路來自EXTI_IMR中斷屏蔽寄存器。只有當電路3輸出有效信號,而且EXTI_IMR寄存器的對應位使能,電路4才會輸出有效信號。

  EXTI_IMR寄存器用來使能或屏蔽相應的中斷線。

電路5:

  電路5是將EXTI_PR寄存器的內容輸出到NVIC中,從而實現系統中斷控制。 

  EXTI事件功能說明: 

  EXTI的事件產生線路,最終輸出一個脈沖信號。 

  產生事件的線路是在電路3之后才與產生中斷的線路有所不同,之前的電路都是共用的。

  電路6: 

  電路3產生的有效信號會被輸入到電路6中。電路6是一個門控電路,電路3的輸出和EXTI_EMR事件屏蔽寄存器作為電路6的輸入。只有當電路3輸出有效信號且EXTI_EMR寄存器的相應位使能,電路6才會輸出有效信號。 

  EXTI_EMR寄存器用來使能或屏蔽相應的事件線。

電路7: 

  電路7是一個脈沖發生器電路,當電路6產生一個有效信號時將會輸出到電路7當中,這時電路7就會產生一個脈沖。

電路8: 

  電路8是一個脈沖信號,這個脈沖信號就是電路7產生的脈沖信號。這個脈沖信號可以給其它外設電路使用,比如TIM定時器、ADC模擬數字轉換器等等,這樣的脈沖信號一般用來觸發TIM或者開始ADC轉換。 

  產生中斷線路目的是運行相應的中斷服務函數,實現功能。

  而產生事件的目的是傳輸一個脈沖信號給其它外設使用,而且產生事件的是電路級別的信號傳輸,屬於硬件級。 

2、中斷/事件線

  EXTI有20個中斷/事件線,每個GPIO都可以被設置為輸入線,占用EXTI0和EXTI15,還有4個用於特點的外設事件。它們如下:

    • EXTI0中斷/事件線:輸入由PA0~PI0等組成。
    • EXTI1中斷/事件線:輸入由PA1~PI1等組成。
    • EXTI2中斷/事件線:輸入由PA2~PI2等組成。
    • EXTI3中斷/事件線:輸入由PA3~PI3等組成。
    • EXTI4中斷/事件線:輸入由PA4~PI4等組成。
    • EXTI5中斷/事件線:輸入由PA5~PI5等組成。
    • EXTI6中斷/事件線:輸入由PA6~PI6等組成。
    • EXTI7中斷/事件線:輸入由PA7~PI7等組成。
    • EXTI8中斷/事件線:輸入由PA8~PI8等組成。
    • EXTI9中斷/事件線:輸入由PA9~PI9等組成。
    • EXTI10中斷/事件線:輸入由PA10~PI10等組成。
    • EXTI11中斷/事件線:輸入由PA11~PI11等組成。
    • EXTI12中斷/事件線:輸入由PA12~PI12等組成。
    • EXTI13中斷/事件線:輸入由PA13~PI13等組成。
    • EXTI14中斷/事件線:輸入由PA14~PI15等組成。
    • EXTI15中斷/事件線:輸入由PA15~PI15等組成。
    • EXTI16中斷/事件線:PVD輸出。
    • EXTI17中斷/事件線:RTC鬧鍾事件。
    • EXTI18中斷/事件線:USB喚醒事件。
    • EXTI19中斷/事件線:以太網喚醒事件(只適用互聯型)。

  從上面可以看出,EXTI0到EXTI15都是用GPIO口做為中斷/事件線,需要通過AFIO_EXTICR1到AFIO_EXTICR4這幾個寄存器來配置具體使用哪一個位來作為中斷/事件線。

  比如AFIO_EXTICR1寄存器的bit3~bit0位用來選擇EXTI0的中斷/事件線的輸入腳位,如下:

    • Bit3~bit0 = 0000:則選擇PA0作為EXTI0的輸入腳位。
    • Bit3~bit0 = 0001:則選擇PB0作為EXTI0的輸入腳位。
    • Bit3~bit0 = 0010:則選擇PC0作為EXTI0的輸入腳位。
    • Bit3~bit0 = 0011:則選擇PD0作為EXTI0的輸入腳位。
    • Bit3~bit0 = 0100:則選擇PE0作為EXTI0的輸入腳位。
    • Bit3~bit0 = 0101:則選擇PF0作為EXTI0的輸入腳位。
    • Bit3~bit0 = 0110:則選擇PG0作為EXTI0的輸入腳位。

  其它EXTI也是一樣的配置,不一樣的只是它們的配置位在AFIO_EXTICR1~AFIO_EXITCR4寄存器中的位置不一樣而已。

  AFIO_EXTICR寄存器只有低16位有效,每4個bit配置一個EXTI,一個AFIO_EXTICR可以配置4個EXTI,4個AFIO_EXTICR就可以配置16個EXTI,也就是說AFIO_EXTICR1~AFIO_EXITCR4寄存器剛好可以配置EXTI0~EXTI15的輸入腳位。

  需要特別注意的是,每一個EXIT只能設置一個IO作為輸入線,比如說,如果設置PA0作為EXTI0的輸入線之后,PB0和其它P0口就不能作為EXTI0的輸入線了。

3、EXTI的中斷服務函數

  通過查詢IRQn_Type結構體中的中斷編號,會發現並不是每個外部中斷都有一個對應中斷編號。有一些外部中斷的中斷編號是組合在一起的,如下:

    • EXTI0的中斷編號:EXTI0_IRQn。
    • EXTI1的中斷編號:EXTI1_IRQn。
    • EXTI2的中斷編號:EXTI2_IRQn。
    • EXTI3的中斷編號:EXTI3_IRQn。
    • EXTI4的中斷編號:EXTI4_IRQn。
    • EXTI5~EXTI9的中斷編號:EXTI9_5_IRQn。
    • EXTI10~EXTI5的中斷編號:EXTI15_10_IRQn。

  從上面可以看到,EXTI5~EXTI9的中斷編號是同一個,也就是說EXTI5~EXIT9是共用一個中斷服務函數,如果要區分是哪一個EXTI產生中斷,可以在中斷服務函數內查詢EXTI_PR。EXTI10~EXTI5的中斷也是一樣的。

4、EXTI配置流程

  初始化IO口:

  使能要相應IO的時鍾。

  將IO口配置上拉或下拉或浮空輸入。設置為浮空輸入的時候,腳位外部最好接上拉電阻或下拉電阻,防止IO口狀態不穩而定,而導致頻繁觸發中斷。

  配置IO與中斷線的映射關系:

  由於要配置AFIO_EXTICR1~AFIO_EXITCR4寄存器,所以需要開啟復用功能的時鍾。

  根據IO配置AFIO_EXTICR寄存器的相應位,使IO作為EXTI功能。

  開啟與該IO相對應的中斷/事件線並設置觸發條件:

  通過EXTI_RTSR和EXTI_FTSR寄存器設置外部中斷的觸發條件,配置成上升沿觸發或下降沿觸發或電平變化觸發。還需要通過EXTI_IMR寄存器使能相應的外部中斷的中斷使能位。

  需要注意的是,如果使用外部中單,並設置該中斷的EMR事件使能位的話,會引起軟件仿真不能跳到中斷,而硬件上可以。如果不是這ERM事件使能位的話,軟件仿真就可以進入中斷服務函數,並且硬件上也可以。

  配置NVIC:

  通過NVIC配置EXTI的中斷優先級,並使能中斷。

  編寫中斷服務函數:

  中斷服務函數是必不可少的,如果在代碼里面開啟了中斷,但沒有編寫中斷服務函數,就可以引起硬件錯誤,從而導致程序崩潰。

5、HAL庫初始化EXTI 

  以配置PA0為EXT0為例,代碼如下:

void EXIT_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_NVIC_SetPriority(EXTI0_IRQn,2,1); HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}

  通過設置GPIO_InitStruct.Mode為GPIO_MODE_IT_FALLING,從而區分是設置IO狀態還是設置EXTI功能,這里將PA0配置為下降沿觸發的EXTI0。

  在HAL_GPIO_Init函數中已經開啟了復用功能的時鍾。

  通過HAL_NVIC_SetPriority函數設置EXTI0的搶占優先級和響應優先級。

  通過HAL_NVIC_EnableIRQ函數使能EXIT0中斷。

  中斷服務函數如下:

void EXTI0_IRQHandler(void )
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
    /* EXTI line interrupt detected */
    if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
    {
        __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
        HAL_GPIO_EXTI_Callback(GPIO_Pin);
    }
}

  在EXTI0中斷服務函數中調用HAL_GPIO_EXTI_IRQHandler函數,HAL_GPIO_EXTI_IRQHandler是HAL庫內定義的一個函數,該函數在進入的時候就通過宏清除了中斷標志位,然后通過調用HAL_GPIO_EXTI_Callback回調函數實現中斷服務函數的功能。

  HAL_GPIO_EXTI_Callback回調函數是一個弱定義的函數,可以通過重新定義來覆蓋。

6、使用EXTI0產生軟件中斷

  代碼如下:

void EXTI_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); EXTI->IMR |= 0x01; HAL_NVIC_SetPriority(EXTI0_IRQn,2,1); HAL_NVIC_EnableIRQ(EXTI0_IRQn); while (1) { if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) != 0) { HAL_Delay(20); if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) != 0) { EXTI->SWIER |= 0x01; while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) != 0) { } } } } }

  首先將PA0口設為浮空輸入,外接下拉電阻。

  然后通過EXTI_IMR寄存器設置EXIT0中斷使能。

  通過HAL_NVIC_SetPriority函數設置EXTI0的搶占優先級和響應優先級。

  通過HAL_NVIC_EnableIRQ函數使能EXIT0中斷。

  最后在主循環中不斷檢測PA是否是高電平,如果是高電平,則給EXTI_SWIER寄存器置位bit0位,這樣就會觸發EXTI0中斷,使得程序跑到EXTI0的中斷服務函數中。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM