在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

3天內不再提示

STM32的HAL庫知識總結

STM32嵌入式開發 ? 來源:STM32嵌入式開發 ? 2023-01-14 11:37 ? 次閱讀

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

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

通過文字描述可以知道HAL庫的幾個點:

1.最大可移植性。

2.提供了一整套一致的中間件組件,如RTOSUSB,TCP / IP和圖形等。

3.通用的用戶友好的API函數接口。

4.ST新出的芯片已經沒有標準庫。

5.HAL庫已經支持STM32全線產品。

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

通常新手在入門STM32的時候,首先都要先選擇一種要用的開發方式,不同的開發方式會導致你編程的架構是完全不一樣的。一般大多數都會選用標準庫和HAL庫,而極少部分人會通過直接配置寄存器進行開發。網上關于標準庫、HAL庫的描述相信是數不勝數。可是一個對于很多剛入門的朋友還是沒法很直觀的去真正了解這些不同開發方式彼此之間的區別,所以筆者想以一種非常直白的方式,用自己的理解去將這些東西表述出來,如果有描述的不對的地方或者是不同意見的也可以大家提出。

01、直接配置寄存器

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

02、標準庫

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

03、HAL庫

HAL庫是ST公司目前主力推的開發方式,全稱就是Hardware Abstraction Layer(抽象印象層)。 庫如其名,很抽象,一眼看上去不太容易知道他的作用是什么。 它的出現比標準庫要晚,但其實和標準庫一樣,都是為了節省程序開發的時期,而且HAL庫尤其的有效,如果說標準庫把實現功能需要配置的寄存器集成了,那么HAL庫的一些函數甚至可以做到某些特定功能的集成。 也就是說,同樣的功能,標準庫可能要用幾句話,HAL庫只需用一句話就夠了。 相關文章:STM32CubeMX教程-GPIO。 并且HAL庫也很好的解決了程序移植的問題,不同型號的stm32芯片它的標準庫是不一樣的,例如在F4上開發的程序移植到F3上是不能通用的,而使用HAL庫,只要使用的是相通的外設,程序基本可以完全復制粘貼,注意是相通外設,意思也就是不能無中生有,例如F7比F3要多幾個定時器,不能明明沒有這個定時器卻非要配置,但其實這種情況不多, 絕大多數都可以直接復制粘貼。 是而且使用ST公司研發的STMcube軟件,可以通過圖形化的配置功能,直接生成整個使用HAL庫的工程文件,可以說是方便至極,但是方便的同時也造成了它執行效率的低下,在各種論壇帖子真的是被吐槽的數不勝數。

HAL庫和標準固件庫區別

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

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

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

比如上面的控制 BRR 寄存器實現電平控制,官方庫封裝了一個函數:

poYBAGPCI4yADugSAAAJwSYyJQ0701.png

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

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

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

pYYBAGPCI4yAcKQ6AAAbE0epRso215.png

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

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

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

在ST的官方聲明中,HAL庫是大勢所趨。 ST最新開發的芯片中,只有HAL庫沒有標準庫。 標準庫和HAL庫雖然都是對外設進行操作的函數,但由于標準庫官方已經停止更新,而且標準庫在STM32創建工程和初始化時,不能由CubMX軟件代碼生成使用,也就是說CubMX軟件在生產代碼時,工程項目和初始化代碼就自動生成,這個工程項目和初始化代碼里面使用的庫都是基于HAL庫的。 STM32CubeMX是一個圖形化的工具,也是配置和初始化C代碼生成器 ,與STM32CubeMX配合使用的是HAL庫(硬件抽象層軟件庫)。

基本配置

工程創建

通過內核芯片的選擇,創建相應的工程文件。

poYBAGPCI4yAXHV_AAOLC_b6CAk404.png

poYBAGPCI4yAS3tmAARqE6DATKo114.png

對時鐘系統進行配置,對引腳及基本功能進行配置。

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

poYBAGPCI4yAKT2xAAJ0hrDw5T8537.png

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

poYBAGPCI4yAIIe3AAKq3Y1YtVY351.png

工程管理設置推薦圖中所示配置,實現更快編譯和更簡潔的文件系統。

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

poYBAGPCI4yAM4IpAAJCp4zjy-U374.png

pYYBAGPCI4yAc3ILAAJXBs1ShMY947.png

