RoboMaster電控培訓(三)中斷


RM電控入門(三)中斷

  今天我們來學習一下中斷,中斷是嵌入式開發中必不可少的一個環節,也是提高程序運行效率的法寶,實際上中斷是實現多線程設計的必要條件,希望大家通過本篇文章,能更好地理解中斷的內涵和本質。

 

為什么要用中斷

  通常我們可能會先問:什么是中斷?但是今天我想讓大家想一想為什么我們需要用到中斷。上一篇文章(GPIO)中我說到,大多數功能語句都是放在while(1)的死循環中不斷執行,只有少部分只需要執行一次的初始化代碼放在while循環外。那么這種對信號處理的方式我們稱之為輪詢方式,也就是不斷地訪問一個信號的端口,看看有沒有信號進入,有再進行處理 。舉個買火車票例子,在售票窗口人都會排隊買票,那售票員挨個處理的這種方式就可以近似看作是輪詢,那假如是春運時間,排隊的隊伍是相當長,很不幸你的車馬上就要發車了但是如果還是排隊的話你肯定是上不了車了。所以輪詢方式在處理事項不多(排隊的人少)且每個事項花費時長不長(每個人很快就能處理完)的情況下是不會出現問題的,一旦事項多且長時,輪詢方式處理信號會出現響應慢甚至不響應的問題,這可能會導致程序崩潰。也就是說在任務多且有急緩之分時,迫切需要一種新的信號處理方式。在這樣的情況下中斷就應運而生了。

 

什么是中斷

  中斷是指計算機運行過程中,出現某些意外情況需主機干預時,機器能自動停止正在運行的程序並轉入處理新情況的程序,處理完畢后又返回原被暫停的程序繼續運行。換句話說中斷就是中途被打斷轉而處理其他事情,處理完后在返回處理原來的事情。本質上看中斷其實就是CPU芯片內外部硬件電路產生的電信號。引起中斷的事件稱為中斷源,中斷源向CPU提出進行處理的請求稱為中斷請求。

  中斷分為同步中斷和異步中斷。

  • 同步中斷是當指令執行時由 CPU 控制單元產生,之所以稱為同步,是因為只有在一條指令執行完畢后 CPU 才會發出中斷,而不是發生在代碼指令執行期間,比如系統調用、CPU本身故障、程序故障和請求系統服務的指令引起的中斷CPU內核出錯。同步中斷也被叫做系統異常(簡稱異常)、內中斷。

  • 異步中斷,通常是外部硬件設備事件所引起的中斷,異步中斷是指由其他硬件設備依照 CPU 時鍾信號隨機產生,即意味着中斷能夠在指令之間發生,例如鍵盤中斷,異步中斷也叫外中斷。

 

  在這里我們暫時不討論異常和中斷的差別,無特殊說明統一稱為中斷。

NVIC、中斷優先級與中斷向量表

QQ截圖20210816162446

NVIC

  上圖為中斷結構框圖,可以看到所有的中斷信號最終都輸入到NVIC中,那NVIC是什么?NVIC是如何處理這些中斷信號的?

