本章參考資料:《STM32F4xx中文參考手冊》系統配置控制器以及中斷和事件章節。
上一章節我們已經詳細介紹了NVIC,對STM32F4xx中斷管理系統有個全局的了解,我們這章的內容是NVIC的實例應用,也是STM32F4xx控制器非常重要的一個資源。學習本章時,配合《STM32F4xx中文參考手冊》系統配置控制器以及中斷和事件章節一起閱讀,效果會更佳,特別是涉及到寄存器說明的部分。
特別說明,本書內容是以STM32F42xxx系列控制器資源講解。
17.1 EXTI簡介
外部中斷/事件控制器(EXTI)管理了控制器的23個中斷/事件線。每個中斷/事件線都對應有一個邊沿檢測器,可以實現輸入信號的上升沿檢測和下降沿的檢測。EXTI可以實現對每個中斷/事件線進行單獨配置,可以單獨配置為中斷或者事件,以及觸發事件的屬性。
17.2 EXTI功能框圖
EXTI的功能框圖包含了EXTI最核心內容,掌握了功能框圖,對EXTI就有一個整體的把握,在編程時就思路就非常清晰。EXTI功能框圖見圖 171。
在圖 171可以看到很多在信號線上打一個斜杠并標注"23"字樣,這個表示在控制器內部類似的信號線路有23個,這與EXTI總共有23個中斷/事件線是吻合的。所以我們只要明白其中一個的原理,那其他22個線路原理也就知道了。
圖 171 EXTI功能框圖
EXTI可分為兩大部分功能,一個是產生中斷,另一個是產生事件,這兩個功能從硬件上就有所不同。
首先我們來看圖 171中紅色虛線指示的電路流程。它是一個產生中斷的線路,最終信號流入到NVIC控制器內。
編號1是輸入線,EXTI控制器有23個中斷/事件輸入線,這些輸入線可以通過寄存器設置為任意一個GPIO,也可以是一些外設的事件,這部分內容我們將在后面專門講解。輸入線一般是存在電平變化的信號。
編號2是一個邊沿檢測電路,它會根據上升沿觸發選擇寄存器(EXTI_RTSR)和下降沿觸發選擇寄存器(EXTI_FTSR)對應位的設置來控制信號觸發。邊沿檢測電路以輸入線作為信號輸入端,如果檢測到有邊沿跳變就輸出有效信號1給編號3電路,否則輸出無效信號0。而EXTI_RTSR和EXTI_FTSR兩個寄存器可以控制器需要檢測哪些類型的電平跳變過程,可以是只有上升沿觸發、只有下降沿觸發或者上升沿和下降沿都觸發。
編號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內,從而實現系統中斷事件控制。
接下來我們來看看綠色虛線指示的電路流程。它是一個產生事件的線路,最終輸出一個脈沖信號。
產生事件線路是在編號3電路之后與中斷線路有所不同,之前電路都是共用的。編號6電路是一個與門,它一個輸入編號3電路,另外一個輸入來自事件屏蔽寄存器(EXTI_EMR)。如果EXTI_EMR設置為0時,那不管編號3電路的輸出信號是1還是0,最終編號6電路輸出的信號都為0;如果EXTI_EMR設置為1時,最終編號6電路輸出的信號才由編號3電路的輸出信號決定,這樣我們可以簡單的控制EXTI_EMR來實現是否產生事件的目的。
編號7是一個脈沖發生器電路,當它的輸入端,即編號6電路的輸出端,是一個有效信號1時就會產生一個脈沖;如果輸入端是無效信號就不會輸出脈沖。
編號8是一個脈沖信號,就是產生事件的線路最終的產物,這個脈沖信號可以給其他外設電路使用,比如定時器TIM、模擬數字轉換器ADC等等。
產生中斷線路目的是把輸入信號輸入到NVIC,進一步會運行中斷服務函數,實現功能,這樣是軟件級的。而產生事件線路目的就是傳輸一個脈沖信號給其他外設使用,并且是電路級別的信號傳輸,屬于硬件級的。
另外,EXTI是在APB2總線上的,在編程時候需要注意到這點。
17.3 中斷/事件線
EXTI有23個中斷/事件線,每個GPIO都可以被設置為輸入線,占用EXTI0至EXTI15,還有另外七根用于特定的外設事件,見表 171。
七根特定外設中斷/事件線由外設觸發,具體用法參考《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()調用,這些設定參數將會設置外設相應的寄存器,達到配置外設工作環境的目的。
初始化結構體和初始化庫函數配合使用是標準庫精髓所在,理解了初始化結構體每個成員意義基本上就可以對該外設運用自如了。初始化結構體定義在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; // 觸發事件
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邊沿觸發事件,可選上升沿觸發(EXTI_Trigger_Rising)、下降沿觸發( EXTI_Trigger_Falling)或者上升沿和下降沿都觸發( EXTI_Trigger_Rising_Falling)。
4) EXTI_LineCmd:控制是否使能EXTI線,可選使能EXTI線(ENABLE)或禁用(DISABLE)。
17.5 外部中斷控制實驗
中斷在嵌入式應用中占有非常重要的地位,幾乎每個控制器都有中斷功能。中斷對保證緊急事件得到第一時間處理是非常重要的
我們設計使用外接的按鍵來作為觸發源,使得控制器產生中斷,并在中斷服務函數中實現控制RGB彩燈的任務。
17.5.1 硬件設計
輕觸按鍵在按下時會使得引腳接通,通過電路設計可以使得按下時產生電平變化,見圖 171。
圖 173 按鍵電路設計
17.5.2 軟件設計
這里只講解核心的部分代碼,有些變量的設置,頭文件的包含等并沒有涉及到,完整的代碼請參考本章配套的工程。我們創建了兩個文件: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為優先級組1 */
6 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
7
8 /* 配置中斷源:按鍵1 */
9 NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
10 /* 配置搶占優先級:1 */
11 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
12 /* 配置子優先級: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配置問題可參考上一章節內容,這里不做過多解釋。
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 /* 下降沿觸發 */
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 /* 上升沿觸發 */
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優先級配置并使能中斷通道。
作為中斷/時間輸入線把GPIO配置為輸入模式,這里不使用上拉或下拉,有外部電路完全決定引腳的狀態。
SYSCFG_EXTILineConfig函數用來指定中斷/事件線的輸入源,它實際是設定SYSCFG外部中斷配置寄存器的值,該函數接收兩個參數,第一個參數指定GPIO端口源,第二個參數為選擇對應GPIO引腳源編號。
我們的目的是產生中斷,執行中斷服務函數,EXTI選擇中斷模式,按鍵1使用下降沿觸發方式,并使能EXTI線。
按鍵2基本上采用與按鍵1相關參數配置,只是改為上升沿觸發方式。
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 }
當中斷發生時,對應的中斷服務函數就會被執行,我們可以在中斷服務函數實現一些控制。
一般為確保中斷確實發生,我們會在中斷服務函數調用中斷標志位狀態讀取函數讀取外設中斷標志位并判斷標志位狀態。
EXTI_GetITStatus函數用來獲取EXTI的中斷標志位狀態,如果EXTI線有中斷發生函數返回"SET"否則返回"RESET"。實際上,EXTI_GetITStatus函數是通過讀取EXTI_PR寄存器值來判斷EXTI線狀態的。
按鍵1的中斷服務函數我們讓LED1翻轉其狀態,按鍵2的中斷服務函數我們讓LED2翻轉其狀態。執行任務后需要調用EXTI_ClearITPendingBit函數清除EXTI線的中斷標志位。
主函數
代碼清單 176 主函數
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 }
主函數非常簡單,只有兩個任務函數。LED_GPIO_Config函數定義在bsp_led.c文件內,完成RGB彩燈的GPIO初始化配置。EXTI_Key_Config函數完成兩個按鍵的GPIO和EXTI配置。
17.5.3 下載驗證
保證開發板相關硬件連接正確,把編譯好的程序下載到開發板。此時RGB彩色燈是暗的,如果我們按下開發板上的按鍵1,RGB彩燈變亮,再按下按鍵1,RGB彩燈又變暗;如果我們按下開發板上的按鍵2并彈開,RGB彩燈變亮,再按下開發板上的KEY2并彈開,RGB彩燈又變暗。
上一篇:第18章 SysTick—系統定時器—零死角玩轉STM32-F429系列
下一篇:第16章 STM32中斷應用概覽—零死角玩轉STM32-F429系列
推薦閱讀
史海拾趣
Cal Test Electronics公司成立于1995年,當時正值電子配件和測試產品市場的快速發展期。創始人憑借對電子行業的深刻理解和敏銳的市場洞察力,決定專注于這一領域。初創時期,公司面臨著資金短缺、市場競爭激烈等諸多挑戰,但創始人帶領團隊通過技術創新和成本控制,逐步在市場上站穩腳跟。他們不斷研發出符合市場需求的高品質產品,贏得了客戶的信任和支持。
隨著公司的發展,Cal Test Electronics逐漸與B&K Precision建立了緊密的合作關系。作為姊妹公司,雙方在技術研發、產品制造和市場推廣等方面展開了深度合作。這種共生關系不僅為Cal Test Electronics帶來了更多的資源和支持,也使其在電子配件和測試產品領域的影響力逐漸擴大。通過共享技術和市場資源,雙方共同推動了行業的發展。
近年來,隨著國家對集成電路產業的重視和支持力度的不斷加大,芯茂微電子也積極響應國家號召,致力于推動國產集成電路產業的發展和自主創新。公司加強了對核心技術的研究和投入,積極引進和培養高端人才,加強與國內外知名企業和研究機構的合作與交流。同時,公司也積極參與國家重大科研項目和產業化項目,為推動我國集成電路產業的發展和自主創新做出了積極貢獻。這些努力不僅提升了芯茂微電子的技術實力和市場競爭力,也為我國集成電路產業的發展注入了新的活力和動力。
以上五個故事僅代表芯茂微電子在電子行業發展過程中的一部分經歷和成就。隨著公司的不斷發展和壯大,相信未來還會有更多精彩的故事等待我們去發現和書寫。
近年來,隨著國家對集成電路產業的重視和支持力度的不斷加大,芯茂微電子也積極響應國家號召,致力于推動國產集成電路產業的發展和自主創新。公司加強了對核心技術的研究和投入,積極引進和培養高端人才,加強與國內外知名企業和研究機構的合作與交流。同時,公司也積極參與國家重大科研項目和產業化項目,為推動我國集成電路產業的發展和自主創新做出了積極貢獻。這些努力不僅提升了芯茂微電子的技術實力和市場競爭力,也為我國集成電路產業的發展注入了新的活力和動力。
以上五個故事僅代表芯茂微電子在電子行業發展過程中的一部分經歷和成就。隨著公司的不斷發展和壯大,相信未來還會有更多精彩的故事等待我們去發現和書寫。
隨著市場競爭的日益激烈和技術創新的加速推進,芯茂微電子也面臨著越來越多的挑戰和機遇。面對這些挑戰,公司始終堅持不懈地推進技術創新和產品研發,不斷提升自身的核心競爭力和市場地位。同時,公司也積極尋求新的市場機遇和合作伙伴,不斷拓展業務領域和市場空間。正是這種對挑戰和機遇的積極應對和堅持不懈的努力,讓芯茂微電子在電子行業中不斷發展壯大。
在電子行業的早期,Advanced Photonix以其卓越的光學技術脫穎而出。公司創始團隊由一群富有遠見的科學家和工程師組成,他們專注于研發高速光電子和高性能的光纖測試產品。經過無數次的實驗和試錯,團隊終于成功開發出一種具有創新性的光纖傳感技術,這一技術為電信行業提供了前所未有的分布式光纖傳感解決方案。這一技術突破不僅為Advanced Photonix贏得了市場聲譽,也奠定了公司在電子行業的重要地位。
摘要:介紹用MCS-51系列單片機控制手機收發短信息的原理、硬件電路、PDU數據格式和符合GSM07.05協議要求的短信息發送/接收程序,同時給出了一個應用實例。 關鍵詞:單片機 短信息 PDU GSM 接口 GSM(Global System for Mobile comm ...… 查看全部問答∨ |
|
E:\\singlechip\\example\\Picture1.png 如上圖所示,如何在isis中打開cpu source code窗口 謝謝… 查看全部問答∨ |
|
假設我現在有一個基于Arm核的單片機,并且有了一個基于這款單片機的開發平臺。現在想增加一塊多媒體芯片(比如中芯微968或者簡單些的芯片)來擴展一些功能,接線配置方面的事情我已經做好了,假設我用CS3作為片選。我不解的是:我用什么方法來讀寫多 ...… 查看全部問答∨ |
從我進實驗室就跟著去做了軍品,到現在有兩年時間了。芯片要求很苛刻,很少有國產的芯片;大都是訂購從國外郵來,價格貴時間長都不說,問題是要看人家臉色,明明網站上有銷售的就說訂不到。 &nb ...… 查看全部問答∨ |
我現在有5組(每組參數若干個)參數要存。主存儲區只分了2段,只好再占用程序存儲區,F600(起始)段,F800段和FC00段。 這樣做太浪費了。但由于每組參數設置和存取要分開。而flash又要段擦除,我現在只好一段只存一組參數。而程序存儲區本壘就已經 ...… 查看全部問答∨ |