熟女俱乐部五十路二区av,又爽又黄禁片视频1000免费,国产卡一卡二卡三无线乱码新区,中文无码一区二区不卡αv,中文在线中文a

"); //-->

博客專欄

EEPW首頁 > 博客 > hal庫操作架構(gòu)

hal庫操作架構(gòu)

發(fā)布人:chh650319 時間:2019-06-11 來源:工程師 發(fā)布文章
  • stm32f2xx.h主要包含STM32同系列芯片的不同具體型號的定義,是否使用HAL庫等的定義,接著,其會根據(jù)定義的芯片信號包含具體的芯片型號的頭文件:

#if defined(STM32F205xx)

  #include "stm32f205xx.h"

#elif defined(STM32F215xx)

  #include "stm32f215xx.h"

#elif defined(STM32F207xx)

  #include "stm32f207xx.h"

#elif defined(STM32F217xx)

  #include "stm32f217xx.h"

#else

 #error "Please select first the target STM32F2xx device used in your application (in stm32f2xx.h file)"

#endif

緊接著,其會包含stm32f2xx_hal.h

  • stm32f2xx_hal.hstm32f2xx_hal.c/h 主要實現(xiàn)HAL庫的初始化、系統(tǒng)滴答相關(guān)函數(shù)、及CPU的調(diào)試模式配置

  • stm32f2xx_hal_conf.h :該文件是一個用戶級別的配置文件,用來實現(xiàn)對HAL庫的裁剪,其位于用戶文件目錄,不要放在庫目錄中。

??接下來對于HAL庫的源碼文件進行一下說明,HAL庫文件名均以stm32f2xx_hal開頭,后面加上_外設(shè)或者模塊名(如:stm32f2xx_hal_adc.c):

庫文件:

    stm32f2xx_hal_ppp.c/.h          // 主要的外設(shè)或者模塊的驅(qū)動源文件,包含了該外設(shè)的通用API

    stm32f2xx_hal_ppp_ex.c/.h       // 外圍設(shè)備或模塊驅(qū)動程序的擴展文件。這組文件中包含特定型號或者系列的芯片的特殊API。以及如果該特定的芯片內(nèi)部有不同的實現(xiàn)方式,則該文件中的特殊API將覆蓋_ppp中的通用API。

    stm32f2xx_hal.c/.h              // 此文件用于HAL初始化,并且包含DBGMCU、重映射和基于systick的時間延遲等相關(guān)的API

    其他庫文件

用戶級別文件:

    stm32f2xx_hal_msp_template.c    // 只有.c沒有.h。它包含用戶應(yīng)用程序中使用的外設(shè)的MSP初始化和反初始化(主程序和回調(diào)函數(shù))。使用者復(fù)制到自己目錄下使用模板。

    stm32f2xx_hal_conf_template.h   // 用戶級別的庫配置文件模板。使用者復(fù)制到自己目錄下使用

    system_stm32f2xx.c              // 此文件主要包含SystemInit()函數(shù),該函數(shù)在剛復(fù)位及跳到main之前的啟動過程中被調(diào)用。 **它不在啟動時配置系統(tǒng)時鐘(與標(biāo)準(zhǔn)庫相反)**。 時鐘的配置在用戶文件中使用HAL API來完成。

    startup_stm32f2xx.s             // 芯片啟動文件,主要包含堆棧定義,終端向量表等

    stm32f2xx_it.c/.h               // 中斷處理函數(shù)的相關(guān)實現(xiàn)

    main.c/.h                       //

 

??根據(jù)HAL庫的命名規(guī)則,其API可以分為以下三大類:

  • 初始化/反初始化函數(shù): HAL_PPP_Init(), HAL_PPP_DeInit()

  • IO 操作函數(shù): HAL_PPP_Read(),      HAL_PPP_Write(),HAL_PPP_Transmit(), HAL_PPP_Receive()

  • 控制函數(shù): HAL_PPP_Set (),      HAL_PPP_Get ().

  • 狀態(tài)和錯誤HAL_PPP_GetState      (), HAL_PPP_GetError ().

注意: 
1. 目前LL庫是和HAL庫捆綁發(fā)布的,所以在HAL庫源碼中,還有一些名為 stm32f2xx_ll_ppp的源碼文件,這些文件就是新增的LL庫文件。 
2. 使用CubeMX生產(chǎn)項目時,可以選擇LL

??HAL庫最大的特點就是對底層進行了抽象。在此結(jié)構(gòu)下,用戶代碼的處理主要分為三部分:

  • 處理外設(shè)句柄(實現(xiàn)用戶功能)

  • 處理MSP

  • 處理各種回調(diào)函數(shù)

外設(shè)句柄定義

??用戶代碼的第一大部分:對于外設(shè)句柄的處理。 HAL庫在結(jié)構(gòu)上,對每個外設(shè)抽象成了一個稱為ppp_HandleTypeDef的結(jié)構(gòu)體,其中ppp就是每個外設(shè)的名字。*所有的函數(shù)都是工作在ppp_HandleTypeDef指針之下。 
??1. 多實例支持:每個外設(shè)/模塊實例都有自己的句柄。 因此,實例資源是獨立的 
??2. 外圍進程相互通信:該句柄用于管理進程例程之間的共享數(shù)據(jù)資源。 
下面,以ADC為例