如果你已經安裝了編譯環境MDK了,可點擊直接打開工程。

GPIO使用

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

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

pYYBAGPCI4uAEdQyAADMLdZnthM228.jpg

pYYBAGPCI4yAPN_YAABxCxvOb_M943.jpg

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

poYBAGPCI4uAL-5tAABRWSBO_J4304.png

pYYBAGPCI4yAN2AVAAA1bcgufIg750.png

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

pYYBAGPCI4yAPEocAACk-QfDXro792.png

點擊Clock Configuration配置系統時鐘為72M最高速度。

poYBAGPCI4yAOZRNAABhS9iygoI522.jpg

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

poYBAGPCI4yAEDXdAABTuotA76E648.jpg

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

poYBAGPCI4yAKnhrAACc43JQ-zY625.jpg

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

poYBAGPCI4uAJrt9AACazpSd83o487.jpg

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

poYBAGPCI4uAS3CuAAB92ltqkzg475.png

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

在main函數里添加如下代碼

pYYBAGPCI4yAU6b9AAB_HjZ6lRI623.jpg

延時電平翻轉函數,這樣LED燈就能開始閃爍。

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

代碼燒寫。

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

poYBAGPCI4yAbRWUAAAEEf48_bI808.png,軟件可自行網上搜索,下載配置如下。

pYYBAGPCI4uALx5tAACG4QNXv0k755.jpg

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

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

1.首先設置讓Cube可以自動聯網下載相關固件庫選擇updater Settings

pYYBAGPCI4yADnTyAADqwIMHvZA947.png

設置如下

poYBAGPCI4yATChfAACZri8O9n4213.png

2.根據芯片選擇所需固件

版本是向下兼容的,可以直接選擇最新版。 但如果覺得最新版太大,可以閱讀下面的Main Changes.能夠支持你目前的芯片就好。

pYYBAGPCI4yAAe2jAAEbBa4WQbg557.png

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

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

poYBAGPCI4yAeHa4AACvLq3dnFs255.png

查找幫助手冊

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

poYBAGPCI4yACYhPAAEyBRvGoNI350.png

比如說 官方提供的開發板程序

poYBAGPCI4yACYhPAAEyBRvGoNI350.png

每個型號下面都有對應功能的實現

poYBAGPCI4yAOQsuAAE0OR9gxTA791.png

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

pYYBAGPCI4yAQpUDAADlNsfWsmk792.png

STM32 HAL庫與標準庫的區別

——淺談句柄、MSP函數、Callback函數

01句柄

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

· 第一種解釋:句柄是一種特殊的智能指針。 當一個應用程序要引用其他系統(如數據庫、操作系統)所管理的內存塊或對象時,就要使用句柄。

· 第二種解釋:整個Windows編程的基礎。 一個句柄是指使用的一個唯一的整數值,即一個4字節(64位程序中為8字節)長的數值,來標識應用程序中的不同對象和同類中的不同的實例,諸如,一個窗口,按鈕,圖標,滾動條,輸出設備,控件或者文件等。 應用程序能夠通過句柄訪問相應的對象的信息,但是句柄不是指針,程序不能利用句柄來直接閱讀文件中的信息。 如果句柄不在I/O文件中,它是毫無用處的。 句柄是Windows用來標志應用程序中建立的或是使用的唯一整數,Windows大量使用了句柄來標識對象。

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

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

pYYBAGPCI4uAW-okAAAi6bqMe8c753.png

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

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

· 2、然后引用Init函數,

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

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

pYYBAGPCI4yAA4JEAAAEWIztbW4429.png

右鍵查看結構體成員

poYBAGPCI4yAMKjyAAQcRMQshEY991.png

我們發現,與標準庫不同的是,該成員不僅:

· 1、包含了之前標準庫就有的六個成員(波特率,數據格式等),

· 2、還包含過采樣、(發送或接收的)數據緩存、數據指針、串口 DMA 相關的變量、各種標志位等等要在整個項目流程中都要設置的各個成員。該UART1_Handler就被稱為串口的句柄,它被貫穿整個USART收發的流程,比如開啟中斷:

pYYBAGPCI4yAVj86AAAHKOIxhmI470.png

比如后面要講到的MSP與Callback回調函數:

poYBAGPCI4uAXBa0AAAKjTQ26SY983.png

