哈哈哈哈哈操欧洲电影,久草网在线,亚洲久久熟女熟妇视频,麻豆精品色,久久福利在线视频,日韩中文字幕的,淫乱毛视频一区,亚洲成人一二三,中文人妻日韩精品电影

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

全網(wǎng)最全STM32 HAL的知識總結(jié)

Q4MP_gh_c472c21 ? 來源:博客園、CSDN ? 作者:csdnpapa、焦糖-布丁 ? 2021-06-28 17:54 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

ST 為開發(fā)者提供了非常方便的開發(fā)庫:有標準外設庫(SPL庫)、HAL 庫(Hardware Abstraction Layer,硬件抽象層庫)、LL 庫(Low-Layer,底層庫)三種。前者是ST的老庫已經(jīng)停更了,后兩者是ST現(xiàn)在主推的開發(fā)庫。

相比標準外設庫,STM32Cube HAL庫表現(xiàn)出更高的抽象整合水平,HAL API集中關注各外設的公共函數(shù)功能,這樣便于定義一套通用的用戶友好的API函數(shù)接口,從而可以輕松實現(xiàn)從一個STM32產(chǎn)品移植到另一個不同的STM32系列產(chǎn)品。HAL庫是ST未來主推的庫,ST新出的芯片已經(jīng)沒有STD庫了,比如F7系列。目前,HAL庫已經(jīng)支持STM32全線產(chǎn)品。

通過文字描述可以知道HAL庫的幾個點:1.最大可移植性。2.提供了一整套一致的中間件組件,如RTOS,USB,TCP / IP和圖形等。3.通用的用戶友好的API函數(shù)接口。4.ST新出的芯片已經(jīng)沒有標準庫。5.HAL庫已經(jīng)支持STM32全線產(chǎn)品。

網(wǎng)友認為,“HAL我覺得是極好的,就是SPI接收時速度實在太慢,不用DMA的話,吃不消。“

通常新手在入門STM32的時候,首先都要先選擇一種要用的開發(fā)方式,不同的開發(fā)方式會導致你編程的架構是完全不一樣的。一般大多數(shù)都會選用標準庫和HAL庫,而極少部分人會通過直接配置寄存器進行開發(fā)。網(wǎng)上關于標準庫、HAL庫的描述相信是數(shù)不勝數(shù)。

可是一個對于很多剛?cè)腴T的朋友還是沒法很直觀的去真正了解這些不同開發(fā)方式彼此之間的區(qū)別,所以筆者想以一種非常直白的方式,用自己的理解去將這些東西表述出來,如果有描述的不對的地方或者是不同意見的也可以大家提出。

01、直接配置寄存器

不少先學了51的朋友可能會知道,會有一小部分人或是教程是通過匯編語言直接操作寄存器實現(xiàn)功能的,這種方法到了STM32就變得不太容易行得通了,因為STM32的寄存器數(shù)量是51單片機的十數(shù)倍,如此多的寄存器根本無法全部記憶,開發(fā)時需要經(jīng)常的翻查芯片的數(shù)據(jù)手冊,此時直接操作寄存器就變得非常的費力了。但還是會有很小一部分人,喜歡去直接操作寄存器,因為這樣更接近原理,知其然也知其所以然。

02、標準庫

上面也提到了,STM32有非常多的寄存器,而導致了開發(fā)困難,所以為此ST公司就為每款芯片都編寫了一份庫文件,也就是工程文件里stm32F1xx…之類的。在這些 .c .h文件中,包括一些常用量的宏定義,把一些外設也通過結(jié)構體變量封裝起來,如GPIO口時鐘等。所以我們只需要配置結(jié)構體變量成員就可以修改外設的配置寄存器,從而選擇不同的功能。也是目前最多人使用的方式,也是學習STM32接觸最多的一種開發(fā)方式,我也就不多闡述了。

03、HAL庫

HAL庫是ST公司目前主力推的開發(fā)方式,全稱就是Hardware Abstraction Layer(抽象印象層)。庫如其名,很抽象,一眼看上去不太容易知道他的作用是什么。它的出現(xiàn)比標準庫要晚,但其實和標準庫一樣,都是為了節(jié)省程序開發(fā)的時期,而且HAL庫尤其的有效,如果說標準庫把實現(xiàn)功能需要配置的寄存器集成了,那么HAL庫的一些函數(shù)甚至可以做到某些特定功能的集成。