/**

 * @brief  ADC handle Structure definition

 */

typedef struct

{

    ADC_TypeDef                   *Instance;                   /*!< Register base address */

    ADC_InitTypeDef               Init;                        /*!< ADC required parameters */

  __IO uint32_t                 NbrOfCurrentConversionRank;  /*!< ADC number of current conversion rank */

    DMA_HandleTypeDef             *DMA_Handle;                 /*!< Pointer DMA Handler */

    HAL_LockTypeDef               Lock;                        /*!< ADC locking object */

    __IO uint32_t                 State;                       /*!< ADC communication state */

    __IO uint32_t                 ErrorCode;                   /*!< ADC Error code */

}ADC_HandleTypeDef;

??從上面的定義可以看出,ADC_HandleTypeDef中包含了ADC可能出現(xiàn)的所有定義,對于用戶想要使用ADC只要定義一個ADC_HandleTypeDef的變量,給每個變量賦好值,對應(yīng)的外設(shè)就抽象完了。接下來就是具體使用了。 
??當(dāng)然,對于那些共享型外設(shè)或者說系統(tǒng)外設(shè)來說,他們不需要進行以上這樣的抽象,這些部分與原來的標(biāo)準(zhǔn)外設(shè)庫函數(shù)基本一樣。例如以下外設(shè): 
??- GPIO 
??- SYSTICK 
??- NVIC 
??- RCC 
??- FLASH 
GPIO為例,對于HAL_GPIO_Init() 函數(shù),其只需要GPIO 地址以及其初始化參數(shù)即可。

三種編程方式

??HAL庫對所有的函數(shù)模型也進行了統(tǒng)一。在HAL庫中,支持三種編程模式:輪詢模式、中斷模式、DMA模式(如果外設(shè)支持)。其分別對應(yīng)如下三種類型的函數(shù)(以ADC為例):

HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc);

HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc);

 

HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);

HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);

 

HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);

HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc);

??其中,帶_IT的表示工作在中斷模式下;帶_DMA的工作在DMA模式下(注意:DMA模式下也是開中斷的);什么都沒帶的就是輪詢模式(沒有開啟中斷的)。至于使用者使用何種方式,就看自己的選擇了。 
??此外,新的HAL庫架構(gòu)下統(tǒng)一采用宏的形式對各種中斷等進行配置(原來標(biāo)準(zhǔn)外設(shè)庫一般都是各種函數(shù))。針對每種外設(shè)主要由以下宏:

  • __HAL_PPP_ENABLE_IT(__HANDLE__,      __INTERRUPT__) 使能一個指定的外設(shè)中斷

  • __HAL_PPP_DISABLE_IT(__HANDLE__, __INTERRUPT__):失能一個指定的外設(shè)中斷

  • __HAL_PPP_GET_IT (__HANDLE__, __      INTERRUPT __):獲得一個指定的外設(shè)中斷狀態(tài)

  • __HAL_PPP_CLEAR_IT (__HANDLE__,      __ INTERRUPT __):清除一個指定的外設(shè)的中斷狀態(tài)

  • __HAL_PPP_GET_FLAG (__HANDLE__,      __FLAG__):獲取一個指定的外設(shè)的標(biāo)志狀態(tài)

  • __HAL_PPP_CLEAR_FLAG (__HANDLE__,      __FLAG__):清除一個指定的外設(shè)的標(biāo)志狀態(tài)

  • __HAL_PPP_ENABLE(__HANDLE__) :使能外設(shè)

  • __HAL_PPP_DISABLE(__HANDLE__) :失能外設(shè)

  • __HAL_PPP_XXXX (__HANDLE__,      __PARAM__) :指定外設(shè)的宏定義

  • __HAL_PPP_GET_ IT_SOURCE      (__HANDLE__, __ INTERRUPT __):檢查中斷源

三大回調(diào)函數(shù)

??HAL庫的源碼中,到處可見一些以__weak開頭的函數(shù),而且這些函數(shù),有些已經(jīng)被實現(xiàn)了,比如:

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)

{

    /*Configure the SysTick to have interrupt in 1ms time basis*/

    HAL_SYSTICK_Config(SystemCoreClock/1000U);

    /*Configure the SysTick IRQ priority */

    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority ,0U);

    /* Return function status */

    return HAL_OK;

}

有些則沒有被實現(xiàn),例如:

__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)

{

  /* Prevent unused argument(s) compilation warning */

  UNUSED(hspi);

  /* NOTE : This function should not be modified, when the callback is needed,the HAL_SPI_TxCpltCallback should be implemented in the user file

  */

}