當一個外設根據其硬件狀況產生了中斷信號時,會將中斷信號提交到NVIC中。NVIC全稱是Nested Vectored Interrupt Controller,即嵌套向量中斷控制器。NVIC接收到中斷信號后會根據中斷信號定義的編號信息,置位ISER寄存器中的相應中斷Pending位,如果該中斷是被使能並且當前階段沒有更高優先級的中斷正在執行,那么NVIC會查詢中斷向量表的對應中斷入口服務函數的地址找到並進入對應服務函數。

  說到這里有大家可能會有點懵,所以我們先來捋一捋相關知識。

  1. NVIC相關寄存器

    • ISER寄存器組: 32位寄存器,每位控制一個中斷,寫1使能相應中斷,寫0無效

    • ICER寄存器組: 32位寄存器,每位控制一個中斷,寫1除能相應中斷,寫0無效、

    • ISPR寄存器組:32位寄存器,每位控制一個中斷,將某位置1會將相應的中斷掛起,寫0無效

    • ICPR寄存器組:32位寄存器,每位控制一個中斷,將某位置1會將相應中斷解除掛起狀態,寫0無效

    • IABR寄存器組:32位寄存器,只讀寄存器組,如果讀到某位為1,表示該位對應中斷正在執行服務函數,中斷服務函數執行完后 由硬件自動清零

    • IP寄存器組:8位寄存器,每個寄存器高四位用來配置搶占優先級和響應優先級的等級(優先級的分組由SCB->AIRCR寄存器的[10:8]位控制)

     

    以上就是NVIC的一些主要寄存器,可以看出NVIC的寄存器與我們平時見到的寄存器有些不同:

    • NVIC寄存器絕大多數是寄存器組,因為F427內核可屏蔽中斷就有80多個,至少需要3個寄存器才能做到控制完全部的中斷,但是廠商深謀遠慮不僅給每個寄存器預留了很多位,每個寄存器也配置了8個(雖然目前我們只用到了3個)。

    • 與大多數的控制寄存器的寫1使能寫0失能不同,中斷的使能和失能都是由不同的寄存器寫1控制,對這些寄存器寫0是無效的。

     

  2. 中斷的一些狀態

    • Pending (中斷懸(掛)起)

      當中斷輸入腳的中斷請求被NVIC確認有效后,NVIC會將該中斷懸起,中斷懸起標志位被置1,這個中斷懸起標志可以類似於生活中去小餐館吃飯點單完的小票單,意思就是說你的點單(中斷請求)后廚(CPU)已經了解了,之后會給你做(響應中斷),但是這個這個做飯的順序就不同與現實生活中的先來后到了:如果CPU從Handler模式退回到線程模式,通俗一點說就是剛處理完一個中斷服務函數。他會瞄一眼現在有哪些中斷請求,根據不同中斷的優先級來確定下一個響應的中斷。當一個中斷被響應,CPU進入該中斷的中斷服務函數時,中斷懸起標志會可能被硬件自動清除也可能需要用戶自己手動清除。如果用戶自己忘了清除中斷懸起標志位,CPU可不會記得自己上一次處理過這個中斷,他會認為有有一個新的中斷請求所以會再次進入該中斷的服務函數,從而導致程序一直卡在這個中斷服務函數里面!!!所以有些中斷懸起標志不會被硬件自動清除的中斷,需要我們在編寫中斷服務函數時手動清除中斷懸起標志,否則后果很嚴重。置於為什么會存在需要用戶自己清除懸起標志這種看上去只會增加程序BUG的設計?因為中斷向量表(之后會談到)在隨着內核更新后變得不夠裝了,所以有許多同類型的中斷共用一個中斷服務函數,那中斷懸起標志需要在進入中斷服務函數之后也保持置高狀態讓用戶能分辨出具體是哪個中斷請求,自然也需要用戶自己清除中斷懸起標志位了。需要注意的是,只要中斷請求被確認有效,中斷懸起標志被置1后,中斷請求撤銷也不能改變中斷懸起標志位,CPU一樣會進入該中斷的中斷服務函數。還有就是,NVIC只會記錄是否有中斷請求,而不會記錄有幾次中斷請求,假如在CPU進入中斷服務函數之前有多次中斷請求,中斷懸起標志早在第一次就會被置高,中斷服務函數也只會執行一次。

    • 中斷活躍

      當某中斷的服務函數開始執行時,就稱此中斷進入了活躍狀態,也叫做中斷有效,並且其中斷懸起位會被硬件自動清零。當中斷服務函數結束退出后,中斷的活躍狀態也停止並返回,只有在返回后才能對該中斷的新請求予以響應。

      這么說可能腦子有點糊,我們來看時序圖來捋一捋。

image-20210817144753525

                                                 當NVIC確認中斷請求有效后,會將對應中斷的中斷懸起標志位置高,當進入對應中斷服務函數時,中斷懸起標志位需要被清除(硬/軟)