在這些函數中,只需要調用初始化時定義的句柄UART1_Handler就好。

02MSP函數

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

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

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

在 STM32 的 HAL 驅動中HAL_PPP_MspInit()作為回調,HAL_PPP_Init()函數所調用。 當我們需要移植程序到 STM32F1平臺的時候,我們只需要修改 HAL_PPP_MspInit 函數內容而不需要修改 HAL_PPP_Init 入口參數內容。

在HAL庫中,幾乎每初始化一個外設就需要設置該外設與單片機之間的聯系,比如IO口,是否復用等等,可見,HAL庫相對于標準庫多了MSP函數之后,移植性非常強,但與此同時卻增加了代碼量和代碼的嵌套層級。 可以說各有利弊。

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

pYYBAGPCI4yACC1_AAAG_6TzF-g246.png

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

03Callback函數

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

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

pYYBAGPCI4yAGSa7AAAZqZmFdKA299.png

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

poYBAGPCI4uASvfoAAAMRbYZ1dY102.png

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

pYYBAGPCI4yAKCYpAAAP0oopJuY422.png

在初始化中,我在句柄里設置好了緩存區的地址,緩存大小(五個字節)

pYYBAGPCI4uANdVAAAAP9a-MCVo026.png

則在接收數據中,每接收完五個字節,HAL_UART_IRQHandler才會執行一次Callback函數:

pYYBAGPCI4yAD4LHAAAF6xjoD8U176.png

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

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

04STM32 HAL庫結構

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

pYYBAGPCI4yAA7bbAAK3TJJaNK4609.png

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

poYBAGPCI4yACCpoAAAVT-Duy0s447.png

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

· 4.2stm32f4xx_hal.h:stm32f4xx_hal.c/h 主要實現HAL庫的初始化、系統滴答相關函數、及CPU的調試模式配置

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

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

· 4.4庫文件

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

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

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

· 4.5其他庫文件

用戶級別文件:

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

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

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

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

·4.6main.c/.h//

根據HAL庫的命名規則,其API可以分為以下三大類:

·初始化/反初始化函數:HAL_PPP_Init(), HAL_PPP_DeInit()

·IO 操作函數:HAL_PPP_Read(), HAL_PPP_Write(),HAL_PPP_Transmit(), HAL_PPP_Receive()

·控制函數:HAL_PPP_Set (), HAL_PPP_Get ().

·狀態和錯誤: ** HAL_PPP_GetState (), HAL_PPP_GetError ().

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

使用CubeMX生產項目時,可以選擇LL庫?

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

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

·處理MSP

·處理各種回調函數

相關知識如下:

·(1) 外設句柄定義??

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

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

外圍進程相互通信:該句柄用于管理進程例程之間的共享數據資源。 下面,以ADC為例

pYYBAGPCI4uAY8ezAAAm8KAZch0642.png

從上面的定義可以看出,ADC_HandleTypeDef中包含了ADC可能出現的所有定義,對于用戶想要使用ADC只要定義一個ADC_HandleTypeDef的變量,給每個變量賦好值,對應的外設就抽象完了。 接下來就是具體使用了。??

當然,對于那些共享型外設或者說系統外設來說,他們不需要進行以上這樣的抽象,這些部分與原來的標準外設庫函數基本一樣。 例如以下外設:

- GPIO?

- 漩渦鳴??

- 國家維克??

-碾 壓 混凝土??

-閃光

以GPIO為例,對于HAL_GPIO_Init() 函數,其只需要GPIO 地址以及其初始化參數即可。

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

pYYBAGPCI4yAWXveAAAX9FEOH_A686.png

其中,帶_IT的表示工作在中斷模式下; 帶_DMA的工作在DMA模式下(注意:DMA模式下也是開中斷的);什么都沒帶的就是輪詢模式(沒有開啟中斷的)。 至于使用者使用何種方式,就看自己的選擇了。??此外,新的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_GETIT_SOURCE (HANDLE, __ INTERRUPT __):檢查中斷源

·(3)三大回調函數??在HAL庫的源碼中,到處可見一些以__weak開頭的函數,而且這些函數,有些已經被實現了,比如:

poYBAGPCI4yAdGZxAAAY1wVRvLc540.png

有些則沒有被實現,例如:

pYYBAGPCI4yAV2pEAAAWg2EbWPc699.png

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