也就是說,同樣的功能,標準庫可能要用幾句話,HAL庫只需用一句話就夠了。并且HAL庫也很好的解決了程序移植的問題,不同型號的stm32芯片它的標準庫是不一樣的,例如在F4上開發(fā)的程序移植到F3上是不能通用的,而使用HAL庫,只要使用的是相通的外設,程序基本可以完全復制粘貼,注意是相通外設,意思也就是不能無中生有。

例如F7比F3要多幾個定時器,不能明明沒有這個定時器卻非要配置,但其實這種情況不多,絕大多數(shù)都可以直接復制粘貼。是而且使用ST公司研發(fā)的STMcube軟件,可以通過圖形化的配置功能,直接生成整個使用HAL庫的工程文件,可以說是方便至極,但是方便的同時也造成了它執(zhí)行效率的低下,在各種論壇帖子真的是被吐槽的數(shù)不勝數(shù)。

HAL庫和標準固件庫區(qū)別

STM32的開發(fā)中,我們可以操作寄存器:

GPIOF-》BSRR=0x00000001;//這里是針對STM32F1系列

這種方法當然可以,但是這種方法的劣勢是你需要去掌握每個寄存器的用法,你才能正確使用STM32,而對于STM32這種級別的MCU,數(shù)百個寄存器記起來又是談何容易。于是ST(意法半導體)推出了官方標準固件庫,標準固件庫將這些寄存器底層操作都封裝起來,提供一整套接口(API)供開發(fā)者調(diào)用,大多數(shù)場合下,你不需要去知道操作的是哪個寄存器,你只需要知道調(diào)用哪些函數(shù)即可。

比如上面的控制 BRR 寄存器實現(xiàn)電平控制,官方庫封裝了一個函數(shù):

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin){GPIOx-》BRR= GPIO_Pin;}

這個時候你不需要再直接去操作 BRR 寄存器了,你只需要知道怎么使用 GPIO_ResetBits()這個函數(shù)就可以了。在你對外設的工作原理有一定的了解之后,你再去看標準庫函數(shù),基本上函數(shù)名字能告訴你這個函數(shù)的功能是什么,該怎么使用,這樣開發(fā)就方便很多。

標準固件庫自推出以來受到廣大工程師推崇,現(xiàn)在很多工程師和公司還在使用標準庫函數(shù)開發(fā)。不過,ST官方已經(jīng)不再更新STM32標準固件庫,而是力推新的固件庫:HAL庫。

比如上面的控制BSRRL 寄存器實現(xiàn)電平控制,官方 HAL 庫封裝了一個函數(shù):

voidHAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,GPIO_PinStatePinState){assert_param(IS_GPIO_PIN(GPIO_Pin));assert_param(IS_GPIO_PIN_ACTION(PinState));if(PinState!= GPIO_PIN_RESET){GPIOx-》BSRR= GPIO_Pin;}else{GPIOx-》BSRR= (uint32_t)GPIO_Pin 《《 16;}}

這個時候你不需要再直接去操作BSRRL 寄存器了,你只需要知道怎么使用HAL_GPIO_WritePin這個函數(shù)就可以了。

標準固件庫和HAL庫一樣都是固件庫函數(shù),由ST官方硬件抽象層而設計的軟件函數(shù)包,由程序、數(shù)據(jù)結(jié)構和宏組成,包括了STM32所有外設的性能特征。 這些固件庫為開發(fā)者底層硬件提供了中間API,通過使用固件庫,無需掌握底層細節(jié),開發(fā)者就可以輕松應用每一個外設。

HAL 庫和標準庫本質(zhì)上是一樣的,都是提供底層硬件操作 API,而且在使用上也是大同小異。有過標準庫基礎的同學對 HAL 庫的使用也很容易入手。ST 官方之所以這幾年大力推廣 HAL 庫,是因為 HAL 的結(jié)構更加容易整合 STM32Cube,而 STM32CubeMX 是 ST 這幾年極力推薦的程序生成開發(fā)工具。所以這幾年新出的 STM32 芯片,ST 直接只提供 HAL 庫。

在ST的官方聲明中,HAL庫是大勢所趨。ST最新開發(fā)的芯片中,只有HAL庫沒有標準庫。標準庫和HAL庫雖然都是對外設進行操作的函數(shù),但由于標準庫官方已經(jīng)停止更新,而且標準庫在STM32創(chuàng)建工程和初始化時,不能由CubMX軟件代碼生成使用,也就是說CubMX軟件在生產(chǎn)代碼時。

工程項目和初始化代碼就自動生成,這個工程項目和初始化代碼里面使用的庫都是基于HAL庫的。STM32CubeMX是一個圖形化的工具,也是配置和初始化C代碼生成器 ,與STM32CubeMX配合使用的是HAL庫(硬件抽象層軟件庫)。

