使用HAL庫開發STM32:概述與常用系統函數說明

目的

使用HAL庫開發STM32是目前ST官方主要推薦的方式,本篇文章對HAL做個基礎說明。下面文章中以STM32F4爲基礎進行介紹,其它系列的HAL庫在設計思路上也是差不多的。

HAL庫概述

STM32F4的HAL庫綜述在文檔《UM1725 - User Manual: Description of STM32F4 HAL and LL drivers》的第二篇章《Overview of HAL drivers》(文檔版本DocID025834 Rev 5 ),官方文檔本身寫得非常詳細,這裏做下簡單梳理。
下文中出現的。

文件說明

庫文件

在這裏插入圖片描述
上圖是HAL庫文件與引用包含關係,其中 ppp 用來指代外設,例如 gpio uart adc 等,箭頭起始文件引用包含了箭頭指向的文件,如user file引用了stm32f4xx_hal.h文件。主要文件描述如下:

文件 描述
stm32f4xx_hal_ppp.c
stm32f4xx_hal_ppp.h
外設基本驅動文件
stm32f4xx_hal_ppp_ex.c
stm32f4xx_hal_ppp_ex.h
外設擴展驅動文件
stm32f4xx_hal.c
stm32f4xx_hal.h
包含HAL初始化、DBGMCU、系統時間相關內容
stm32f4xx_hal_def.h 公共枚舉與宏定義等資源

用戶文件

這裏的用戶文件指的是使用stm32cube生成的項目所需的文件:

文件 描述
system_stm32f4xx.c 主要包含SystemInit(),用來初始化系統時鐘等
startup_stm32f4xx.s 目標芯片啓動文件
stm32f4xx_hal_msp.c 外設系統級初始化與反初始化
stm32f4xx_hal_conf.h HAL庫配置,用以適配項目
stm32f4xx_it.c
stm32f4xx_it.h
包含項目涉及的中斷服務程序
main.c
main.h
包含各類初始化以及用戶程序主入口

API

分類與命名

HAL庫大多數功能的外設API可以分爲兩類,Generic和Extension,這點從文檔目錄和庫文件命名上就可以看出。
Generic APIs就是指普通的、通用的API,一般來說這部分API是兼容所有STM32系列芯片的,如果你的項目中只用到這部分API的話那就可以非常方便的更換MCU型號。很多時候我們也只用到這些API就可以完成項目開發了。
Extension APIs指擴展的API,這部分API涉及不同STM32系列MCU差異部分功能的操作,所以並不兼容所有STM32芯片。這部分API細分的話也可以分成兩類Family specific APIs(不同系列芯片差異,比如F0、F1、F4等)和Device part number specific APIs(具體不同型號芯片差異,比如F401、F405、F429等)

命名規則見下表:
在這裏插入圖片描述
HAL庫中命名還是挺統一與簡單易懂的,比如使用某個GPIO口輸出使用,一般就是設置輸出電平,就算沒有實際用過也能知道相關函數是 HAL_GPIO_xxxxx ,使用UART發送相關函數是 HAL_UART_xxxxx ,配合IDE的代碼補全功能開發起來就得心應手:
在這裏插入圖片描述

基本API說明

功能分類

單個外設的API大體上可以分爲四類:

類別 說明 舉例
Initialization 初始化與反初始化 HAL_ADC_Init()
IO operation 啓動、停止、讀寫、回調函數等 HAL_ADC_Start ()
HAL_ADC_ConvCpltCallback()
Control 相關參數設置 HAL_ADC_ConfigChannel()
State and Errors 獲取狀態與錯誤信息 HAL_ADC_GetState()
HAL_ADC_GetError()

操作模型

對於外設IO中很多耗時操作HAL庫提供了三種模型:輪詢、中斷、DMA。比如串口讀寫數據就有三類方式:

  • 輪詢:HAL_UART_Transmit() & HAL_UART_Receive()
  • 中斷:HAL_UART_Transmit_IT() & HAL_UART_Receive_IT()
  • DMA:HAL_UART_Transmit_DMA() & HAL_UART_Receive_DMA()

輪詢是一種阻塞的方式、中斷和DMA是非阻塞方式(一般結合回調函數一起使用)。對於同一個外設使用時最好不要混用,不然可能會發生不可預知的問題。

回調函數

HAL庫對很對操作編寫了用 __weak 符號修飾的回調函數,用戶可以在自己的代碼中重新定義該回調函數實現具體功能,比如下面就是串口收發完成的回調函數:
HAL_UART_TxCpltCallback() & HAL_UART_RxCpltCallback()

公共資源

公共資源指全局的宏定義、枚舉、結構體等,主要定義在stm32fxxx_hal_def.h文件中。
這裏主要提一個HAL Status:

typedef enum 
{
  HAL_OK       = 0x00U,
  HAL_ERROR    = 0x01U,
  HAL_BUSY     = 0x02U,
  HAL_TIMEOUT  = 0x03U
} HAL_StatusTypeDef;

這個枚舉類型經常出現在操作設置等的返回值中,比如HAL_StatusTypeDef HAL_UART_Transmit(),寫代碼時可以通過該狀態知道操作是否成功等。

常用系統函數

STM32F4的HAL庫系統函數介紹在文檔《UM1725 - User Manual: Description of STM32F4 HAL and LL drivers》的第五篇章《HAL System Driver》(文檔版本DocID025834 Rev 5 )。這裏列出在STM32CubeMX生成代碼時不會用到的部分常用的函數:

  • __weak uint32_t HAL_GetTick(void)
    返回從系統運行開始經過的時間,默認情況下單位爲ms;
  • __weak void HAL_Delay(uint32_t Delay)
    延時,該延時是阻塞的,默認情況下延時單位爲ms,該函數不能在等於或高於系統時鐘源優先級(默認情況下爲0)的中斷程序中使用,不然程序就阻塞在這裏不動了;
  • __weak void HAL_SuspendTick(void)
    暫停系統時間運行,記得與HAL_ResumeTick()成對使用;
  • __weak void HAL_ResumeTick(void)
    繼續系統時間運行;
  • uint32_t HAL_GetUIDw0(void)
    uint32_t HAL_GetUIDw1(void)
    uint32_t HAL_GetUIDw2(void)
    STM32芯片 96位全球唯一ID。

特殊函數

特殊操作一般用的不多,這裏列舉部分常用的:

全局中斷

使用下面函數關閉/開啓全局中斷:
__disable_irq(); //關閉全局中斷,等同於__set_PRIMASK(1);
__enable_irq(); //開啓全局中斷,等同於__set_PRIMASK(0);
__disable_irq()操作相當於把當前運行的代碼優先級調整至0,所有其它用戶中斷程序將不會運行,直至重新開啓全局中斷。

使用下面函數也可以關閉/開啓全局中斷(有些系列的芯片沒有該組函數):
__disable_fault_irq(); //關閉全局中斷,等同於__set_FAULTMASK(1);
__enable_fault_irq(); //開啓全局中斷,等同於__set_FAULTMASK(0);
__disable_fault_irq()操作相當於把當前運行的代碼優先級調整至-1,硬件錯誤也將被屏蔽;

軟復位系統

使用 NVIC_SystemReset() 函數可以軟復位系統,最好配合關閉全局中斷使用,以免出現意外操作。

總結

HAL整體功能組織、命名還是比較不錯的。剛從標準外設庫(STD)轉過來的開發者可能會不太習慣,主要是兩者的設計思路上有區別。瞭解HAL庫的功能組織和命名習慣對於理解HAL庫設計思路、使用HAL庫進行開發還是有促進作用的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章