EXTI—外部中斷/事件控制器


外部中斷/事件控制器(EXTI)管理了控制器的 23 個中斷/事件線。每個中斷/事件線都對
應有一個邊沿檢測器,可以實現輸入信號的上升沿檢測和下降沿的檢測。 EXTI 可以實現對
每個中斷/事件線進行單獨配置,可以單獨配置為中斷或者事件,以及觸發事件的屬性。

EXTI功能框圖
EXTI 的功能框圖包含了 EXTI 最核心內容,掌握了功能框圖,對 EXTI 就有一個整體
的把握,在編程時就思路就非常清晰。 EXTI 功能框圖見圖 17-1
在圖 17-1 可以看到很多在信號線上打一個斜杠並標注“ 23”字樣,這個表示在控制器
內部類似的信號線路有 23 個,這與 EXTI 總共有 23 個中斷/事件線是吻合的。所以我們只
要明白其中一個的原理,那其他 22 個線路原理也就知道了。


EXTI 可分為兩大部分功能,一個是產生中斷,另一個是產生事件,這兩個功能從硬件
上就有所不同。

產生中斷線路目的是把輸入信號輸入到 NVIC,進一步會運行中斷服務函數,實現功
能,這樣是軟件級的。而產生事件線路目的就是傳輸一個脈沖信號給其他外設使用,並且
是電路級別的信號傳輸,屬於硬件級的。
另外, EXTI 是在 APB2 總線上的,在編程時候需要注意到這點。

EXTI 23 個中斷/事件線,每個 GPIO 都可以被設置為輸入線,占用 EXTI0
EXTI15,還有另外七根用於特定的外設事件,見表 17-1
七根特定外設中斷/事件線由外設觸發,具體用法參考《 STM32F4xx 中文參考手冊》
中對外設的具體說明。

 EXTI0 可以通過 SYSCFG 外部中斷配置寄存器
1(SYSCFG_EXTICR1)EXTI0[3:0]位選擇配置為 PA0PB0PC0PD0PE0PF0
PG0PH0 或者 PI0

EXTI初始化結構體詳解
標准庫函數對每個外設都建立了一個初始化結構體,比如 EXTI_InitTypeDef,結構體
成員用於設置外設工作參數,並由外設初始化配置函數,比如 EXTI_Init()調用,這些設定
參數將會設置外設相應的寄存器,達到配置外設工作環境的目的。
初始化結構體和初始化庫函數配合使用是標准庫精髓所在,理解了初始化結構體每個
成員意義基本上就可以對該外設運用自如了。初始化結構體定義在 stm32f4xx_exti.h 文件中,
初始化庫函數定義在 stm32f4xx_exti.c 文件中,編程時我們可以結合這兩個文件內注釋使用。

下面說一下編程框架:

使用 GPIO 之前必須開啟 GPIO 端口的時鍾;用到 EXTI 必須開啟 SYSCFG 時鍾。

 作為中斷/時間輸入線把 GPIO 配置為輸入模式,這里不使用上拉或下拉,由外部電路
完全決定引腳的狀態。

 SYSCFG_EXTILineConfig 函數用來指定中斷/事件線的輸入源,它實際是設定
SYSCFG 外部中斷配置寄存器的值,該函數接收兩個參數,第一個參數指定 GPIO 端口源,
第二個參數為選擇對應 GPIO 引腳源編號。

 

 1 int main(void)
 2 {
 3     /* LED 端口初始化 */
 4     LED_GPIO_Config();
 5       
 6     /* 初始化EXTI中斷,按下按鍵會觸發中斷,
 7   *  觸發中斷會進入stm32f4xx_it.c文件中的函數
 8     *  KEY1_IRQHandler和KEY2_IRQHandler,處理中斷,反轉LED燈。
 9     */
10     EXTI_Key_Config(); 
11     
12     /* 等待中斷,由於使用中斷方式,CPU不用輪詢按鍵 */
13     while(1)                            
14     {
15     }
16 }

 