基本配置

工程創(chuàng)建

通過內(nèi)核芯片的選擇,創(chuàng)建相應的工程文件。

對時鐘系統(tǒng)進行配置,對引腳及基本功能進行配置。

配置時鐘系統(tǒng)我們首要思考的是:我們需要怎樣的時鐘系統(tǒng),而不是如何配置時鐘系統(tǒng)。

配置SWD程序燒錄接口,使用ST-Link進行燒錄下載。

工程管理設置推薦圖中所示配置,實現(xiàn)更快編譯和更簡潔的文件系統(tǒng)。

點擊“GENERATE CODE”生成Keil工程文件

如果你已經(jīng)安裝了編譯環(huán)境MDK了,可點擊直接打開工程。

GPIO使用

開發(fā)環(huán)境搭建好以后,可以依開始STM32的開發(fā),下面是使用GPIO的例程,讓LED燈每隔400ms閃爍一次

打開STM32CubeMX新建工程,選擇STM32F103ZET6芯片。選擇外部高速晶振(HSE)。

根據(jù)下位機主控引腳分配圖及原理圖,選擇LED引腳

PD7為LED1輸出控制管腳,選擇GPIO_OUTPUT模式。

點擊Clock Configuration配置系統(tǒng)時鐘為72M最高速度。

點擊Configuration-》GPIO配置管腳。LED管腳配置為低速推挽輸出模式,既不上拉也不下拉(即默認的模式不用配置)。

點擊生成報告,軟件會提示新建工程,輸入工程名,選擇工程保存路徑。IDE選擇MDK-ARM V5。

在Code Generator中找到Generated files框,勾選Generated periphera initialization as a pair of ‘.c/.h’files per IP。外設初始化為獨立的C文件和頭文件。

點擊生成代碼。點擊Open Project打開工程。到這里我們就配置好工程外設初始化。

點擊Build按鈕,然后等一會,Build Optput信息框會輸出沒有錯誤沒有警告。在main函數(shù)里添加如下代碼

延時電平翻轉(zhuǎn)函數(shù),這樣LED燈就能開始閃爍。

再點擊Build按鈕,然后等一會,Build Optput信息框會輸出沒有錯誤沒有警告。代碼燒寫。

現(xiàn)在開始燒寫程序,燒寫程序有兩種,一種是使用ST-LINK工具燒寫,一種是直接用與上位機通訊的串口1燒寫。燒寫工具使用mcuisp。

軟件可自行網(wǎng)上搜索,下載配置如下。

選擇好串口端口后,可以開始下載。

HAL庫固件庫安裝與用戶手冊

1.首先設置讓Cube可以自動聯(lián)網(wǎng)下載相關固件庫選擇updater Settings

2.根據(jù)芯片選擇所需固件版本是向下兼容的,可以直接選擇最新版。但如果覺得最新版太大,可以閱讀下面的Main Changes.能夠支持你目前的芯片就好。

選好了,點擊Install Now就行,過程可能有點長。建議直接官網(wǎng)下載到本地,再安裝

文件會被下載到如下位置,建議更改此目錄,不要選在C盤?。。?/p>

查找?guī)椭謨?/p>

3.尋找用戶幫助手冊進入固件所在文件夾,里面包含很多內(nèi)容。

比如說 官方提供的開發(fā)板程序

每個型號下面都有對應功能的實現(xiàn)

用戶手冊就在Drivers文件夾下面。

STM32 HAL庫與標準庫的區(qū)別——淺談句柄、MSP函數(shù)、Callback函數(shù)

01句柄

句柄(handle),有多種意義,其中第一種是指程序設計,第二種是指Windows編程?,F(xiàn)在大部分都是指程序設計/程序開發(fā)這類。

· 第一種解釋:句柄是一種特殊的智能指針。當一個應用程序要引用其他系統(tǒng)(如數(shù)據(jù)庫、操作系統(tǒng))所管理的內(nèi)存塊或?qū)ο髸r,就要使用句柄?!?第二種解釋:整個Windows編程的基礎。一個句柄是指使用的一個唯一的整數(shù)值,即一個4字節(jié)(64位程序中為8字節(jié))長的數(shù)值,來標識應用程序中的不同對象和同類中的不同的實例。

諸如,一個窗口,按鈕,圖標,滾動條,輸出設備,控件或者文件等。應用程序能夠通過句柄訪問相應的對象的信息,但是句柄不是指針,程序不能利用句柄來直接閱讀文件中的信息。如果句柄不在I/O文件中,它是毫無用處的。句柄是Windows用來標志應用程序中建立的或是使用的唯一整數(shù),Windows大量使用了句柄來標識對象。