image-20210817145048834

                                                                        如果在CPU進入中斷服務函數之前,中斷懸起標志被軟件清零,則CPU不會進入中斷服務函數(Handler模式)

image-20210817145245819

                                                                     當CPU進入中斷服務函數,相應的中斷活躍寄存器位(IABR寄存器)置1,退出中斷服務函數時,中斷活躍寄存器被置0

20181203061942619

                                                                                                       只有當中斷服務函數執行完,中斷從活躍狀態返回后,才能響應新的中斷請求

 

優先級分組

  上文講了單個中斷的響應流程,接下來講的是當有多個中斷請求時,NVIC如何仲裁這些中斷哪個先響應,這就涉及到中斷的優先級分組的知識了,還記得上文中NVIC的寄存器一塊里我們有一個IP寄存器嗎,我們來講一下單片機是如何操控這個寄存器來實現中斷的優先級分組的。

  對於M3和M4內核的MCU,每個中斷的優先級都是用IP寄存器中的8位來設置的。8位的話就可以設置2^8 =256級中斷,實際中用不了這么多,所以芯片廠商根據自己生產的芯片做出了調整。比如ST的STM32F1xx和F4xx只使用了這個8位中的高四位[7:4],低四位取零,這樣2^4=16,只能表示16級中斷嵌套。用於表達優先級的這 4bit,又被分組成搶占優先級響應優先級。4bit分別表示兩個優先級等級,一共可以分成5組

組別 搶占優先級位 響應優先級位 搶占優先級級數 響應優先級級數
0 [7:4] none 16 0
1 [7:5] [4] 8 2
2 [7:6] [5:4] 4 4
3 [7] [6:4] 2 8
4 none [7:4] 0 16

  表中可以看出搶占優先級和響應優先級在分高四位([7:4]),如果分組策略是組0的話,表達的優先級就全部用於區別搶占優先級,搶占優先級就有16級,中斷的優先級選擇可以從0~15。如果分組策略是組2的話,4位中各有2位表示搶占優先級和響應優先級,那一個中斷分別有4級搶占優先級和4級響應優先級可供選擇。注意:優先級的數值越小代表器優先級等級越高

 

  中斷的仲裁原則:

  • 搶占優先級高(數值小)的中斷可以打斷正在執行的搶占優先級低(數值大)的中斷。

  • 多個中斷同時響應,搶占優先級高(數值小)的中斷優先響應

  • 如果多個中斷搶占優先級相同,則不存在打斷現象,只是在同時響應中優先執行響應優先級高(數值小)的中斷

  • 如果搶占優先級和響應優先級都一樣的中斷,就比較他們的硬件中斷編號,硬件編號小的優先響應

 

  搶占優先級的存在導致了有中斷嵌套的現象。如果大家有C語言的基礎,了解過循環嵌套的說法后 ,對中斷嵌套也能理解地非常快。

  CPU是在每次執行完一條語句后查看NVIC中所有的中斷懸起標志位,如果CPU看到了比現在正在執行的中斷服務函數優先級更高的中斷懸起標志,那么CPU會轉而執行更高優先級的中斷,實現了中斷的中斷,只要你想,就有中斷的中斷的中斷,中斷的中斷的中斷的中斷 …

  既然是嵌套,那內層中斷執行完后必然要回到上一級中斷執行完,如下圖。這其實涉及到一個完整的中斷響應流程:中斷懸起標志置高—>保存現場—>處理中斷—>恢復現場的過程。下圖中的ISR指的是中斷服務處理,Interrupt Service Routines。

image-20210818105313558

 

中斷向量表

  以上是中斷的響應流程,但是F427在內核水平上的異常響應系統中系統異常有 10 個,外部中斷有 87 個。 這些中斷中包含所有的外設中斷,外部中斷,系統異常。每個中斷都有自己的中斷服務函數,那NVIC將一個中斷信號和其對應的中斷服務函數聯系起來,用的就是中斷向量表。這里我們節選部分。

