HAL庫的框架結構
1 初始HAL庫
1.1 CMSIS簡介
基于Cortex系列芯片采用的內核都是相同的,區別主要為核外的片上外設的差異,這些差異卻導致軟件在同內核,不同外設的芯片上移植困難。為了解決不同的芯片廠商生產的Cortex微控制器軟件 的兼容性問題,ARM與芯片廠商建立了CMSIS標準(Cortex MicroController Software Interface Standard)。
Cortex微控制器軟件接口標準(Cortex Microcontroller Software Interface Standard)是ARM和一些編譯器廠家以及半導體廠家共同遵循的一套標準,是由ARM提出,專門針對CORTEX-M系列的標準。在該標準的約定下,ARM和芯片廠商會提供一些通用的API接口來訪問CORTEX內核以及一些專用外設,以減少更換芯片以及開發工具等移植工作所帶來的金錢以及時間上的消耗。
以下是ARM官網關于CMSIS的架構圖
可見,CMSIS層位于硬件層與操作系統或用戶層之間,提供了與芯片生產商無關的硬件抽象層,可以為接口外設、實時操作系統提供簡單的處理器軟件接口,屏蔽了硬件差異,這對軟件的移植是有極大的好處的。STM32的庫,就是按照CMSIS標準建立的。
1.2 HAL庫簡介
ST 為了方便用戶開發 STM32芯片開發提供了三種庫:
- 標準外設庫 :Standard Peripheral Libraries F0/F1/F3/F2/F4/L1目前已停止維護。
- HAL庫:Hardware Abstraction Layer 全系列兼容,ST目前主推的庫,具有強兼容性、易移植性,但效率較低。
- LL庫:Low Layer 全系列兼容,與HAL庫捆綁發布,輕量級、效率高,但不匹配部分復雜外設。
三種庫比較:
1.3 MCU固件包
STM32微控制器各個產品系列都有獨立的MCU固件包,HAL庫屬于MCU固件包的一部分。
MCU固件包文件結構:
- Drivers:文件夾下是官方的CMSISI庫,HAL庫,板載外設驅動。
- Middleware:中間件,包含ST官方的STemWin、 STM32_Audio、STM32_USB_Device_Library、STM32_USB_Host_Library;也有第三方的fatfs文件系統等等。
- Projects:文件夾下是用驅動庫寫的針對官方發行demo板的例子和工程模板。
- Templates:各集成開發環境的工程模板。
- Examples:針對MCU片內外設的簡單例程,如GPIO、UART等。
- Applications:針對單個中間件的應用例程。
- Demonstations:針對多個中間件的綜合應用例程。
- Utilities:實用的公用組件比如LCD_LOG實用液晶打印調試信息。
1.4 HAL庫框架結構
HAL庫文件夾結構
Src(Source):外設驅動源碼,Inc(Include):外設驅動源碼頭文件。
HAL庫文件介紹:
- stm32f1xx_hal.c, stm32f1xx_hal.h
HAL庫初始化、系統滴答、HAL庫延時等相關函數 - stm32f1xx_hal_conf.h
HAL庫的用戶配置文件,用于裁剪HAL庫、配置晶振參數等 - stm32f1xx_hal_def.h
包含HAL庫通用的枚舉類型數據和宏定義 - stm32f1xx_hal_cortex.h, stm32f1xx_hal_cortex.c
內核通用函數定義和聲明,如NVIC、MPU、系統軟復位、Systick等,其實主要是對core_cm3.h 文件的相關函數再次封裝。 - stm32f1xx_hal_ppp.c, stm32f1xx_hal_ppp.h
某任意外設驅動源碼,PPP表示任意外設 - stm32f1xx_hal_ppp_ex.c, stm32f1xx_hal_ppp_ex.h
主要是存放外設的擴展(特殊)功能的驅動源碼,PPP表示任意外設 - stm32f1xx_II_ppp.c, stm32f1xx_II_ppp.h
LL庫驅動源碼,在部分STM32F1xx_hal_ppp.c 或stm32f1xx_hal_ppp_ex.c中會被調用
HAL庫API函數和變量命名規則:
- stm32f1xx_hal_ppp .(c/h)
- 函數名:HAL_PPP_Function
- 外設句柄:PPP_HandleTypeDef
- 外設工作參數初始化結構體:PPP_InitTypeDef
- 配置參數結構體:PPP_ YyyyConfTypeDef
- stm32f1xx_hal_ppp_ex .(c/h)
- 函數名:HAL_PPPEx_Function
- 外設句柄:無
- 外設工作參數初始化結構體:PPP_InitTypeDef
- 配置參數結構體:PPP_ YyyyConfTypeDef
- 初始化/反初始化函數:
- HAL_PPP_Init(),HAL_PPP_DeInit()
- 外設讀寫函數:
- HAL_PPP_Read(),
- HAL_PPP_Write(),
- HAL_PPP_Transmit(),
- HAL_PPP_Receive()
- 控制函數:
- HAL_PPP_Set (),
- HAL_PPP_Get ()
- 狀態和錯誤:
- HAL_PPP_GetState (),HAL_PPP_GetError ()
HAL庫對寄存器位操作的相關宏定義:
- __HAL_PPP_ENABLE_IT( HANDLE , INTERRUPT )
使能外設中斷 - __HAL_PPP_DISABLE_IT( HANDLE , INTERRUPT )
禁用外設中斷 - __HAL_PPP_GET_IT ( HANDLE , __ INTERRUPT __)
獲取外設某一中斷源 - __HAL_PPP_CLEAR_IT ( HANDLE , __ INTERRUPT __)
清除外設中斷 - __HAL_PPP_GET_FLAG ( HANDLE , FLAG )
獲取外設的狀態標記 - __HAL_PPP_CLEAR_FLAG ( HANDLE , FLAG )
清除外設的狀態標記 - __HAL_PPP_ENABLE( HANDLE )
使能某一外設 - __HAL_PPP_DISABLE( HANDLE )
禁用某一外設 - __HAL_PPP_XXXX ( HANDLE , PARAM )
針對外設的特殊操作 - _HAL_PPP_GET IT_SOURCE ( HANDLE , __INTERRUPT __)
檢查外設的中斷源
HAL庫回調函數:
- HAL_PPP_MspInit() / _MspDeInit()
舉例: HAL_USART_MspInit() 會被HAL_PPP_Init() 函數調用,該函數主要用于存放外設使用到的GPIO、CLOCK、NVIC、DMA等初始化代碼。 - HAL_PPP_ProcessCpltCallback
舉例: HAL_USART_TxCpltCallback由外設中斷或DMA中斷調用,HAL庫中斷公共處理函數已經實現對中斷標記位讀取、判斷和清除操作,用戶只需要專注于中斷邏輯功能的實現即可。 - HAL_PPP_ErrorCallback
舉例: HAL_USART_ErrorCallback外設或DMA中斷中發生的錯誤,用于發生錯誤處理。
此類函數通常被_weak修飾(弱函數),允許用戶重新定義該函數。
1.5 HAL庫的設計思想
HAL庫借鑒 面向對象的設計思想 :
開發方式的特點:
- 屏蔽底層硬件 :編程者只需要了解庫函數中相關接口函數的功能,并按照要求傳入參數,利用返回值完成操作即可,不需要過多了解底層硬件。
- 提高開發效率 :開發難度較小,開發周期較短,后期的維護升級、以及硬件平臺的移植等工作量較小。
- 程序執行效率 :由于考慮了程序的穩健性、擴充性和可移植性,程序代碼比較繁瑣和臃腫,執行效率較低。
用戶代碼的處理主要分為三部分:
- 處理外設句柄(實現用戶功能)
- 處理MSP
- 處理各種回調函數
設計思想:從抽象到重載
1.6 以USART為例說明HAL庫的抽象結構
①外設句柄的定義:
HAL庫在結構上,對每個外設抽象成了一個稱為ppp_HandleTypeDef
的結構體,其中ppp就是每個外設的名字。所有的函數都是工作在ppp_HandleTypeDef
指針之下。
例如,使用USART2時,可以定義USART初始化結構體變量(全局變量)huart2
。huart2
就被稱為串口的句柄,它被貫穿整個USART收發的流程。
UART_HandleTypeDef huart2;
②外設句柄數據類型的組成:
③串口初始化數據類型的組成:
④串口初始化過程:
抽象—串口初始化函數
MX_USART2_UART_Init
: 將與MCU無關的通信參數存入句柄結構 +使用HAL_UART_Init
執行串口初始化操作,將句柄參數寫入寄存器。
HAL_UART_Init` 干了哪些事?調用
HAL_UART_MspInit
* 修改狀態忙* 配置寄存器* 清除標志位承載—與MCU相關的初始化函數
HAL_UART_MspInit
: 時鐘初始化 + 引腳初始化
⑤串口中斷處理過程:
HAL_UART_Receive_IT
:開啟中斷,在中斷方式下接收一定數量的數據。USART2_IRQHandler
:串口2的中斷服務程序,調用串口中斷通用處理函數HAL_UART_IRQHandler
。HAL_UART_IRQHandler
:在函數HAL_UART_IRQHandler
內部通過判斷中斷類型是否為接收完成中斷,確定是否調用UART_Receive_IT
。
函數UART_Receive_IT
的作用是把每次中斷接收到的字符保存在串口句柄的緩存指針pRxBuffPtr
中,同時每次接收一個字符,其計數器RxXferCount
減 1,直到接收完成RxXferSize
個字符之后RxXferCount
設置為0,同時調用接收完成回調函數HAL_UART_RxCpltCallback
進行處理。HAL_UART_RxCpltCallback
:函數由串口中斷通用處理函數UART_Receive_IT
調用,完成所有串口的接收中斷任務處理,函數內部需要根據串口句柄的實例來判斷是哪一個串口產生的接收中斷,函數由用戶根據具體的處理任務編寫。
-
微控制器
+關注
關注
48文章
7646瀏覽量
151891 -
mcu
+關注
關注
146文章
17316瀏覽量
352265 -
STM32
+關注
關注
2271文章
10923瀏覽量
357108 -
Cortex
+關注
關注
2文章
203瀏覽量
46558 -
HAL庫
+關注
關注
1文章
121瀏覽量
6361
發布評論請先 登錄
相關推薦
評論