STM32的標準庫中,句柄是一種特殊的指針,通常指向結(jié)構體!

在STM32的標準庫中,假設我們要初始化一個外設(這里以USART為例),我們首先要初始化他們的各個寄存器。在標準庫中,這些操作都是利用固件庫結(jié)構體變量+固件庫Init函數(shù)實現(xiàn)的:

USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate = bound;//串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數(shù)據(jù)格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數(shù)據(jù)流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收發(fā)模式

USART_Init(USART3, &USART_InitStructure); //初始化串口1

可以看到,要初始化一個串口,需要:

· 1、對六個位置進行賦值,

· 2、然后引用Init函數(shù),

USART_InitStructure并不是一個全局結(jié)構體變量,而是只在函數(shù)內(nèi)部的局部變量,初始化完成之后,USART_InitStructure就失去了作用。

而在HAL庫中,同樣是USART初始化結(jié)構體變量,我們要定義為全局變量。

UART_HandleTypeDef UART1_Handler;

typedef struct{ USART_TypeDef *Instance; /*!《 UART registers base address */ UART_InitTypeDef Init; /*!《 UART communication parameters */ uint8_t *pTxBuffPtr; /*!《 Pointer to UART Tx transfer Buffer */ uint16_t TxXferSize; /*!《 UART Tx Transfer size */ uint16_t TxXferCount; /*!《 UART Tx Transfer Counter */ uint8_t *pRxBuffPtr; /*!《 Pointer to UART Rx transfer Buffer */ uint16_t RxXferSize; /*!《 UART Rx Transfer size */ uint16_t RxXferCount; /*!《 UART Rx Transfer Counter */ DMA_HandleTypeDef *hdmatx; /*!《 UART Tx DMA Handle parameters */ DMA_HandleTypeDef *hdmarx; /*!《 UART Rx DMA Handle parameters */ HAL_LockTypeDef Lock; /*!《 Locking object */ __IO HAL_UART_StateTypeDef State; /*!《 UART communication state */ __IO uint32_t ErrorCode; /*!《 UART Error code */}UART_HandleTypeDef;

我們發(fā)現(xiàn),與標準庫不同的是,該成員不僅:

· 1、包含了之前標準庫就有的六個成員(波特率,數(shù)據(jù)格式等),· 2、還包含過采樣、(發(fā)送或接收的)數(shù)據(jù)緩存、數(shù)據(jù)指針、串口 DMA 相關的變量、各種標志位等等要在整個項目流程中都要設置的各個成員。該UART1_Handler就被稱為串口的句柄,它被貫穿整個USART收發(fā)的流程,比如開啟中斷:

HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);

比如后面要講到的MSP與Callback回調(diào)函數(shù):

void HAL_UART_MspInit(UART_HandleTypeDef *huart);void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

在這些函數(shù)中,只需要調(diào)用初始化時定義的句柄UART1_Handler就好。

02MSP函數(shù)

MSP: MCU Specific Package 單片機的具體方案

MSP是指和MCU相關的初始化,引用一下正點原子的解釋,個人覺得說的很明白:我們要初始化一個串口,首先要設置和 MCU 無關的東西,例如波特率,奇偶校驗,停止位等,這些參數(shù)設置和 MCU 沒有任何關系,可以使用 STM32F1,也可以是 STM32F2/F3/F4/F7上的串口。而一個串口設備它需要一個 MCU 來承載,例如用 STM32F4 來做承載,PA9 做為發(fā)送,PA10 做為接收,MSP 就是要初始化 STM32F4 的 PA9,PA10,配置這兩個引腳。所以 HAL驅(qū)動方式的初始化流程就是:

HAL_USART_Init()—》HAL_USART_MspInit() ,先初始化與 MCU無關的串口協(xié)議,再初始化與 MCU 相關的串口引腳。

在 STM32 的 HAL 驅(qū)動中HAL_PPP_MspInit()作為回調(diào),HAL_PPP_Init()函數(shù)所調(diào)用。當我們需要移植程序到 STM32F1平臺的時候,我們只需要修改 HAL_PPP_MspInit 函數(shù)內(nèi)容而不需要修改 HAL_PPP_Init 入口參數(shù)內(nèi)容。在HAL庫中,幾乎每初始化一個外設就需要設置該外設與單片機之間的聯(lián)系,比如IO口,是否復用等等,可見,HAL庫相對于標準庫多了MSP函數(shù)之后,移植性非常強,但與此同時卻增加了代碼量和代碼的嵌套層級??梢哉f各有利弊。

