一、提高程序實時性的架構方案
- 輪詢式
指的是在程序運行時,首先對所有的硬件進行初始化,然后在主程序中寫一個死循環,需要運行的功能按照順序進行執行,輪詢系統是一種簡單可靠的方式,一般適用于在只需要按照順序執行的并且沒有外部事件的影響的情況下。
//自定義延時函數
void Delay();
int main() {
//1.硬件初始化
LED_Init();
BEEP_Init();
KEY_Init();
//2.進入死循環 for(;;)
{
//判斷按鍵狀態,導致程序的實時性較差
if(KEY0 == 0 ) {
//控制BEEP發聲 GPIO_SetBits();
Delay(50); //50ms
//控制LED點亮GPIO_ResetBits();
Delay(100); //100ms
} } }
- 前后臺
相比于輪詢系統,前后臺系統增加中斷的概念,如果外部事件發生,則在中斷中進行處理,主程序在輪詢系統中運行,中斷被稱為前臺,主程序中的while(1)就稱為后臺。中斷會終止后臺程序的運行,然后跳轉到對應的中斷服務函數中去處理,處理完成后,在繼續執行后臺的程序。使用前后臺系統可以極大程度的提高程序的實時響應能力,避免造成外部事件的缺失。
//定義信號的回調函數,該函數不需要調用
void signal_handler(int signum)
{
//定義狀態機
switch(signum){
case SIGUSR1: xxxx;break;case SIGUSR2: xxxx;
break; .....
} }
int main(){
//1.硬件初始化
LED_Init();
BEEP_Init();
KEY_Init();
//2.注冊信號,進程收到該信號,會觸發信號的回調函數,此時會中斷當前程序
signal(SIGUSR1, signal_handler);
//3.進入死循環
for(;;)
{
//控制BEEP發聲GPIO_SetBits();
Delay(50); //50ms
//控制LED點亮
GPIO_ResetBits();
Delay(100); //100ms } }
- 多任務
相比于前后臺系統,多任務系統的外部事件也是在中斷中進行響應,但是外部事件的處理是任務中進行處理。任務具有優先級,優先級高的任務先處理,所以程序就會被分割為一個個的任務,任務是一個獨立的死循環,并且不能返回,可以由操作系統進行任務的調度,程序段的實時響應能力又得到提升。
|
二、MCU中斷的原理與應用
- 中斷的概念
中斷指的是CPU來處理和響應外部發生的異常,中斷也就意味著打斷,比如打斷正在做的事,然后去處理一個緊急的事,處理完成后在繼續做剛才沒做完的事。
- 中斷源分析
中斷源指的是異常發生的源頭,中斷源在內核中已經定義好了,中斷源表也稱為中斷向量表,向量表在STM32F4中文參考手冊參考。
上圖中的表格就是STM32F4系列的異常向量表,對于STM32F407xx有82個可屏蔽異常!!!!
- 中斷的管理
NVIC指的是嵌套向量中斷控制器,屬于內核中的外設,作用是管理所有的中斷,比如中斷的使能或失能、中斷的優先級.....。
不管是Cortex A系列還是Cortex M系列的內核內部均有NVIC,通過NVIC來管理內核異常和外部異常。
NVIC管理中斷通道的打開與關閉,可以把NVIC理解為負責管理所有中斷的開關,想要使用中斷發送中斷請求,就必須提前打開中斷的通道。關于NVIC的使用都存儲在一個結構體中,這個結構體和NVIC的函數接口都定義在misc.c和misc.h中。
- 中斷的順序
NVIC利用4bit的優先級來管理所有的中斷通道,STM32中斷的優先級分為兩種:搶占式優先級(主優先級) + 響應式優先級(子優先級),有16個優先級(0~15),數字越小,優先級越高。
意義:如果同時發生多個中斷請求,但是又不能同時處理,就根據中斷請求的優先級來處理和響應中斷。
搶占優先級(主優先級):搶占優先級高的中斷可以打斷正在執行的搶占優先級低的中斷!!!
響應優先級(子優先級):在同時發生多個中斷的情況下,響應優先級高的中斷可先執行!!!
- 搶占優先級高的中斷可以打斷正在執行的搶占優先級低的中斷
- 搶占優先級相同的中斷同時發生,響應優先級高的中斷先執行
- 搶占優先級相同的多個中斷發生,響應優先級高的中斷不能打算響應優先級低的中斷
- 搶占優先級和響應優先級相同的多個中斷同時發生,則按照向量表的中斷編號來執行
為了方便用戶管理和響應中斷,NVIC需要對中斷優先級進行分組,這樣用戶可以方便配置
注意:該函數必須在主程序的入口進行調用,并且整個項目應該只調用一次,因為設置好優先級分組之后就不應該隨意更改分組,否則中斷管理比較混亂,另外用戶在設置中斷優先級的時候應該遵守分組對應的優先級范圍。
三、EXTI外設的基本原理與應用
- 基本概念
EXTI指的是外部中斷/事件控制器,一共有23個,每個都有一個內部的邊沿檢測器,可以檢測上升沿或者下降沿,每根線都可以產生事件或者中斷。
注意:每個GPIO引腳都可以配置為外部中斷,但是和GPIO相關的外部中斷線一共有16根,分別為EXTI0~EXTI15。
- 基本原理
思考:STM32F407系列有114個GPIO口,那如何和外部中斷線進行關聯?通過映射的方式
注意:STM32F407所有IO口都可以設置為外部中斷,但是必須把GPIO引腳配置為輸入模式。
- 程序設計
- 把EXTI外設的源文件以及SYSCFG外設的源文件添加到項目工程中,具體操作如下所示:
- 參考ST公司提供的外設的源文件的開頭的注釋以及參數ST公司提供的關于外設的例程
- 打開GPIOA端口時鐘(因為KEY0按鍵對應的引腳PA0)以及SYSCFG外設時鐘(映射)!
- 配置GPIOA端口PA0引腳的模式為輸入模式,因為需要利用該引腳檢測外部事件,如下
- 利用SYSCFG外設的寄存器對GPIOA端口的引腳PA0以及EXTI0建立映射關系(自動建立)
- 定義EXTI外設的結構體變量,對結構體成員初始化(編號+模式+邊沿+狀態),如下圖
- 配置EXTI外設的中斷,需要使用NVIC外設管理中斷的通道以及中斷的優先級,如下圖
- 對EXTI中斷通道配置完成后,需要編寫對應的中斷服務函數,中斷服務函數的格式固定
注意:ISR中斷服務函數的名字是已經提前定義在啟動文件中向量表內,啟動文件是在程序運行之前先運行的一個匯編文件(xxx.s結尾的),用戶在選擇使用某個外設的中斷的時候,必須從啟動文件中復制中斷服務函數的名稱,比如EXTI0外部中斷線的中斷服務函數名字是EXTI0_IRQHandler
啟動文件的意思是在程序運行之后第一個被執行的文件,啟動文件是使用匯編語言實現的,啟動文件會對系統的堆棧空間進行初始化、以及會對系統的時鐘進行初始化、以及會設置向量表的ISR地址,最后會跳轉到標準C庫的main函數中。
啟動流程:堆棧空間初始化 ---> 設置中斷向量表 ---> 系統時鐘初始化 ---> 跳轉到主函數
- 堆棧空間的初始化
- 設置中斷向量表
中斷向量表其實是用于記錄異常的ISR中斷服務程序的地址,向量表的本質就是一個指針數組,數組中的每個成員都是一個地址(ISR的地址),但是數組中每個元素本身也有地址,不要把地址搞混。
STM32F4的中文參考手冊中記錄了向量表中每個元素的地址,然后每個元素的地址下都會存儲對應的異常的ISR的地址。
- 系統時鐘的初始化
復位也屬于異常,所以在MCU復位之后,CPU會自動跳轉到復位的ISR函數執行,復位異常的ISR函數已經定義在啟動文件中,ISR中會對系統的時鐘進行初始化,并且會跳轉到main函數。
提示:ISR中斷服務程序的結構是固定,是不允許有返回值,以及不允許有參數,結構如下:
void PPP_IRQHandler(void) {
}
注意:如果需要使用異常,就一定要在匯編文件外部定義異常的ISR程序,并且ISR函數名稱必須和啟動文件的向量表中的異常名稱一致,如果不一致,則會導致程序死循環!!!!!
注意:當異常發生后,CPU會跳轉到異常的ISR程序進行執行,ISR程序應該精簡,執行的越快越好。如果異常確實要使用較多代碼解除,則可以選擇回到后臺對異常進行解決,可以選擇采用狀態機思想實現。
|
作業:利用中斷機制實現對開發板的4個按鍵的檢測,另外要求了解4*4矩陣鍵盤的原理,并提供狀態機方式實現16個按鍵的檢測。