外設系統級初始化/解除初始化回調函數(用戶代碼的第二大部分:對于MSP的處理):

HAL_PPP_MspInit()和 HAL_PPP_MspDeInit** 例如:__weak void

HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)。 在HAL_PPP_Init() 函數中被調用,用來初始化底層相關的設備(GPIOs, clock, DMA, interrupt)

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

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

絕大多數用戶代碼均在以上三大回調函數中實現。

HAL庫結構中,在每次初始化前(尤其是在多次調用初始化前),先調用對應的反初始化(DeInit)函數是非常有必要的。

某些外設多次初始化時不調用返回會導致初始化失敗。 完成回調函數有多種,例如串口的完成回調函數有HAL_UART_TxCpltCallback 和 HAL_UART_TxHalfCpltCallback等(用戶代碼的第三大部分:對于上面第二點和第三點的各種回調函數的處理)在實際使用中,發現HAL仍有不少問題,例如在使用USB時,其庫配置存在問題

05HAL庫移植使用

基本步驟

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

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

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

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

5.關于中斷,HAL提供了中斷處理函數,只需要調用HAL提供的中斷處理函數。 用戶自己的代碼,不建議先寫到中斷中,而應該寫到HAL提供的回調函數中。

6.對于每一個外設,HAL都提供了回調函數,回調函數用來實現用戶自己的代碼。 整個調用結構由HAL庫自己完成。 例如:Uart中,HAL提供了void HAL_UART_IRQHandler(UART_HandleTypeDef *huart); 函數,用戶只需要觸發中斷后,用戶只需要調用該函數即可,同時,自己的代碼寫在對應的回調函數中即可! 如下:

poYBAGPCI4yAMbiEAAASzFAXL4Y394.png

使用了哪種就用哪個回調函數即可!

基本結構?

綜上所述,使用HAL庫編寫程序(針對某個外設)的基本結構(以串口為例)如下:

1.配置外設句柄例如,建立UartConfig.c,在其中定義串口句柄 UART_HandleTypeDef huart; ,接著使用初始化句柄(HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDefhuart))

2.編寫Msp例如,建立UartMsp.c,在其中實現void HAL_UART_MspInit(UART_HandleTypeDef huart) 和 void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)

3.實現對應的回調函數例如,建立UartCallBack.c,在其中實現上文所說明的三大回調函數中的完成回調函數和錯誤回調函數

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • mcu
    mcu
    +關注

    關注

    146

    文章

    17185

    瀏覽量

    351708
  • 寄存器
    +關注

    關注

    31

    文章

    5357

    瀏覽量

    120685
  • STM32
    +關注

    關注

    2270

    文章

    10910

    瀏覽量

    356605
  • 標準庫
    +關注

    關注

    0

    文章

    31

    瀏覽量

    7495
  • HAL庫
    +關注

    關注

    1

    文章

    121

    瀏覽量

    6327

原文標題:長文 | STM32的HAL庫知識總結

