第16章 STM32中斷應用概覽本章參考資料《STM32F4xx 中文參考手冊》第十章-中斷和事件,、《 ARM Cortex?-M4F 技術參考手冊》-4.3 章節(jié):NVIC和4.4章節(jié):SCB—4.4.5的AIRCR。 STM32中斷非常強大,,每個外設都可以產生中斷,,所以中斷的講解放在哪一個外設里面去講都不合適,,這里單獨抽出一章來做一個總結性的介紹,這樣在其他章節(jié)涉及到中斷部分的知識我們就不用費很大的篇幅去講解,,只要示意性帶過即可,。 本章如無特別說明,異常就是中斷,,中斷就是異常,,請不要刻意鉆牛角尖較勁。 16.1 異常類型F429在內核水平上搭載了一個異常響應系統(tǒng),,支持為數眾多的系統(tǒng)異常和外部中斷,。其中系統(tǒng)異常有10個,外部中斷有91個,。除了個別異常的優(yōu)先級被定死外,,其它異常的優(yōu)先級都是可編程的。有關具體的系統(tǒng)異常和外部中斷可在標準庫文件stm32f4xx.h這個頭文件查詢到,,在IRQn_Type這個結構體里面包含了F4系列全部的異常聲明,。 表格 12 F429系統(tǒng)異常清單
表格 13 F429外部中斷清單
16.2 NVIC簡介在講如何配置中斷優(yōu)先級之前,我們需要先了解下NVIC,。NVIC是嵌套向量中斷控制器,,控制著整個芯片中斷相關的功能,,它跟內核緊密耦合,,是內核里面的一個外設。但是各個芯片廠商在設計芯片的時候會對Cortex-M4內核里面的NVIC進行裁剪,,把不需要的部分去掉,,所以說STM32的NVIC是Cortex-M4的NVIC的一個子集。 16.2.1 NVIC寄存器簡介在固件庫中,,NVIC的結構體定義可謂是頗有遠慮,,給每個寄存器都預覽了很多位,恐怕為的是日后擴展功能,。不過STM32F429可用不了這么多,,只是用了部分而已,具體使用了多少可參考《 ARM Cortex?-M4F 技術參考手冊》-4.3.11:NVIC寄存器映射,。 代碼 17 NVIC結構體定義,,來自固件庫頭文件:core_cm4.h
在配置中斷的時候我們一般只用ISER、ICER和IP這三個寄存器,,ISER用來使能中斷,,ICER用來失能中斷,,IP用來設置中斷優(yōu)先級。 16.2.2 NVIC 中斷配置固件庫固件庫文件core_cm4.h的最后,,還提供了NVIC的一些函數,,這些函數遵循CMSI規(guī)則,只要是Cortex-M4 的處理器都可以使用,,具體如下: 表格 14 符合CMSIS標準的NVIC庫函數
這些庫函數我們在編程的時候用的都比較少,,甚至基本都不用。在配置中斷的時候我們還有更簡潔的方法,,請看中斷編程小節(jié),。 16.3 優(yōu)先級的定義16.3.1 優(yōu)先級定義在NVIC 有一個專門的寄存器:中斷優(yōu)先級寄存器NVIC_IPRx(在F429中,x=0...90)用來配置外部中斷的優(yōu)先級,,IPR寬度為8bit,,原則上每個外部中斷可配置的優(yōu)先級為0~255,數值越小,,優(yōu)先級越高,。但是絕大多數CM4芯片都會精簡設計,以致實際上支持的優(yōu)先級數減少,,在F429中,,只使用了高4bit,如下所示: 表格 15 F429 使用4bit表達優(yōu)先級
用于表達優(yōu)先級的這4bit,,又被分組成搶占優(yōu)先級和子優(yōu)先級。如果有多個中斷同時響應,,搶占優(yōu)先級高的就會搶占搶占優(yōu)先級低的優(yōu)先得到執(zhí)行,,如果搶占優(yōu)先級相同,就比較子優(yōu)先級,。如果搶占優(yōu)先級和子優(yōu)先級都相同的話,,就比較他們的硬件中斷編號,編號越小,,優(yōu)先級越高,。 16.3.2 優(yōu)先級分組優(yōu)先級的分組由內核外設SCB的應用程序中斷及復位控制寄存器AIRCR的PRIGROUP[10:8]位決定,F429分為了5組,,具體如下:主優(yōu)先級=搶占優(yōu)先級
設置優(yōu)先級分組可調用庫函數NVIC_PriorityGroupConfig()實現,,有關NVIC中斷相關的庫函數都在庫文件misc.c和misc.h中。 代碼 18 中斷優(yōu)先級分組庫函數
表格 16 優(yōu)先級分組真值表
16.4 中斷編程在配置每個中斷的時候一般有3個編程要點: 1,、使能外設某個中斷,,這個具體由每個外設的相關中斷使能位控制。比如串口有發(fā)送完成中斷,,接收完成中斷,,這兩個中斷都由串口控制寄存器的相關中斷使能位控制。 2,、初始化NVIC_InitTypeDef結構體,,配置中斷優(yōu)先級分組,設置搶占優(yōu)先級和子優(yōu)先級,,使能中斷請求,。 代碼 19 NVIC初始化結構體
有關NVIC初始化結構體的成員我們一一解釋下: 1)NVIC_IROChannel:用來設置中斷源,不同的中斷中斷源不一樣,,且不可寫錯,,即使寫錯了程序不會報錯,只會導致不想要中斷,。具體的成員配置可參考stm32f4xx.h頭文件里面的IRQn_Type結構體定義,,這個結構體包含了所有的中斷源。 代碼 20 IRQn_Type中斷源結構體
2)NVIC_IRQChannelPreemptionPriority:搶占優(yōu)先級,具體的值要根據優(yōu)先級分組來確定,,具體參考表格 16 優(yōu)先級分組真值表 ,。 3)NVIC_IRQChannelSubPriority:子優(yōu)先級,具體的值要根據優(yōu)先級分組來確定,,具體參考表格 16 優(yōu)先級分組真值表 ,。 4)NVIC_IRQChannelCmd:中斷使能(ENABLE)或者失能(DISABLE),。操作的是NVIC_ISER和NVIC_ICER這兩個寄存器,。 3、編寫中斷服務函數 在啟動文件startup_stm32f429_439xx.s中我們預先為每個中斷都寫了一個中斷服務函數,,只是這些中斷函數都是為空,,為的只是初始化中斷向量表。實際的中斷服務函數都需要我們重新編寫,,中斷服務函數我們統(tǒng)一寫在stm32f4xx_it.c這個庫文件中,。 關于中斷服務函數的函數名必須跟啟動文件里面預先設置的一樣,如果寫錯,,系統(tǒng)就在中斷向量表中找不到中斷服務函數的入口,,直接跳轉到啟動文件里面預先寫好的空函數,,并且在里面無限循環(huán),實現不了中斷,。 16.5 每課一問1,、庫文件core_cm4.h主要實現了什么?回去認真看庫的源碼 2,、庫文件mics.c和mics.h主要實現了什么,?回去認真看庫的源碼 3、如果實現一次軟件系統(tǒng)復位,,具體是操作哪個寄存器的哪個位實現,?答案:給內核外設SCB的AIRCR寄存器的位2:SYSRESETREQ 寫1即可實現一次系統(tǒng)復位。 第17章 EXTI—外部中斷/事件控制器本章參考資料:《STM32F4xx中文參考手冊》系統(tǒng)配置控制器以及中斷和事件章節(jié),。上一章節(jié)我們已經詳細介紹了NVIC,,對STM32F4xx中斷管理系統(tǒng)有個全局的了解,我們這章的內容是NVIC的實例應用,,也是STM32F4xx控制器非常重要的一個資源,。學習本章時,配合《STM32F4xx中文參考手冊》系統(tǒng)配置控制器以及中斷和事件章節(jié)一起閱讀,,效果會更佳,,特別是涉及到寄存器說明的部分。 特別說明,,本書內容是以STM32F42xxx系列控制器資源講解,。 17.1 EXTI簡介外部中斷/事件控制器(EXTI)管理了控制器的23個中斷/事件線。每個中斷/事件線都對應有一個邊沿檢測器,,可以實現輸入信號的上升沿檢測和下降沿的檢測,。EXTI可以實現對每個中斷/事件線進行單獨配置,可以單獨配置為中斷或者事件,,以及觸發(fā)事件的屬性,。 17.2 EXTI功能框圖EXTI的功能框圖包含了EXTI最核心內容,掌握了功能框圖,,對EXTI就有一個整體的把握,,在編程時就思路就非常清晰。EXTI功能框圖見圖 171,。 在圖 171可以看到很多在信號線上打一個斜杠并標注"23"字樣,,這個表示在控制器內部類似的信號線路有23個,這與EXTI總共有23個中斷/事件線是吻合的,。所以我們只要明白其中一個的原理,,那其他22個線路原理也就知道了。 圖 171 EXTI功能框圖 EXTI可分為兩大部分功能,一個是產生中斷,,另一個是產生事件,,這兩個功能從硬件上就有所不同。 首先我們來看圖 171中紅色虛線指示的電路流程,。它是一個產生中斷的線路,,最終信號流入到NVIC控制器內。 編號1是輸入線,,EXTI控制器有23個中斷/事件輸入線,,這些輸入線可以通過寄存器設置為任意一個GPIO,也可以是一些外設的事件,,這部分內容我們將在后面專門講解,。輸入線一般是存在電平變化的信號。 編號2是一個邊沿檢測電路,,它會根據上升沿觸發(fā)選擇寄存器(EXTI_RTSR)和下降沿觸發(fā)選擇寄存器(EXTI_FTSR)對應位的設置來控制信號觸發(fā),。邊沿檢測電路以輸入線作為信號輸入端,如果檢測到有邊沿跳變就輸出有效信號1給編號3電路,,否則輸出無效信號0,。而EXTI_RTSR和EXTI_FTSR兩個寄存器可以控制器需要檢測哪些類型的電平跳變過程,可以是只有上升沿觸發(fā),、只有下降沿觸發(fā)或者上升沿和下降沿都觸發(fā),。 編號3電路實際就是一個或門電路,它一個輸入來自編號2電路,,另外一輸入來自軟件中斷事件寄存器(EXTI_SWIER),。EXTI_SWIER允許我們通過程序控制就可以啟動中斷/事件線,這在某些地方非常有用,。我們知道或門的作用就是有"就為1,,所以這兩個輸入隨便一個有有效信號1就可以輸出1給編號4和編號6電路。 編號4電路是一個與門電路,,它一個輸入編號3電路,,另外一個輸入來自中斷屏蔽寄存器(EXTI_IMR)。與門電路要求輸入都為1才輸出1,,導致的結果如果EXTI_IMR設置為0時,,那不管編號3電路的輸出信號是1還是0,最終編號4電路輸出的信號都為0,;如果EXTI_IMR設置為1時,,最終編號4電路輸出的信號才由編號3電路的輸出信號決定,,這樣我們可以簡單的控制EXTI_IMR來實現是否產生中斷的目的,。編號4電路輸出的信號會被保存到掛起寄存器(EXTI_PR)內,如果確定編號4電路輸出為1就會把EXTI_PR對應位置1,。 編號5是將EXTI_PR寄存器內容輸出到NVIC內,,從而實現系統(tǒng)中斷事件控制,。 接下來我們來看看綠色虛線指示的電路流程。它是一個產生事件的線路,,最終輸出一個脈沖信號,。 產生事件線路是在編號3電路之后與中斷線路有所不同,之前電路都是共用的,。編號6電路是一個與門,,它一個輸入編號3電路,另外一個輸入來自事件屏蔽寄存器(EXTI_EMR),。如果EXTI_EMR設置為0時,,那不管編號3電路的輸出信號是1還是0,最終編號6電路輸出的信號都為0,;如果EXTI_EMR設置為1時,,最終編號6電路輸出的信號才由編號3電路的輸出信號決定,這樣我們可以簡單的控制EXTI_EMR來實現是否產生事件的目的,。 編號7是一個脈沖發(fā)生器電路,,當它的輸入端,即編號6電路的輸出端,,是一個有效信號1時就會產生一個脈沖,;如果輸入端是無效信號就不會輸出脈沖。 編號8是一個脈沖信號,,就是產生事件的線路最終的產物,,這個脈沖信號可以給其他外設電路使用,比如定時器TIM,、模擬數字轉換器ADC等等,。 產生中斷線路目的是把輸入信號輸入到NVIC,進一步會運行中斷服務函數,,實現功能,,這樣是軟件級的。而產生事件線路目的就是傳輸一個脈沖信號給其他外設使用,,并且是電路級別的信號傳輸,,屬于硬件級的。 另外,,EXTI是在APB2總線上的,,在編程時候需要注意到這點。 17.3 中斷/事件線EXTI有23個中斷/事件線,,每個GPIO都可以被設置為輸入線,,占用EXTI0至EXTI15,還有另外七根用于特定的外設事件,見表 171,。 七根特定外設中斷/事件線由外設觸發(fā),,具體用法參考《STM32F4xx中文參考手冊》中對外設的具體說明。 表 171 EXTI中斷/事件線
EXTI0至EXTI15用于GPIO,,通過編程控制可以實現任意一個GPIO作為EXTI的輸入源,。由表 171可知,EXTI0可以通過SYSCFG外部中斷配置寄存器1(SYSCFG_EXTICR1)的EXTI0[3:0]位選擇配置為PA0,、PB0,、PC0、PD0,、PE0,、PF0、PG0,、PH0或者PI0,,見圖 172。其他EXTI線(EXTI中斷/事件線)使用配置都是類似的,。 圖 172 EXTI0輸入源選擇 17.4 EXTI初始化結構體詳解標準庫函數對每個外設都建立了一個初始化結構體,,比如EXTI_InitTypeDef,結構體成員用于設置外設工作參數,,并由外設初始化配置函數,,比如EXTI_Init()調用,這些設定參數將會設置外設相應的寄存器,,達到配置外設工作環(huán)境的目的,。 初始化結構體和初始化庫函數配合使用是標準庫精髓所在,理解了初始化結構體每個成員意義基本上就可以對該外設運用自如了,。初始化結構體定義在stm32f4xx_exti.h文件中,,初始化庫函數定義在stm32f4xx_exti.c文件中,編程時我們可以結合這兩個文件內注釋使用,。 代碼清單 171 EXTI初始化結構體 1 typedef struct { 2 uint32_t EXTI_Line; // 中斷/事件線 3 EXTIMode_TypeDef EXTI_Mode; // EXTI模式 4 EXTITrigger_TypeDef EXTI_Trigger; // 觸發(fā)事件 5 FunctionalState EXTI_LineCmd; // EXTI控制 6 } EXTI_InitTypeDef; 1) EXTI_Line:EXTI中斷/事件線選擇,,可選EXTI0至EXTI22,可參考表 171選擇,。 2) EXTI_Mode:EXTI模式選擇,,可選為產生中斷(EXTI_Mode_Interrupt)或者產生事件(EXTI_Mode_Event)。 3) EXTI_Trigger:EXTI邊沿觸發(fā)事件,,可選上升沿觸發(fā)(EXTI_Trigger_Rising),、下降沿觸發(fā)( EXTI_Trigger_Falling)或者上升沿和下降沿都觸發(fā)( EXTI_Trigger_Rising_Falling)。 4) EXTI_LineCmd:控制是否使能EXTI線,,可選使能EXTI線(ENABLE)或禁用(DISABLE),。 17.5 外部中斷控制實驗中斷在嵌入式應用中占有非常重要的地位,,幾乎每個控制器都有中斷功能。中斷對保證緊急事件得到第一時間處理是非常重要的 我們設計使用外接的按鍵來作為觸發(fā)源,,使得控制器產生中斷,,并在中斷服務函數中實現控制RGB彩燈的任務,。 17.5.1 硬件設計輕觸按鍵在按下時會使得引腳接通,,通過電路設計可以使得按下時產生電平變化,見圖 171,。 圖 173 按鍵電路設計 17.5.2 軟件設計這里只講解核心的部分代碼,,有些變量的設置,頭文件的包含等并沒有涉及到,,完整的代碼請參考本章配套的工程,。我們創(chuàng)建了兩個文件:bsp_exti.c和bsp_exti.h文件用來存放EXTI驅動程序及相關宏定義,中斷服務函數放在stm32f4xx_it.h文件中,。 1. 編程要點1) 初始化RGB彩燈的GPIO,; 2) 開啟按鍵GPIO時鐘和SYSCFG時鐘; 3) 配置NVIC,; 4) 配置按鍵GPIO為輸入模式,; 5) 將按鍵GPIO連接到EXTI源輸入; 6) 配置按鍵EXTI中斷/事件線,; 7) 編寫EXTI中斷服務函數,。 2. 軟件分析按鍵和EXTI宏定義代碼清單 172 按鍵和EXTI 宏定義 1 //引腳定義 2 /*******************************************************/ 3 #define KEY1_INT_GPIO_PORT GPIOA 4 #define KEY1_INT_GPIO_CLK RCC_AHB1Periph_GPIOA 5 #define KEY1_INT_GPIO_PIN GPIO_Pin_0 6 #define KEY1_INT_EXTI_PORTSOURCE EXTI_PortSourceGPIOA 7 #define KEY1_INT_EXTI_PINSOURCE EXTI_PinSource0 8 #define KEY1_INT_EXTI_LINE EXTI_Line0 9 #define KEY1_INT_EXTI_IRQ EXTI0_IRQn 10 11 #define KEY1_IRQHandler EXTI0_IRQHandler 12 13 #define KEY2_INT_GPIO_PORT GPIOC 14 #define KEY2_INT_GPIO_CLK RCC_AHB1Periph_GPIOC 15 #define KEY2_INT_GPIO_PIN GPIO_Pin_13 16 #define KEY2_INT_EXTI_PORTSOURCE EXTI_PortSourceGPIOC 17 #define KEY2_INT_EXTI_PINSOURCE EXTI_PinSource13 18 #define KEY2_INT_EXTI_LINE EXTI_Line13 19 #define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn 20 21 #define KEY2_IRQHandler EXTI15_10_IRQHandler 使用宏定義方法指定與電路設計相關配置,這對于程序移植或升級非常有用的,。 嵌套向量中斷控制器NVIC配置代碼清單 173 NVIC配置 1 static void NVIC_Configuration(void) 2 { 3 NVIC_InitTypeDef NVIC_InitStructure; 4 5 /* 配置NVIC為優(yōu)先級組1 */ 6 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 7 8 /* 配置中斷源:按鍵1 */ 9 NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ; 10 /* 配置搶占優(yōu)先級:1 */ 11 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 12 /* 配置子優(yōu)先級:1 */ 13 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 14 /* 使能中斷通道 */ 15 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 16 NVIC_Init(&NVIC_InitStructure); 17 18 /* 配置中斷源:按鍵2,,其他使用上面相關配置 */ 19 NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ; 20 NVIC_Init(&NVIC_InitStructure); 21 } 有關NVIC配置問題可參考上一章節(jié)內容,這里不做過多解釋,。 EXTI中斷配置代碼清單 174 EXTI中斷配置 1 void EXTI_Key_Config(void) 2 { 3 GPIO_InitTypeDef GPIO_InitStructure; 4 EXTI_InitTypeDef EXTI_InitStructure; 5 6 /*開啟按鍵GPIO口的時鐘*/ 7 RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK|KEY2_INT_GPIO_CLK ,ENABLE); 8 9 /* 使能 SYSCFG 時鐘,,使用GPIO外部中斷時必須使能SYSCFG時鐘*/ 10 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 11 12 /* 配置 NVIC */ 13 NVIC_Configuration(); 14 15 /* 選擇按鍵1的引腳 */ 16 GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN; 17 /* 設置引腳為輸入模式 */ 18 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; 19 /* 設置引腳不上拉也不下拉 */ 20 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 21 /* 使用上面的結構體初始化按鍵 */ 22 GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure); 23 24 /* 連接 EXTI 中斷源到key1引腳 */ 25 SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, 26 KEY1_INT_EXTI_PINSOURCE); 27 28 /* 選擇 EXTI 中斷源 */ 29 EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE; 30 /* 中斷模式 */ 31 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 32 /* 下降沿觸發(fā) */ 33 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; 34 /* 使能中斷/事件線 */ 35 EXTI_InitStructure.EXTI_LineCmd = ENABLE; 36 EXTI_Init(&EXTI_InitStructure); 37 38 /* 選擇按鍵2的引腳 */ 39 GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN; 40 /* 其他配置與上面相同 */ 41 GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure); 42 43 /* 連接 EXTI 中斷源到key2 引腳 */ 44 SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, 45 KEY2_INT_EXTI_PINSOURCE); 46 47 /* 選擇 EXTI 中斷源 */ 48 EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE; 49 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 50 /* 上升沿觸發(fā) */ 51 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 52 EXTI_InitStructure.EXTI_LineCmd = ENABLE; 53 EXTI_Init(&EXTI_InitStructure); 54 } 首先,使用GPIO_InitTypeDef和EXTI_InitTypeDef結構體定義兩個用于GPIO和EXTI初始化配置的變量,,關于這兩個結構體前面都已經做了詳細的講解,。 使用GPIO之前必須開啟GPIO端口的時鐘;用到EXTI必須開啟SYSCFG時鐘,。 調用NVIC_Configuration函數完成對按鍵1,、按鍵2優(yōu)先級配置并使能中斷通道,。 作為中斷/時間輸入線把GPIO配置為輸入模式,這里不使用上拉或下拉,有外部電路完全決定引腳的狀態(tài),。 SYSCFG_EXTILineConfig函數用來指定中斷/事件線的輸入源,它實際是設定SYSCFG外部中斷配置寄存器的值,,該函數接收兩個參數,,第一個參數指定GPIO端口源,,第二個參數為選擇對應GPIO引腳源編號。 我們的目的是產生中斷,,執(zhí)行中斷服務函數,,EXTI選擇中斷模式,按鍵1使用下降沿觸發(fā)方式,,并使能EXTI線,。 按鍵2基本上采用與按鍵1相關參數配置,只是改為上升沿觸發(fā)方式,。 EXTI中斷服務函數代碼清單 175 EXTI中斷服務函數 1 void KEY1_IRQHandler(void) 2 { 3 //確保是否產生了EXTI Line中斷 4 if (EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) { 5 // LED1 取反 6 LED1_TOGGLE; 7 //清除中斷標志位 8 EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE); 9 } 10 } 11 12 void KEY2_IRQHandler(void) 13 { 14 //確保是否產生了EXTI Line中斷 15 if (EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) { 16 // LED2 取反 17 LED2_TOGGLE; 18 //清除中斷標志位 19 EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE); 20 } 21 } 當中斷發(fā)生時,,對應的中斷服務函數就會被執(zhí)行,我們可以在中斷服務函數實現一些控制,。 一般為確保中斷確實發(fā)生,,我們會在中斷服務函數調用中斷標志位狀態(tài)讀取函數讀取外設中斷標志位并判斷標志位狀態(tài)。 EXTI_GetITStatus函數用來獲取EXTI的中斷標志位狀態(tài),,如果EXTI線有中斷發(fā)生函數返回"SET"否則返回"RESET",。實際上,EXTI_GetITStatus函數是通過讀取EXTI_PR寄存器值來判斷EXTI線狀態(tài)的,。 按鍵1的中斷服務函數我們讓LED1翻轉其狀態(tài),,按鍵2的中斷服務函數我們讓LED2翻轉其狀態(tài)。執(zhí)行任務后需要調用EXTI_ClearITPendingBit函數清除EXTI線的中斷標志位,。 主函數代碼清單 176 主函數 1 int main(void) 2 { 3 /* LED 端口初始化 */ 4 LED_GPIO_Config(); 5 6 /* 初始化EXTI中斷,,按下按鍵會觸發(fā)中斷, 7 * 觸發(fā)中斷會進入stm32f4xx_it.c文件中的函數 8 * KEY1_IRQHandler和KEY2_IRQHandler,,處理中斷,,反轉LED燈。 9 */ 10 EXTI_Key_Config(); 11 12 /* 等待中斷,,由于使用中斷方式,,CPU不用輪詢按鍵 */ 13 while (1) { 14 } 15 } 主函數非常簡單,只有兩個任務函數,。LED_GPIO_Config函數定義在bsp_led.c文件內,,完成RGB彩燈的GPIO初始化配置。EXTI_Key_Config函數完成兩個按鍵的GPIO和EXTI配置,。 17.5.3 下載驗證保證開發(fā)板相關硬件連接正確,,把編譯好的程序下載到開發(fā)板。此時RGB彩色燈是暗的,,如果我們按下開發(fā)板上的按鍵1,,RGB彩燈變亮,再按下按鍵1,,RGB彩燈又變暗,;如果我們按下開發(fā)板上的按鍵2并彈開,,RGB彩燈變亮,再按下開發(fā)板上的KEY2并彈開,,RGB彩燈又變暗,。 每課一問1、 是否可以同時使用PA0和PB0中斷,?如果不可以,,有什么解決方法。 2,、 從硬件角度結合程序分析,,為什么按下按鍵1RGB彩燈就馬上變化,,而按鍵2卻需要按下按鍵再彈開之后RGB彩燈才變化,? |
|