日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 嵌入式 > 玩轉嵌入式
[導讀]很久之前就聽說st出了一個新版本的庫,用于代替原來的標準庫,非常好奇,但是一直沒有機會去體驗。這次借著做畢設的機會,嘗試著切換到新庫。官網介紹說,hal是一層硬件的抽象,看到這里,我非常激動,看來st終于意識到原來標準庫的問題了,原來的標準庫非常依賴于具體硬件細節(jié),很難體現(xiàn)出使用庫的優(yōu)勢,而且很難移植。同時我也非常好奇,st到底是如何把不同系列mcu的操作給封裝起來的,是不是足夠抽象,方便移植。

很久之前就聽說st出了一個新版本的庫,用于代替原來的標準庫,非常好奇,但是一直沒有機會去體驗。這次借著做畢設的機會,嘗試著切換到新庫。

官網介紹說,hal(hardware abstract layer)是一層硬件的抽象,看到這里,我非常激動,看來st終于意識到原來標準庫的問題了,原來的標準庫非常依賴于具體硬件細節(jié),很難體現(xiàn)出使用庫的優(yōu)勢,而且很難移植。同時我也非常好奇,st到底是如何把不同系列mcu的操作給封裝起來的,是不是足夠抽象,方便移植。

話不多說,直接上官網下下來再說。

上圖就是hal庫的全部內容,其中STM32F1xx_HAL_Driver中屬于hal庫的內容。

拿到庫第一步需要做的就是配置一個簡單的hello world,我在配置的時候,出現(xiàn)了非常多的問題。最開始非常自信,只從文件夾里挑選自認為有用的文件加入到工程中,結果出現(xiàn)了各種問題,里面各種庫的依賴關系比較復雜,如果不是很熟悉整個架構的話,還是老老實實拷貝整個文件夾吧。

配置之前,首先要了解一下整個庫的框架,官方給的框架圖如下:

個人認為這幅圖和我理解的有些許出入,故重新畫了一張:

有幾點區(qū)別:

  • cmsis我放在了驅動層的最底層,因為cmsis庫中包含的內容都是和具體cpu內核相關的東西,還有一些地址定義,這些都是非常底層的東西了,而且hal層確實是依賴于cmsis。

  • hal底層我增加了一層msp,類似于bsp,全稱是mcu support package,這一層相當于hal的驅動層,與硬件相關的部分比如最終的時鐘配置,gpio配置等等提取出來,交給用戶配置。

了解了架構,下面我們就來配置一個簡單的工程吧。

  1. 首先拷貝整個Driver目錄到工程中。

  2. 新建user文件夾,新建main.c文件。
    找到stm32f1xx_hal_conf_template.h,stm32f1xx_hal_msp_template.c,去掉"_template"放入user文件夾。
    找到stm32f1xx_it.c和stm32f1xx_it.h放入user文件夾。

  3. 新建工程
    添加源文件:

配置工程:

  • 勾選Use MicroLib,因為hal使用了c標準庫。

  • 添加全局宏定義:USE_HAL_DRIVER,STM32F103xB。關于芯片選擇,有如下表格:

  • 勾選c99支持,因為hal采用的是c99標準編寫,不勾選的話,會出現(xiàn)類似于uint32_t等類型不存在的編譯錯誤。

  • 添加包含目錄,如下圖:

4.編寫代碼:

配置stm32f1xx_hal_conf.h:
這里面有許多用于配置的宏,比如用于精準延時的晶振頻率,還有各個外設模塊的開關等等。

main.c

		

#include "stm32f1xx_hal.h"int main() { ? ?HAL_Init(); __HAL_RCC_GPIOC_CLK_ENABLE(); GPIO_InitTypeDef gpio_initstruct; gpio_initstruct.Mode=GPIO_MODE_OUTPUT_PP; gpio_initstruct.Speed=GPIO_SPEED_FREQ_HIGH; gpio_initstruct.Pull=GPIO_NOPULL; gpio_initstruct.Pin=GPIO_PIN_13; HAL_GPIO_Init(GPIOC,&gpio_initstruct); while(1) ? ?{ ? ? ? ?HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,0); HAL_Delay(150); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,1); HAL_Delay(150); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,0); HAL_Delay(150); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,1); HAL_Delay(1000); } ? ?return 0;}

stm32f1xx_hal_msp.c

			