同樣,MSP函數(shù)又可以配合句柄,達到非常強的移植性:

void HAL_UART_MspInit(UART_HandleTypeDef *huart);

入口參數(shù)僅僅需要一個串口句柄,這樣就能看出句柄的方便。

03Callback函數(shù)

類似于MSP函數(shù),個人認為Callback函數(shù)主要幫助用戶應用層的代碼編寫。

還是以USART為例,在標準庫中,串口中斷了以后,我們要先在中斷中判斷是否是接收中斷,然后讀出數(shù)據(jù),順便清除中斷標志位,然后再是對數(shù)據(jù)的處理,這樣如果我們在一個中斷函數(shù)中寫這么多代碼,就會顯得很混亂:

void USART3_IRQHandler(void) //串口1中斷服務程序{u8 Res;if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾){Res =USART_ReceiveData(USART3);//讀取接收到的數(shù)據(jù)/*數(shù)據(jù)處理區(qū)*/} }}

而在HAL庫中,進入串口中斷后,直接由HAL庫中斷函數(shù)進行托管:

void USART1_IRQHandler(void) {HAL_UART_IRQHandler(&UART1_Handler);//調(diào)用HAL庫中斷處理公用函數(shù)/***************省略無關代碼****************/}

HAL_UART_IRQHandler這個函數(shù)完成了判斷是哪個中斷(接收?發(fā)送?或者其他?),然后讀出數(shù)據(jù),保存至緩存區(qū),順便清除中斷標志位等等操作。比如我提前設置了,串口每接收五個字節(jié),我就要對這五個字節(jié)進行處理。在一開始我定義了一個串口接收緩存區(qū):

/*HAL庫使用的串口接收緩沖,處理邏輯由HAL庫控制,接收完這個數(shù)組就會調(diào)用HAL_UART_RxCpltCallback進行處理這個數(shù)組*//*RXBUFFERSIZE=5*/u8 aRxBuffer[RXBUFFERSIZE];

在初始化中,我在句柄里設置好了緩存區(qū)的地址,緩存大?。ㄎ鍌€字節(jié))

/*該代碼在HAL_UART_Receive_IT函數(shù)中,初始化時會引用*/huart-》pRxBuffPtr = pData;//aRxBuffer huart-》RxXferSize = Size;//RXBUFFERSIZE huart-》RxXferCount = Size;//RXBUFFERSIZE

則在接收數(shù)據(jù)中,每接收完五個字節(jié),HAL_UART_IRQHandler才會執(zhí)行一次Callback函數(shù):

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

在這個Callback回調(diào)函數(shù)中,我們只需要對這接收到的五個字節(jié)(保存在aRxBuffer[]中)進行處理就好了,完全不用再去手動清除標志位等操作。所以說Callback函數(shù)是一個應用層代碼的函數(shù),我們在一開始只設置句柄里面的各個參數(shù),然后就等著HAL庫把自己安排好的代碼送到手中就可以了~

綜上,就是HAL庫的三個與標準庫不同的地方之個人見解。個人覺得從這三個小點就可以看出HAL庫的可移植性之強大,并且用戶可以完全不去理會底層各個寄存器的操作,代碼也更有邏輯性。但與此帶來的是復雜的代碼量,極慢的編譯速度,略微低下的效率。看怎么取舍了。

04STM32 HAL庫結(jié)構

說到STM32的HAL庫,就不得不提STM32CubeMX,其作為一個可視化的配置工具,對于開發(fā)者來說,確實大大節(jié)省了開發(fā)時間。STM32CubeMX就是以HAL庫為基礎的,且目前僅支持HAL庫及LL庫!首先看一下,官方給出的HAL庫的包含結(jié)構:

· 4.1 stm32f4xx.h主要包含STM32同系列芯片的不同具體型號的定義,是否使用HAL庫等的定義,接著,其會根據(jù)定義的芯片信號包含具體的芯片型號的頭文件:

#if defined(STM32F405xx) #include “stm32f405xx.h”#elif defined(STM32F415xx) #include “stm32f415xx.h”#elif defined(STM32F407xx) #include “stm32f407xx.h”#elif defined(STM32F417xx) #include “stm32f417xx.h”#else #error “Please select first the target STM32F4xx device used in your application (in stm32f2xx.h file)”#endif

緊接著,其會包含stm32f4xx_hal.h。

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

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

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

· 4.4 庫文件

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

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

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

· 4.5 其他庫文件

用戶級別文件:

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

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

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