image-20210818090952732

image-20210818091143979

image-20210818090923669

 

  上面我斷斷續續截了一些圖,如果想看詳細的這97個中斷的向量表可以在STM32F4中文/英文參考手冊中NVIC一章中看到。

  從上圖我們能觀察出一些特點,先說明一下表格中灰色的部分代表是系統異常

  • 系統異常中有一些中斷優先級是比其他所有優先級都要高的,他們的優先級等級為負數,這是可配置優先級所不能配置出的。像硬件復位優先級最高,可以打斷任何中斷,還有NMI中斷 :Non Maskable Interrupt 即不可屏蔽中斷,這是時鍾安全系統(CSS)的中斷,當外部高速時鍾故障時,CSS會緊急調用內部高速時鍾來應急,這些我們會在下一節 時鍾中具體談到。

  • 並不是系統異常的優先級一定比外部中斷的優先級高,有一些系統異常的優先級類型也是可設置的,自然就有可能比外部中斷等級低

  • 有一些中斷共用同一個中斷向量例如EXTI0,所以需要在中斷服務函數內部判斷具體是哪個中斷。

 

  至於中斷向量這個名字是怎么來的?中斷向量到底有什么用?為什么要有中斷向量表的存在?我們現在來解釋一下:

  經過一番查找資料后,網絡上大部分對中斷向量的觀點是:中斷向量更偏向於指針的作用,中斷向量是中斷服務函數的指針,向量的含義可能只是代表有指向方向。那內核廠商把所有可能的中斷都初步編寫了中斷服務函數,自然也就把這些中斷向量列成了一張中斷向量表供NVIC查閱,有了中斷向量表后CPU看到中斷懸起標志就能根據這個中斷向量表查找到對應中斷向量,自動尋址到中斷服務函數,這樣處理中斷的效率就非常高。關於中斷向量表有個我覺得網上有個非常恰當的比喻,中斷向量表就是一個地址黃頁,上面記錄着如果火警去哪找消防隊,如果匪警上哪去找警察局,如果病危上哪去找醫院。這里面的“火警”、“匪警”、“病危”就是各種中斷,上哪去找負責的單位,就是中斷向量表里面的地址。專業一點說中斷向量就是記錄着每個不同中斷發生后處理器跳轉到中斷服務程序的起始地址。

  那NVIC的主要功能我們已經全部講完了,現在來小結一下NVIC的主要功能。

  • 使能與失能某些中斷

  • 配置中斷的搶占優先級和響應優先級

  • 接收中斷請求后置位相應中斷懸掛位

  • 提供只讀寄存器IABR,檢測中斷的活躍狀態,監測是否進入中斷服務程序

 

EXTI

  上一小節我們已經詳細介紹了 NVIC,對 STM32F4xx 中斷管理系統有個全局的了解, 那么接下來我們講講外部中斷,我們重新看一下上面的中斷程序框圖,可以看到並不是所有的中斷都是直接移交給NVIC控制的,外部設備的中斷處理經過了一個特殊的控制器來管控,這就是我們的EXTI,External interrupt/event controller,即外部中斷/事件控制器。

QQ截圖20210816162446

  外部中斷/事件控制器 (EXTI) 管理了控制器的 23 個中斷/事件線。每個中斷/事件線都對應有一個邊沿檢測器,可以實現輸入信號的上升沿檢測和下降沿的檢測。 EXTI 可以實現對每個中斷/事件線進行單獨配置,可以單獨配置為中斷或者事件,以及觸發事件的屬性。可以這么說,一共144引腳的芯片,可配置中斷的140多個GPIO,都是由EXTI管理的,注意是GPIO,一旦引腳為外設專用腳或是復用為其他外設的引腳比如串口接收引腳,CAN接收引腳等等。它們就屬於片上外設的引腳,它們的中斷相關配置由其模塊的寄存器配置,有專門的中斷請求和中斷源由NVIC管控。

  23個中斷/事件線,具體是哪些我們要看STM32F4XX中文參考手冊