文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    STM32四種對比 STM32標準HAL有什么不同?

    STM32的四種STM32Snippets、Standard Peripheral Library、STM32Cube LL、STM32
    發表于 08-24 09:45 ?1.4w次閱讀
    <b class='flag-5'>STM32</b>四種<b class='flag-5'>庫</b>對比 <b class='flag-5'>STM32</b>標準<b class='flag-5'>庫</b>和<b class='flag-5'>HAL</b><b class='flag-5'>庫</b>有什么不同?

    STM32標準改為HAL的程序實現

    標準占絕大多數,自己買的板子跟的資料也一般是標準HAL很少,不過要是使用STM32CubeMx配置,那么就是使用的
    發表于 11-22 11:23 ?3.5w次閱讀

    STM32HAL與LL能共同使用(混用)嗎?

    STM32HAL和LL能共同使用(混用)嗎?
    的頭像 發表于 02-28 16:57 ?1.5w次閱讀

    全網最全STM32 HAL知識總結

    是ST的老已經停更了,后兩者是ST現在主推的開發。 相比標準外設STM32Cube HAL
    的頭像 發表于 06-28 17:54 ?7172次閱讀

    00_STM32F4學習_HAL_GPIO函數

    00_STM32F4學習_HAL_GPIO函數最近重學STM32,打算從HAL+
    發表于 12-05 14:21 ?12次下載
    00_<b class='flag-5'>STM32</b>F4學習_<b class='flag-5'>HAL</b><b class='flag-5'>庫</b>_GPIO函數

    STM32 CubeMX+HAL基本操作

    STM32 CubeMX+HAL基本操作
    發表于 12-07 11:21 ?50次下載
    <b class='flag-5'>STM32</b> CubeMX+<b class='flag-5'>HAL</b><b class='flag-5'>庫</b>基本操作

    STM32實戰 2 | STM32CubeMX及HAL點亮LED

    STM32實戰 2 | STM32CubeMX及HAL點亮LED
    發表于 12-08 12:36 ?34次下載
    <b class='flag-5'>STM32</b>實戰 2 | <b class='flag-5'>STM32</b>CubeMX及<b class='flag-5'>HAL</b><b class='flag-5'>庫</b>點亮LED

    使用HAL開發STM32:系統時間基礎及進階使用

    目的HAL默認提供了系統時間,基礎使用進階使用總結
    發表于 12-08 14:21 ?1次下載
    使用<b class='flag-5'>HAL</b><b class='flag-5'>庫</b>開發<b class='flag-5'>STM32</b>:系統時間基礎及進階使用

    STM32HAL微秒延時(μs)

    STM32HAL微秒(μs)延時
    發表于 01-18 10:39 ?48次下載
    <b class='flag-5'>STM32HAL</b><b class='flag-5'>庫</b>微秒延時(μs)

    stm32 hal資料分享

    stm32 hal資料分享
    發表于 11-03 16:17 ?120次下載

    STM32 HAL串口收發如何使用

    前言 一、 HAL 串口收發 1.1 串口發送 1.2 串口接收 二、 收發同時串口卡死? 2.1 問題說明 2.2 嘗試的處理方式 結語 前言 對于 STM32 串口的使用,確實很簡單
    的頭像 發表于 06-22 10:38 ?6395次閱讀
    <b class='flag-5'>STM32</b> <b class='flag-5'>HAL</b><b class='flag-5'>庫</b>串口收發如何使用

    STM32 HAL的功能和使用方法 STM32 HAL和標準的區別

    和可維護性,從而節省開發成本和時間。STM32 HALSTM32系列芯片的HAL,由ST公
    發表于 08-08 18:21 ?4558次閱讀

    STM32 HAL串口收發是如何使用的?

    STM32 HAL串口收發是如何使用的? STM32是一款高性能的微控制器,它擁有廣泛的應用領域,其中包括了各種通訊應用,如UART串口通訊。HA
    的頭像 發表于 10-26 17:42 ?1243次閱讀

    STM32 HAL串口同時收發,接收卡死?

    STM32 HAL串口同時收發,接收卡死? 為什么STM32 HAL串口會出現同時收發導致接
    的頭像 發表于 10-26 17:42 ?3530次閱讀

    如何快速入門HAL編程 HAL與裸機編程的比較

    如何快速入門HAL編程 要快速入門HAL編程,可以遵循以下步驟: 了解基礎知識 : 掌握C語言編程基礎,包括變量、數據類型、函數、指針等
    的頭像 發表于 12-02 11:39 ?363次閱讀
    主站蜘蛛池模板: 污污的黄色小说| jiuma和我啪啪| 狂野欧美激情性xxxx| 日不卡在线| 在线观看886影院成人影院| 久久好色| 日本bbxx| 四虎永久免费地址| 成人夜色| 欧美一级第一免费高清| 97影院午夜在线观看视频| 国精视频一区二区视频| 欧美videosex性欧美成人| 三级国产| 四虎影院.com| 四虎在线免费视频| 日本高清中文字幕在线观穿线视频 | 久久成人免费网站| 爱爱免费网址| 国产成人永久免费视频| 激情开心婷婷| 久久国产精品久久久久久 | 婷婷久久综合九色综合九七| 伊人啪| 在线综合网| 在线看片一区| 色播五月激情五月| 国产亚洲美女| aaa一级| 男子扒开美女尿口做羞羞的事| 色极影院| 久久午夜视频| 久久国产午夜精品理论片34页| 欧美乱强性伦xxxxx| 色 ed2k| 亚洲欧美视频一区二区| 一二三区在线视频| 一区三区三区不卡| 天天躁夜夜躁狠狠躁2021a| 亚洲国产成人久久精品图片| 五月婷婷激情综合|