startup_stm32f4xx.s // 芯片啟動文件,主要包含堆棧定義,終端向量表等stm32f4xx_it.c/.h // 中斷處理函數(shù)的相關實現(xiàn)

· 4.6 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 ()。

注意:目前LL庫是和HAL庫捆綁發(fā)布的,所以在HAL庫源碼中,還有一些名為 stm32f2xx_ll_ppp的源碼文件,這些文件就是新增的LL庫文件。

使用CubeMX生產(chǎn)項目時,可以選擇LL庫?

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

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

· 處理MSP

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

相關知識如下:

· (1) 外設句柄定義??用戶代碼的第一大部分:對于外設句柄的處理。HAL庫在結(jié)構上,對每個外設抽象成了一個稱為ppp_HandleTypeDef的結(jié)構體,其中ppp就是每個外設的名字。*所有的函數(shù)都是工作在ppp_HandleTypeDef指針之下。??

1. 多實例支持:每個外設/模塊實例都有自己的句柄。因此,實例資源是獨立的?

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的變量,給每個變量賦好值,對應的外設就抽象完了。接下來就是具體使用了。??當然,對于那些共享型外設或者說系統(tǒng)外設來說,他們不需要進行以上這樣的抽象,這些部分與原來的標準外設庫函數(shù)基本一樣。

例如以下外設:- GPIO?- SYSTICK??- NVIC??- RCC??- FLASH以GPIO為例,對于HAL_GPIO_Init() 函數(shù),其只需要GPIO 地址以及其初始化參數(shù)即可。