image-20210818144245962

  可以看到EXTI0~EXTI15這16根線由GPIO 映射而成,所有的0引腳從PA0到PH0都與EXTI0線相連,也就是說,在PA0到PH0這8個IO口同時只有一個能配置成外部中斷模式,不然會沖突,其他線也同理,那具體選擇那個引腳作為外部中斷線由SYSCFG_EXTICR寄存器的相應位設置,所以我們配置EXTI模式時,也要開啟SYSCFG的時鍾。另外七根 EXTI 線連接方式如下,這些特定外設的中斷在具體用到時再做說明。

image-20210818145226933

EXTI功能框圖

image-20210818145616580

  和任何外設一樣,想要掌握使用方法首先我們要理解他的功能框圖,可以看到功能框圖中有紅綠兩條主線,一個是產生中斷請求到NVIC中斷控制器中,一個是通過脈沖發生器產生一個脈沖信號這里叫做產生事件,這也是EXTI名字的由來:外部中斷/事件控制器 。圖中還有很多23上划有斜杠,這個表示在控制器內部類似的信號線路有 23 個,這與 EXTI 總共有 23 個中斷/事件線是吻合的,線路與線路之間也是獨立不干涉的。 還有一點就是EXTI是在APB2總線上的,可以看到有PCLK2指向其外設接口,至於APB2總線的知識我們也會在下一章時鍾一節講解。

QQ截圖20210818193452

中斷線

  最右邊的輸入線代表的都是我們的GPIO口或是一些外設的事件,一個GPIO配置成EXTI模式后,那這個引腳的輸入電平就會接到輸入線上,那輸入電平首先就會經過邊沿檢測電路。這個邊沿檢測電路就是受上升沿觸發選擇寄存器和下降沿觸發選擇寄存器配置的一個電路,這兩個寄存器可以控制器需要檢測哪些類型的電平跳變過程即配置有效邊沿跳變,可以是只有上升沿觸發、 只有下降沿觸發或者上升沿和下降沿都觸發。 而輸入線輸入的電平一般都是存在電平變化的信號。如果邊沿檢測電路檢測到有效邊沿跳變就會輸出1到后續的電路,否則輸出0。之后邊沿檢測電路輸出的信號會流入編號3電路中。

 

  編號3是一個或門電路,或門電路是一個經典的邏輯門電路,這個門電路要求有兩個輸入,只要有一個輸入為1,那或門電路就輸出1,只有當兩個輸入門都是輸入0時,或門電路才輸出0。在此處中或門電路的一個輸入信號來自邊沿檢測電路,另一個信號來自軟件中斷事件寄存器,該寄存器允許我們通過程序來啟動中斷/事件線,這在某些地方非常有用。我們知道或門的作用就是有1就為 1,所以這兩個輸入隨便一個有有效信號 1 就可以輸出 1 給編號 4 和編號 6 電路 。

  之后是編號4電路,現在我們有了3號的輸出信號,不論是軟件提供的中斷信號還是硬件的電平跳變信號都會轉化成中斷請求信號輸入到4號電路中,4號電路是另一個經典邏輯門電路——與門電路,與門電路也是兩個輸入,並且只有當所有輸入都為1時,才會輸出1,任何一個輸入為0都會導致輸出也為0。那來自3號的輸出信號為1表示有中斷請求,另一路輸入來自中斷屏蔽寄存器,這個寄存器的作用和他的名字一樣,這個寄存器的輸出可以導致3號的輸出信號被屏蔽,這其實也是配合了與門電路,如果中斷屏蔽寄存器輸出1,則是不屏蔽輸出信號,4號的輸出取決於3號電路的輸出,如果中斷屏蔽器選擇輸出低電平,那么不論3號是否輸出高電平與門電路都不會輸出中斷信號。那4號與門電路最終輸出的中斷請求信號會把掛起請求寄存器的對應位置1,這樣中斷請求就能被NVIC接收到了。

 