#include "stm32f1xx_hal.h"void SystemClock_Config(void);void HAL_MspInit(void){ ? ?SystemClock_Config(); }void SystemClock_Config(void){ ?RCC_ClkInitTypeDef clkinitstruct = {0}; ?RCC_OscInitTypeDef oscinitstruct = {0}; /* Configure PLL ------------------------------------------------------*/ /* PLL configuration: PLLCLK = (HSI / 2) * PLLMUL = (8 / 2) * 16 = 64 MHz */ /* PREDIV1 configuration: PREDIV1CLK = PLLCLK / HSEPredivValue = 64 / 1 = 64 MHz */ /* Enable HSI and activate PLL with HSi_DIV2 as source */ oscinitstruct.OscillatorType ?= RCC_OSCILLATORTYPE_HSE;//RCC_OSCILLATORTYPE_HSI; oscinitstruct.HSEState ? ? ? ?= RCC_HSE_ON;//RCC_HSE_OFF; oscinitstruct.LSEState ? ? ? ?= RCC_LSE_OFF; ?oscinitstruct.HSIState ? ? ? ?= RCC_HSI_OFF;//RCC_HSI_ON; oscinitstruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; ?oscinitstruct.HSEPredivValue ? ?= RCC_HSE_PREDIV_DIV1; ?oscinitstruct.PLL.PLLState ? ?= RCC_PLL_ON; ?oscinitstruct.PLL.PLLSource ? = RCC_PLLSOURCE_HSE;//RCC_PLLSOURCE_HSI_DIV2; oscinitstruct.PLL.PLLMUL ? ? ?= RCC_PLL_MUL9;//RCC_PLL_MUL16; if (HAL_RCC_OscConfig(&oscinitstruct)!= HAL_OK) ?{ /* Initialization Error */ while(1); ?} /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 ? ? clocks dividers */ clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); ?clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; ?clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1; ?clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1; ?clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2)!= HAL_OK) ?{ /* Initialization Error */ while(1); ?} }

整個編程步驟就是,hal庫初始化->開外設時鐘->外設初始化->用戶程序,然后在msp.c文件里實現(xiàn)其他平臺相關的雜七雜八的操作,需要調用的時候會自動調用,我這里只實現(xiàn)了一個點亮led的功能,故只實現(xiàn)了HAL_MspInit()函數。如果我們要使用uart、adc等其他更復雜的外設,我們需要在msp.c文件里重寫HAL_UART_MspInit()、HAL_ADC_MspInit()等函數,當我們調用HAL_PPP_Init()時,他們都會自動被調用。

說到這里,我要說一下這里其實使用了一個c語言的技巧,實現(xiàn)了類似于c++的重載功能。比如我們來看UART的源文件:

			

/** ?* @brief ?USART MSP Init. ?* @param ?husart: Pointer to a USART_HandleTypeDef structure that contains ?* ? ? ? ? ? ? ? ? the configuration information for the specified USART module. ?* @retval None ?*/ __weak void HAL_USART_MspInit(USART_HandleTypeDef *husart){ /* Prevent unused argument(s) compilation warning */ UNUSED(husart); /* NOTE: This function should not be modified, when the callback is needed, ? ? ? ? ? the HAL_USART_MspInit can be implemented in the user file ? */ }

函數被__weak修飾了,意思就是,如果別處沒定義,這個函數就是他,如果別處重定義了,就用新的函數,這樣就實現(xiàn)了重載。這有一個很大的好處,就是實現(xiàn)思想中的差異化編程,hal實現(xiàn)所有硬件通用的功能,而把不通用的部分通過可重載的函數開放給用戶修改。

每個函數中,都會接收到一個handle指針,這其實和this指針非常類似,每個函數都不用知道自己到底是在操作某一個具體的對象,只需要根據handle的指向來操作就可以了。

回到上面的重載。在hal庫中有一點比較大的改變是,中斷都是通過回調函數來開放給用戶的,具體使用方式也是重載相關回調函數,不像標準庫是直接在stm32fxxx_it.c里填寫相關中斷處理函數。這樣做的好處是,hal幫我們處理了一些中斷來臨時的雜務,只把我們感興趣的事件開放給用戶。

但是個人覺得這個改變需要再徹底一點,因為這并沒有解決代碼耦合性的痛點,每一次我們需要寫中斷函數的時候,總是要去改底層代碼,而如果st給我們實現(xiàn)一個注冊回調的接口,那么上層和下層之前就完全分離了,應用層各個模塊之間也不會產生耦合。

總結:
總體而言,hal相比于標準庫,層次架構更加清晰了,對平臺更加抽象,但是還遠遠不夠,依然非常依賴于具體的硬件,如果能實現(xiàn)Qt的那種抽象就完美了。用戶使用的時候,只用包含hal.h而不用去管是hal_f1還是hal_f2或是什么其他系列的頭文件,所有系列的代碼打包在一起,通過條件編譯來實現(xiàn)真正的跨平臺,而如果需要使用某款mcu的特色功能時,就再包含一個hal_f1extend.h。如果這些st都實現(xiàn)了,那么單片機編程將會變得和應用編程一樣簡單方便!

文章來源于“簡書”,作者:logic_wei

文章出處:http://www.jianshu.com/p/c6809c2bcb4f

關注微信公眾號『玩轉嵌入式』,后臺回復“128”獲取干貨資料匯總,回復“256”加入技術交流群。

精彩技術文章推薦


01

單片機的Bootloader,可以實現(xiàn)用戶輕松升級程序


02

模塊化編程,是團隊協(xié)作編程的前提


03

PWM是什么,有哪些用處?


04

零基礎如何學習單片機,一位入門者的進階路徑,可參考



免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據LED驅動電源的公式,電感內電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