· (2) 三種編程方式??HAL庫對所有的函數(shù)模型也進行了統(tǒng)一。在HAL庫中,支持三種編程模式:輪詢模式、中斷模式、DMA模式(如果外設支持)。其分別對應如下三種類型的函數(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庫架構下統(tǒng)一采用宏的形式對各種中斷等進行配置(原來標準外設庫一般都是各種函數(shù))。針對每種外設主要由以下宏:

__HAL_PPP_ENABLE_IT(HANDLE, INTERRUPT): 使能一個指定的外設中斷__HAL_PPP_DISABLE_IT(HANDLE, INTERRUPT):失能一個指定的外設中斷__HAL_PPP_GET_IT (HANDLE, __ INTERRUPT __):獲得一個指定的外設中斷狀態(tài)__HAL_PPP_CLEAR_IT (HANDLE, __ INTERRUPT __):清除一個指定的外設的中斷狀態(tài)__HAL_PPP_GET_FLAG (HANDLE, FLAG):獲取一個指定的外設的標志狀態(tài)__HAL_PPP_CLEAR_FLAG (HANDLE, FLAG):清除一個指定的外設的標志狀態(tài)__HAL_PPP_ENABLE(HANDLE) :使能外設__HAL_PPP_DISABLE(HANDLE) :失能外設__HAL_PPP_XXXX (HANDLE, PARAM) :指定外設的宏定義_HAL_PPP_GET IT_SOURCE (HANDLE, __ INTERRUPT __):檢查中斷源

· (3)三大回調(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關鍵字的函數(shù)表示,就可以由用戶自己來實現(xiàn)。如果出現(xiàn)了同名函數(shù),且不帶__weak關鍵字,那么連接器就會采用外部實現(xiàn)的同名函數(shù)。通常來說,HAL庫負責整個處理和MCU外設的處理邏輯,并將必要部分以回調(diào)函數(shù)的形式給出到用戶,用戶只需要在對應的回調(diào)函數(shù)中做修改即可。HAL庫包含如下三種用戶級別回調(diào)函數(shù)(PPP為外設名):

1. 外設系統(tǒng)級初始化/解除初始化回調(diào)函數(shù)(用戶代碼的第二大部分:對于MSP的處理):HAL_PPP_MspInit()和 HAL_PPP_MspDeInit** 例如:__weak voidHAL_SPI_MspInit(SPI_HandleTypeDef *hspi)。在HAL_PPP_Init() 函數(shù)中被調(diào)用,用來初始化底層相關的設備(GPIOs, clock, DMA, interrupt)

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

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

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

HAL庫結(jié)構中,在每次初始化前(尤其是在多次調(diào)用初始化前),先調(diào)用對應的反初始化(DeInit)函數(shù)是非常有必要的。某些外設多次初始化時不調(diào)用返回會導致初始化失敗。完成回調(diào)函數(shù)有多種,例如串口的完成回調(diào)函數(shù)有HAL_UART_TxCpltCallback 和 HAL_UART_TxHalfCpltCallback等(用戶代碼的第三大部分:對于上面第二點和第三點的各種回調(diào)函數(shù)的處理)在實際使用中,發(fā)現(xiàn)HAL仍有不少問題,例如在使用USB時,其庫配置存在問題

05HAL庫移植使用

基本步驟

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

2.復制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.關于中斷,HAL提供了中斷處理函數(shù),只需要調(diào)用HAL提供的中斷處理函數(shù)。用戶自己的代碼,不建議先寫到中斷中,而應該寫到HAL提供的回調(diào)函數(shù)中。

6.對于每一個外設,HAL都提供了回調(diào)函數(shù),回調(diào)函數(shù)用來實現(xiàn)用戶自己的代碼。整個調(diào)用結(jié)構由HAL庫自己完成。例如:Uart中,HAL提供了void HAL_UART_IRQHandler(UART_HandleTypeDef *huart);函數(shù),用戶只需要觸發(fā)中斷后,用戶只需要調(diào)用該函數(shù)即可,同時,自己的代碼寫在對應的回調(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é)構?綜上所述,使用HAL庫編寫程序(針對某個外設)的基本結(jié)構(以串口為例)如下:

1.配置外設句柄 例如,建立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)對應的回調(diào)函數(shù) 例如,建立UartCallBack.c,在其中實現(xiàn)上文所說明的三大回調(diào)函數(shù)中的完成回調(diào)函數(shù)和錯誤回調(diào)函數(shù)

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5619

    瀏覽量

    130391
  • ST
    ST
    +關注

    關注

    32

    文章

    1193

    瀏覽量

    132751
  • STM32
    +關注

    關注

    2312

    文章

    11189

    瀏覽量

    374554
  • 函數(shù)
    +關注

    關注

    3

    文章

    4421

    瀏覽量

    67822
  • dma
    dma
    +關注

    關注

    3

    文章

    582

    瀏覽量

    106252

原文標題:STM32 HAL的超全知識總結(jié)

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    MOSFET管開關電路基本知識總結(jié)

    總結(jié)以上知識,在選MOSFET開關時,首先選MOS管的VDS電壓,和其VGS開啟電壓,再就是ID電流值是否滿足系統(tǒng)需要,然后再考慮封裝了,功耗了,價格了之類次要一些的因素了,以上是用P溝道MOS管做的例子,N溝道的其實也是基本上一樣用的。
    的頭像 發(fā)表于 04-20 11:26 ?165次閱讀
    MOSFET管開關電路基本<b class='flag-5'>知識</b><b class='flag-5'>總結(jié)</b>

    RK3576平臺Android HAL層故障排查:從lshal命令看透問題本質(zhì)

    ? ? ? 在 Android 嵌入式開發(fā)中, HAL (硬件抽象層)是連接系統(tǒng)框架與硬件驅(qū)動的核心橋梁,一旦 HAL 層出問題,音頻、藍牙、傳感器等硬件功能都會直接 “ 罷工 ” 。而
    的頭像 發(fā)表于 02-06 07:12 ?587次閱讀
    RK3576平臺Android <b class='flag-5'>HAL</b>層故障排查:從lshal命令看透問題本質(zhì)

    小白也能聽懂的單片機知識路徑

    項目的復雜度和性能。 進階知識: RTOS(實時操作系統(tǒng)):學習如何在STM32上移植和運行RTOS,實現(xiàn)多任務并發(fā)處理,提高系統(tǒng)的實時性和可靠性。 硬件抽象層(HAL)與底層驅(qū)動:了解HA
    發(fā)表于 02-04 16:44

    【求助】Proteus 8.17SP5中STM32 HALHAL_GPIO_ReadPin讀不出低電平!

    開發(fā)環(huán)境STM32 CubeIDE v1.12.1,仿真環(huán)境Proteus 8.17SP5。使用STM32F103R6Tx。 配置PB7為Inputmode,內(nèi)部Pull-up。PC5為
    發(fā)表于 01-30 16:45

    《機智云Gokit3開發(fā)篇》4 RGB燈的介紹與驅(qū)動移植(HAL庫)

    的色彩控制能力。本文聚焦Gokit3開發(fā)板(MCU模式,主控STM32F103C8T6),以HAL庫為開發(fā)基礎,從P9813驅(qū)動芯片的工作原理入手,系統(tǒng)講解RGB燈的
    的頭像 發(fā)表于 01-28 19:11 ?5299次閱讀
    《機智云Gokit3開發(fā)篇》4 RGB燈的介紹與驅(qū)動移植(<b class='flag-5'>HAL</b>庫)

    TDK Joystick Evaluation Platform:HAL 3900的全方位解析

    TDK Joystick Evaluation Platform:HAL 3900的全方位解析 在電子設備的設計與開發(fā)中,傳感器的應用至關重要,尤其是在操縱桿等設備中,精確的位置和角度檢測能夠極大
    的頭像 發(fā)表于 12-26 11:35 ?610次閱讀

    立即在GitHub上搶先體驗面向STM32U5的最新STM32Cube HAL更新

    其滿足您的需求。 如何獲取預覽版本 面向STM32U5系列的STM32Cube HAL2預覽版已在GitHub代碼庫STM32CubeU5-V2-Preview中開放。 更新后的
    的頭像 發(fā)表于 10-20 17:12 ?1232次閱讀

    全網(wǎng)最全CSA3412,BCT4340,VL162,MCU/ USB3.1 正反插10G bps四種解決方案

    CSA3412,BCT4340,VL162,MCU/ USB3.1 全網(wǎng)最全正反插10G bps四種解決方案
    的頭像 發(fā)表于 09-25 03:06 ?938次閱讀
    <b class='flag-5'>全網(wǎng)</b><b class='flag-5'>最全</b>CSA3412,BCT4340,VL162,MCU/ USB3.1 正反插10G bps四種解決方案

    rt-thread stm32 BSP編譯不通過,缺乏HAL庫怎么處理?

    拉取gitee上關于rt-thread master分支的代碼進行BSP/stm32f407部分編譯時,使用env編譯不通過,提示缺乏Libraries下的HAL,這部分我看是缺乏的,然后分支v5.1.0是有的,
    發(fā)表于 09-15 07:35

    制作STM32F1開發(fā)板的BSP失敗的原因?

    \\bsp\\stm32\\stm32f10x_template,然后通過Keil5打開工程并編譯,出現(xiàn)如下錯誤: compiling stm32f1xx_hal_nor.c... \"
    發(fā)表于 08-29 07:42

    STM32H7使用HAL庫如何控制外置USB HS PHY進入低功耗?

    項目使用STM32H7的HAL庫控制外置USB HS PHY(如USB3300或CH132)的。不知如何讓MCU通過ULPI接口寫寄存器讓USB HS PHY進入低功耗,且USB保持鏈接狀態(tài)讓PC可以重新喚醒。
    發(fā)表于 08-14 07:21

    詳解hal_entry入口函數(shù)

    當使用RTOS時,程序從main函數(shù)開始進行線程調(diào)度;當沒有使用RTOS時,C語言程序的入口函數(shù)main函數(shù)調(diào)用了hal_entry函數(shù)。由于我們新建的工程是沒有選用RTOS的,因此,用戶程序從
    的頭像 發(fā)表于 07-25 15:34 ?2210次閱讀

    SPI+DMA一直發(fā)會進入HAL_BUSY無法跳出是怎么回事?

    HAL_SPI_STATE_BUSY_TX_RX狀態(tài),導致HAL_SPI_TransmitReceive_DMA無法正常運行,我不知道是不是哪里設置不對還是其他問題導致的。 這是STM32Cube的中斷設置
    發(fā)表于 07-18 06:38

    基于STM32 HAL庫與標準庫的esp8266接入機智云方案(二)

    在《基于STM32HAL庫與標準庫的esp8266接入機智云方案(一)》中,我們詳細介紹了硬件連接和機智云客戶端的創(chuàng)建。本篇將重點講解如何下載代碼、分析下載的代碼,并直接使用這些代碼連接機智云。同時
    的頭像 發(fā)表于 05-28 18:02 ?1621次閱讀
    基于<b class='flag-5'>STM32</b> <b class='flag-5'>HAL</b>庫與標準庫的esp8266接入機智云方案(二)

    HAL15xy_SOT23

    HAL1501SU-A,HAL1502SU-A,HAL1503SU-A,HAL1504SU-A,HAL1505SU-A,
    發(fā)表于 05-14 15:03 ?0次下載
    雷州市| 贵港市| 久治县| 鸡泽县| 松桃| 蓝田县| 江川县| 神农架林区| 罗田县| 新建县| 阿拉善盟| 宜兰县| 江川县| 确山县| 巴林右旗| 积石山| 兰州市| 南召县| 阿荣旗| 平南县| 塔河县| 威信县| 怀宁县| 临潭县| 泸溪县| 泊头市| 乐昌市| 昌吉市| 新干县| 曲靖市| 开原市| 原阳县| 白朗县| 盖州市| 宜昌市| 玉树县| 达拉特旗| 芦溪县| 雷州市| 合作市| 高清|