事件線

  事件線的流程與中斷線非常相似,在3號或門電路之前的路徑可以說完全一致,或門電路判斷出中斷/事件信號后也是和一個屏蔽寄存器進入一個與門。唯一的不同就是事件線的末端是接入一個脈沖發生器,這個脈沖發生器在收到有事件請求后會產生一個脈沖信號,這個脈沖信號可以給其他外設電路使用,比如定時器 TIM、模擬數字轉換器 ADC 等等,這樣的脈沖信號一般用來觸發 TIM 或者 ADC開始轉換

  可能會不太好理解為什么需要產生事件,如果我們需要一個事件信號來觸發TIM或者啟動AD轉換,為什么不用中斷信號來產生一個中斷,然后在中斷服務函數里面編寫這些驅動程序?更何況從外部激勵信號來看,中斷和事件的產生源都是一樣的。

  之所以分成2個部分,由於中斷是需要CPU參與的,需要軟件的中斷服務函數才能完成中斷后產生的結果。但是事件,是靠脈沖發生器產生一個脈沖,進而由硬件自動完成這個事件產生的結果,當然相應的聯動部件需要先設置好,比如引起DMA操作,AD轉換等。用事件通道,在有硬件基礎的條件下可以順帶驅動一個功能而不需要CPU的參與了。可以這樣簡單的認為,事件機制提供了一個完全有硬件自動完成的觸發到產生結果的通道,不要軟件的參與,降低了CPU的負荷,節省了中斷資源,提高了響應速度(硬件總快於軟件),是利用硬件來提升CPU芯片處理事件能力的一個有效方法。

至此,與中斷相關的知識就全部梳理完了,接下來是實際操作,我們會用硬件輸入中斷(按鍵)和軟件中斷兩種中斷來實現點燈。

 

實戰練習

  在前面兩篇文章中我重點介紹了STM32CubeMX和Keil5的功能使用,以后的文章中一些配置步驟就會比較簡略,只會留下關鍵步驟截圖

image-20210818193810464

image-20210818200140009

  這里雖然是軟件中斷,引腳配置只要選擇是中斷模式就都行,因為軟件中斷的信號與輸入線的電平變化無關。這里設置一下可以用作或門的實驗。然后配置一下LED

image-20210818205215642

image-20210818201206165

image-20210818201301969

image-20210818201321946

image-20210818201407760

  生成代碼,打開工程文件,進入keil,可以在main.h中看到我們的User label

image-20210818205256187

  在Startup.S文件中我們可以看到官方用匯編寫的中斷向量表,CPU就是根據中斷向量表來尋址中斷服務函數。

image-20210818201618411

  在stm32f4xx_it.c中就存放者各種中斷服務函數,其中沒配置的中斷往往都是空函數,而用CubeMX配置過的中斷的中斷服務函數內部有相應的HAL庫函數。而且可以看出EXTI的中斷服務函數都是同一個HAL_GPIO_EXTI_IRQHandler,也就是說我們需要在內部查看中斷懸起標志才能判斷出具體是哪個中斷。如果我們不是HAL庫函數而是使用標准庫函數,那么我們的中斷服務函數就要在相應的IRQHandler里面編寫了,這里面的IRQ是Interrupt Request的縮寫。

image-20210818202021398

  我們再查看HAL_GPIO_EXTI_IRQHandler的函數定義。

image-20210818202441986

  可以看到HAL_GPIO_EXTI_IRQHandler函數首先利用了__HAL_GPIO_EXTI_GET_IT函數來確定中斷請求是否是確定的(asserted),__HAL_GPIO_EXTI_GET_IT是一個宏定義函數,他的函數功能如下圖所示。