所有帶有__weak關(guān)鍵字的函數(shù)表示,就可以由用戶自己來實現(xiàn)。如果出現(xiàn)了同名函數(shù),且不帶__weak關(guān)鍵字,那么連接器就會采用外部實現(xiàn)的同名函數(shù)。通常來說,HAL庫負責(zé)整個處理和MCU外設(shè)的處理邏輯,并將必要部分以回調(diào)函數(shù)的形式給出到用戶,用戶只需要在對應(yīng)的回調(diào)函數(shù)中做修改即可。 HAL庫包含如下三種用戶級別回調(diào)函數(shù)(PPP為外設(shè)名): 
??1. 外設(shè)系統(tǒng)級初始化/解除初始化回調(diào)函數(shù)(用戶代碼的第二大部分:對于MSP的處理):HAL_PPP_MspInit() HAL_PPP_MspDeInit**。例如:__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)。在HAL_PPP_Init() 函數(shù)中被調(diào)用,用來初始化底層相關(guān)的設(shè)備(GPIOs, clock, DMA, interrupt

??2. 處理完成回調(diào)函數(shù):HAL_PPP_ProcessCpltCallback*Process指具體某種處理,如UARTTx),例如:__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)。當(dāng)外設(shè)或者DMA工作完成后時,觸發(fā)中斷,該回調(diào)函數(shù)會在外設(shè)中斷處理函數(shù)或者DMA的中斷處理函數(shù)中被調(diào)用

??3. 錯誤處理回調(diào)函數(shù):HAL_PPP_ErrorCallback例如:__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)**。當(dāng)外設(shè)或者DMA出現(xiàn)錯誤時,觸發(fā)終端,該回調(diào)函數(shù)會在外設(shè)中斷處理函數(shù)或者DMA的中斷處理函數(shù)中被調(diào)用

  1. 絕大多數(shù)用戶代碼均在以上三大回調(diào)函數(shù)中實現(xiàn)。

  2. HAL庫結(jié)構(gòu)中,在每次初始化前(尤其是在多次調(diào)用初始化前),先調(diào)用對應(yīng)的反初始化(DeInit)函數(shù)是非常有必要的。某些外設(shè)多次初始化時不調(diào)用返回會導(dǎo)致初始化失敗。

  3. 完成回調(diào)函數(shù)有多中,例如串口的完成回調(diào)函數(shù)有HAL_UART_TxCpltCallback HAL_UART_TxHalfCpltCallback

  4. (用戶代碼的第三大部分:對于上面第二點和第三點的各種回調(diào)函數(shù)的處理)

  5. 在實際使用中,發(fā)現(xiàn)HAL仍有不少問題,例如在使用USB時,其庫配置存在問題

HAL庫移植使用

基本步驟

  1. 復(fù)制stm32f2xx_hal_msp_template.c,參照該模板,依次實現(xiàn)用到的外設(shè)的HAL_PPP_MspInit() HAL_PPP_MspDeInit。

  2. 復(fù)制stm32f2xx_hal_conf_template.h,用戶可以在此文件中自由裁剪,配置HAL庫。

  3. 在使用HAL庫時,必須先調(diào)用函數(shù):HAL_StatusTypeDef      HAL_Init(void)(該函數(shù)在stm32f2xx_hal.c中定義,也就意味著第一點中,必須首先實現(xiàn)HAL_MspInit(void)HAL_MspDeInit(void)

  4. HAL庫與STD庫不同,HAL庫使用RCC中的函數(shù)來配置系統(tǒng)時鐘,用戶需要單獨寫時鐘配置函數(shù)(STD庫默認在system_stm32f2xx.c中)

  5. 關(guān)于中斷,HAL提供了中斷處理函數(shù),只需要調(diào)用HAL提供的中斷處理函數(shù)。用戶自己的代碼,不建議先寫到中斷中,而應(yīng)該寫到HAL提供的回調(diào)函數(shù)中。

  6. 對于每一個外設(shè),HAL都提供了回調(diào)函數(shù),回調(diào)函數(shù)用來實現(xiàn)用戶自己的代碼。整個調(diào)用結(jié)構(gòu)由HAL庫自己完成。例如:Uart中,HAL提供了void      HAL_UART_IRQHandler(UART_HandleTypeDef *huart);函數(shù),用戶只需要觸發(fā)中斷后,用戶只需要調(diào)用該函數(shù)即可,同時,自己的代碼寫在對應(yīng)的回調(diào)函數(shù)中即可!如下:

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);

void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);

使用了哪種就用哪個回調(diào)函數(shù)即可!

基本結(jié)構(gòu)

??綜上所述,使用HAL庫編寫程序(針對某個外設(shè))的基本結(jié)構(gòu)(以串口為例)如下: 
1. 配置外設(shè)句柄。例如,建立UartConfig.c,在其中定義串口句柄 UART_HandleTypeDef huart;,接著使用初始化句柄(HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)) 
2. 編寫Msp。 例如,建立UartMsp.c,在其中實現(xiàn)void HAL_UART_MspInit(UART_HandleTypeDef* huart) void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) 
3. 實現(xiàn)對應(yīng)的回調(diào)函數(shù)。例如,建立UartCallBack.c,在其中實現(xiàn)上文所說明的三大回調(diào)函數(shù)中的完成回調(diào)函數(shù)錯誤回調(diào)函數(shù)


*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。



關(guān)鍵詞:

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