主函數結構,先初始化硬件LED,用於按鍵中斷控制的效果展示。

然后是 EXTI_Key_Config(); 需要留意一點的函數或者配置加以紅色標注:

 1  /**
 2   * @brief  配置嵌套向量中斷控制器NVIC
 3   * @param  無
 4   * @retval 無
 5   */
 6 static void NVIC_Configuration(void)
 7 {
 8   NVIC_InitTypeDef NVIC_InitStructure;
 9   
10   /* 配置NVIC為優先級組1 */
11   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
12   
13   /* 配置中斷源:按鍵1 */
14   NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
15   /* 配置搶占優先級:1 */
16   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
17   /* 配置子優先級:1 */
18   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
19   /* 使能中斷通道 */
20   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
21   NVIC_Init(&NVIC_InitStructure);
22   
23   /* 配置中斷源:按鍵2,其他使用上面相關配置 */  
24   NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
25   NVIC_Init(&NVIC_InitStructure);
26 }
27 
28  /**
29   * @brief  配置 PA0 為線中斷口,並設置中斷優先級
30   * @param  無
31   * @retval 無
32   */
33 void EXTI_Key_Config(void)
34 {
35     GPIO_InitTypeDef GPIO_InitStructure; 
36     EXTI_InitTypeDef EXTI_InitStructure;
37   
38     /*開啟按鍵GPIO口的時鍾*/
39     RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK|KEY2_INT_GPIO_CLK ,ENABLE);
40   
41   /* 使能 SYSCFG 時鍾 ,使用GPIO外部中斷時必須使能SYSCFG時鍾*/
42   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
43   
44   /* 配置 NVIC */
45   NVIC_Configuration();
46   
47     /* 選擇按鍵1的引腳 */ 
48   GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
49   /* 設置引腳為輸入模式 */ 
50   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;                
51   /* 設置引腳不上拉也不下拉 */
52   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
53   /* 使用上面的結構體初始化按鍵 */
54   GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure); 
55 
56     /* 連接 EXTI 中斷源 到key1引腳 */
57   SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE,KEY1_INT_EXTI_PINSOURCE);
58 
59   /* 選擇 EXTI 中斷源 */
60   EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
61   /* 中斷模式 */
62   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
63   /* 下降沿觸發 */
64   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  
65   /* 使能中斷/事件線 */
66   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
67   EXTI_Init(&EXTI_InitStructure);
68   
69   /* 選擇按鍵2的引腳 */ 
70   GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;  
71   /* 其他配置與上面相同 */
72   GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);      
73 
74     /* 連接 EXTI 中斷源 到key2 引腳 */
75   SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE,KEY2_INT_EXTI_PINSOURCE);
76 
77   /* 選擇 EXTI 中斷源 */
78   EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
79   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
80   /* 上升沿觸發 */
81   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
82   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
83   EXTI_Init(&EXTI_InitStructure);
84 }

 

在stm32f4xx_it.c中編寫中斷服務函數,其中中斷服務函數名要對應啟動文件的中斷向量表,為了可讀性可以用宏給中斷向量表取一個適合中斷目的的名字。

還有一個需要注意的:需要使能 SYSCFG 時鍾 ,使用GPIO外部中斷時必須使能SYSCFG時鍾。

上面是固件庫的函數定義內部,這個是固件庫編程的套路,都是這樣定義某個功能的結構體,然后初始化這個結果體,最后調用一個init函數完成。

固件庫這樣的套路明白之后,編寫應用程序會輕松愉快地多。至於固件庫內部到底是如何實現的,在達到高手水平了再去,畢竟做項目是以速度和質量說話的,固件庫肯定快於寄存器版的,但是想自己寫出庫函數,又不得不去學習寄存器編程,所以都是相輔相成的,先學好固件庫,然后學寄存器版,然后達到自己可以編寫庫,就達到學習目的了。


免責聲明!

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



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