image-20210818202625913

  判斷完中斷是確定的后,HAL_GPIO_EXTI_IRQHandler調用了另一個宏定義函數__HAL_GPIO_EXTI_CLEAR_IT。簡而言之,這個函數就是程序清除中斷懸起標志位,將中斷懸起標志位置0,不然CPU會一直卡在中斷服務函數里。

image-20210818202823507

  清除完中斷懸起標志后,HAL_GPIO_EXTI_IRQHandler調用了HAL_GPIO_EXTI_Callback函數,其實這才是HAL庫里的真正的中斷服務函數,又被翻譯為中斷回調函數。如果是標准庫,那檢驗中斷有效性,清除中斷標志位,中斷服務函數內容會一股腦塞在IRQHandler函數內,但是HAL庫將一些系統的操作檢驗中斷有效性,清除中斷標志位放在HAL_GPIO_EXTI_IRQHandler中,而真正需要用戶編寫邏輯的中斷服務函數,放在了Callback函數內。其函數定義如下圖。

image-20210818203341937

  可以看到這個函數與我們平時所見的函數定義不太相同,這個函數好像沒有什么內容,並且在函數頭前還有_weak關鍵字,這個weak關鍵字的作用就是弱定義。有_weak屬性的函數是允許再次定義並且不會報錯的,如果你定義了一個重名函數,那么原weak函數定義就不再生效,你調用的該函數如果用go_to_definition查看會跳轉到你的函數定義中。所以我們能夠在別處定義一個同名的Callback函數。來實現用戶自己的中斷服務功能。

  最后我們再利用function窗口看看軟件中斷的相關函數。可以看到__HAL_GPIO_EXTI_GENERATE_SWIT函數的作用就是對一條EXTI線產生軟件中斷。

image-20210818212341991

  小結一下EXTI的相關HAL庫函數:

  • HAL_GPIO_EXTI_IRQHandler函數,中斷服務函數

  • __HAL_GPIO_EXTI_GET_IT函數,返回中斷是否有效

  • __HAL_GPIO_EXTI_CLEAR_IT函數,清除中斷懸起標志

  • HAL_GPIO_EXTI_Callback函數,中斷回調函數,編寫中斷服務邏輯

  • __HAL_GPIO_EXTI_GENERATE_SWIT函數,產生軟件中斷。

 

我們編寫的程序邏輯如下圖:

image-20210818213858231

  可以看到我們在while(1)內每3s產生一次軟件中斷信號。

  然后我們在main.c的下方的任意一處可以編寫函數的地方重新定義中斷回調函數。注意要找User Code Begin 和User Code End 之間填寫

image-20210818214105995

  可以看到我們首先用if判斷到底是哪個引腳產生的中斷對應不同的處理。這里我們對軟件中斷的回調服務亮紅燈,硬件的按鍵中斷回調服務是亮綠燈。

  既然都是一個引腳產生的外部中斷,軟件中斷與輸入線的外部中斷是或門關系,我們在這個程序中同樣可以測試,可以將while(1)中的有關軟件中斷的兩行代碼注釋掉,下載好程序后,我們用一根杜邦線一邊連GND,另一邊插入PF1腳,觀察現象,同樣可以觀察到紅燈翻轉。

 

總結

  本章我們學習了NVIC和EXTI這兩大中斷控制器,需重點掌握以下幾點:

  • 輪詢式和中斷式的信號處理

  • 中斷優先級的分組

  • 中斷響應流程

  • 中斷嵌套

  • EXTI功能框圖

  • EXTI相關函數

  • 三種信號觸發方式

  • 產生中斷與產生事件的區別

  • __weak關鍵字

 

  思考以下問題:

  1. 為什么實驗中是將引腳接GND而不是接VCC?

  2. 在本例實驗中會存在中斷嵌套的現象嗎?

  3. 在上一篇文章中我們談到了按鍵需要按鍵消抖動,那本次按鍵是以外部中斷的形式輸入,如何實現按鍵消抖動,可以在中斷回調函數中使用HAL_Delay()函數嗎?

 

  下一節我們將學習STM32時鍾。


免責聲明!

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



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