新建工程的方式
- 1. 安裝開發工具 MDK5 / keil5
- 2. CMSIS 標準
- 3. 新建工程
- 3.1 寄存器版工程
- 3.2 標準庫版工程
- 3.3 HAL/LL庫版工程
- 3.4 HAL庫、LL庫、標準庫和寄存器對比
- 3.5 庫開發和寄存器的關系
- 4. STM32CubeMX工具的作用
1. 安裝開發工具 MDK5 / keil5
MDK5
由兩個部分組成:MDK Core 和 Software Packs。其中,Software Packs 可以獨立于工具鏈進行新芯片支持和中間庫的升級。
- MDK Core 分為四個部分:
uVision IDE with Editor(編輯器)
,ARM C/C++ Compiler(編譯器)
,Pack Installer(包安裝器)
,uVision Debugger with Trace(調試跟蹤器)
。Pack Installer 用于下載、安裝、更新和管理 Software Packs。- Software Packs(軟件包) 分為三個部分:
Device(芯片支持)
,CMSIS(微控制器軟件接口標準)
,Mdidleware(中間庫)
。?
特性 MDK5 Keil5 定位 完整的開發套件 集成開發環境(IDE) 包含內容 IDE、編譯器、調試器、中間件、設備支持包 僅包含 IDE 適用場景 ARM Cortex-M 微控制器開發 嵌入式開發(尤其是 ARM Cortex-M) 功能范圍 更廣泛,包含完整的開發工具鏈 專注于代碼編輯、編譯和調試 適用項目規模 開發復雜的嵌入式系統,或者需要使用豐富的中間件 只需要一個 IDE 來編寫和調試代碼,或者項目規模較小
2. CMSIS 標準
因為基于 Cortex 系列芯片采用的內核都是相同的,區別主要為核外的片上外設的差異,這些差異卻導致軟件在同內核,不同外設的芯片上移植困難。為了解決不同的芯片廠商生產的 Cortex 微控制器軟件的兼容性問題,ARM 與芯片廠商建立了
CMSIS 標準
(微控制器軟件接口標準)。所有芯片廠家的官方庫
(包括ST官方庫)都是根據這套標準設計的。
??從圖中可以看出,CMSIS 層在整個系統中是處于中間層,向下負責與內核和各個外設直接打交道,向上提供實時操作系統用戶程序調用的函數接口。如果沒有 CMSIS 標準,那么各個芯片公司就會設計自己喜歡的風格的庫函數,而 CMSIS 標準就是要強制規定,芯片生產公司設計的庫函數必須按照 CMSIS 這套規范來設計。
??其實不用講這么復雜的,舉一個簡單的例子,我們在使用 STM32 芯片的時候首先要進行系統初始化,CMSIS 規范就規定,系統初始化函數名字必須為 SystemInit,所以各個芯片公司寫自己的庫函數的時候就必須用 SystemInit 對系統進行初始化。CMSIS 還對各個外設驅動文件的文件名字規范化,以及函數名字規范化等等一系列規定。例如函數
GPIO_ResetBits
這個函數名字也是不能隨便定義的,是要遵循 CMSIS 規范的。?
CMSIS 分為 3 個基本功能層:
- 核內外設訪問層:用于訪問內核寄存器的名稱、地址定義以及功能函數,
ARM 公司提供
。- 中間件訪問層:用于訪問中間件的通用 API,
ARM 公司提供
。- 外設訪問層:提供片上的核外外設的地址和中斷定義以及外設的訪問函數,
芯片生產商提供
。
3. 新建工程
3.1 寄存器版工程
必備文件 描述 位置 stm32f4xx.h 標準外設庫頭文件,包含寄存器定義、外設地址映射、位域定義等內容。ST官方提供 STM32Cube_FW_F4_V1.26.0\Drivers\
CMSIS\Device\ST\STM32F4xx\Include
startup_stm32f407xx.s 匯編語言啟動文件,主要進行初始化堆棧,定義中斷向量表以及跳轉到主程序main()。ST官方提供 STM32Cube_FW_F4_V1.26.0\Drivers\
CMSIS\Device\ST\STM32F4xx\Source\
Templates\arm
3.2 標準庫版工程
??標準外設庫 是對 STM32 芯片的一個完整的封裝,包括所有標準器件外設的器件驅動器,是 ST 最早推出的針對 STM 系列主控的庫函數。標準外設庫仍然接近于寄存器操作,主要就是將一些基本的寄存器操作封裝成了 C 函數。開發者仍需要關注所使用的外設是在哪個總線之上,具體寄存器的配置等底層信息。
??ST 為各系列提供的標準外設庫稍微有些區別。例如,STM32F1x 的庫和 STM32F4x 的庫在文件結構上就有些不同,此外,在內部的實現上也稍微有些區別,這個在具體使用(移植)時,需要注意一下!但是,不同系列之間的差別并不是很大,而且在設計上是相同的。
??STM32 的標準外設庫涵蓋以下 3 個抽象級別:
- 包含位,位域和寄存器在內的完整的
寄存器地址映射
- 涵蓋所有外圍功能(具有公共 API 的驅動器)的例程和數據結構的集合。
- 一組包含所有可用外設的示例,其中包含最常用的開發工具的模板項目。
?
?
上圖黃色部分為新建工程所必須的內容,接下來介紹這些文件的作用
文件名 作用 類別 是否必須 stm32f4xx_conf.h 1.
用戶配置文件,啟用或禁用外設驅動: 通過條件編譯控制是否包含特定外設的頭文件用戶層 是 stm32f4xx_it.c
stm32f4xx_it.h1.
用戶定義和處理與內核
及外設
相關的中斷事件,不一定放到這個文件,可刪除用戶層 否 stm32f4xx.h 1.
定義所有外設寄存器及其位于 (寄存器定義)
2.
使用結構體組織相關寄存器 (外設結構體)
3.
定義外設寄存器的基地址和偏移量 (地址映射)
4.
定義中斷向量號和中斷處理 (中斷定義)
5.
定義一些常用宏,用于位操作、寄存器配置等 (常用宏)
6.
定義標準數據類型,如uinit32_t
(類型定義)
7.
包含外設的配置選項和默認設置 (外設配置)CMSIS
核心層是 system_stm32f4xx.c
system_stm32f4xx.h1.
實現SystemInit()
函數,負責在系統啟動時初始化關鍵硬件模塊 (系統初始化)
2.
實現SystemCoreClockUpdate()
函數,用于更新全局變量SystemCoreClock
的值 (系統時鐘更新)
3.
定義全局變量SystemCoreClock
,用于存儲系統核心時鐘頻率 (全局變量定義)
4.
定義默認的時鐘配置,確保系統以正確的頻率運行 (默認時鐘配置)
5.
在啟動文件中,SystemInit()
函數會在 main() 函數執行之前被調用,確保系統在進入用戶代碼之前完成初始化 (與啟動文件配合)CMSIS
核心層是 startup_stm32f40xx.s 1.
定義中斷向量表
2.
初始化堆棧指針
3.
在復位后初始化 .data 和 .bss 段
4.
調用系統初始化函數SystemInit()
5.
跳轉到用戶的主程序main()
6.
提供默認的中斷處理函數CMSIS
核心層是 core_cm4.h 1.
定義內核的寄存器結構體和地址映射,包括NVIC、SCB、SysTick、MPU、FPU
(定義內核寄存器)
2.
提供一系列內聯函數,用于方便地訪問內核的功能 (提供內聯函數)
3.
定義特殊功能寄存器(如xPSR、CONTROL、PRIMASK 等
),用于控制處理器的運行狀態 (定義特殊功能寄存器)
4.
定義FPU
相關的寄存器和函數,用于配置和控制 FPU (支持 FPU)
5.
提供 CMSIS 標準接口
6.
與標準外設庫stm32f4xx.h
配合使用,提供對內核功能的訪問 (與標準外設庫配合)CMSIS
核心層是 core_cmFunc.h 1.
提供內聯函數訪問內核的特殊功能寄存器(如xPSR、CONTROL、PRIMASK 等
)
2.
支持特權和非特權模式的切換
3.
提供中斷控制函數(如全局中斷的使能和禁用)
4.
支持浮點單元(FPU)操作(如果可用)CMSIS
核心層是 core_cmInstr.h 1.
定義內聯函數,用于封裝內核的匯編指令(如WFI、WFE、SEV、NOP 等
)
2.
提供同步指令(如ISB、DSB、DMB
)
3.
支持低功耗模式指令(如WFI 和 WFE
)CMSIS
核心層是 core_cmSimd.h 1.
定義 SIMD 指令的訪問函數
2.
提供對 DSP 擴展指令的支持CMSIS
核心層是 stm32f4xx_ppp.c
stm32f4xx_ppp.h1.
提供操作外設的 API 函數
2.
定義外設的寄存器結構體、函數聲明和宏定義設備
驅動層是 ?
標準外設庫各文件間的關系:
3.3 HAL/LL庫版工程
??
LL 庫
(Low Layer)目前與 HAL 庫捆綁發布,它設計為比 HAL 庫更接近于硬件底層的操作,代碼更輕量級,代碼執行效率更高的庫函數組件,可以完全獨立于 HAL 庫來使用,但 LL庫不匹配復雜的外設,如 USB 等。所以 LL 庫并不是每個外設都有對應的完整驅動配置程序。使用 LL 庫需要對芯片的功能有一定的認知和了解,它可以:
- 獨立使用,該庫完全獨立實現,可以完全拋開 HAL 庫,只用 LL 庫編程完成。
- 混合使用,和 HAL 庫結合使用。
??HAL 庫和 LL 庫設計為彼此獨立的分支,但又同屬于 HAL 庫體系。標準庫和 HAL 庫、LL 庫完全相互獨立,HAL 庫更傾向于外設通用化,擴展組件中解決芯片差異操作部分;LL傾向于最簡單的寄存器操作,ST 在未來還將重點維護和建設 HAL 庫,標準庫已經部分停止更新。HAL 庫和 LL 庫的應用將是未來的一個趨勢。
??
HAL
即硬件抽象層。HAL 庫是 ST 公司提供的外設驅動代碼的驅動庫,用戶只需要調用庫的 API 函數,便可間接配置寄存器。我們要寫程序控制 STM32 芯片,其實最終就是控制它的寄存器,使之工作在我們需要得模式下,HAL 庫將大部分寄存器的操作封裝成了函數,我們只需要學習和掌握 HAL 庫函數的結構和用法,就能方便地驅動 STM32 工作,以節省開發時間。??HAL 庫開發,指的是利用 HAL 庫里面封裝好的 C 語言編寫的驅動文件,來實現對 STM32 內部和外部電器元件的控制過程。但只有 HAL 庫還不能直接驅動一個 STM32 的芯片,其他的組件已經由 ARM 與眾多芯片硬件、軟件廠商指定的通用的軟件開發標準 CMSIS 實現了。
??STM32Cube 是 ST 提供的一套性能強大的免費開發工具和嵌入式軟件模塊,它包含兩個關鍵部分:
- 允許用戶通過圖形配置工具
STM32CubeMX
來生成 C 語言工程。可以通過 STM32CubeMX 實現方便地下載各種軟件或開發固件包。- 嵌入式軟件包
(STM32Cube 庫)
包含完整的 HAL 庫(硬件抽象層 API),配套的中間件(包括 RTOS、USB、FAT文件系統、圖形、TCP/IP 、以太網),以及一系列完整的例程。
?
上圖黃色部分為新建工程所必須的內容,接下來介紹這些文件的作用
文件名 作用 類別 是否
必須stm32f4xx_it.c
stm32f4xx_it.h同 標準外設庫
一樣用戶層 否 stm32f4xx_hal_conf.h 同 標準外設庫
中 stm32f4xx_conf.h 作用一樣用戶層 是 stm32f4xx_hal_msp.c 回調函數存放文件,已刪除 用戶層 否 stm32f407xx.h 同 標準外設庫
中 stm32f4xx.h 作用一樣CMSIS
核心層是 system_stm32f4xx.c
system_stm32f4xx.h同 標準外設庫
一樣CMSIS
核心層是 startup_stm32f407xx.s 同 標準外設庫
一樣CMSIS
核心層是 stm32f4xx.h 是所有 STM32F4 系列的頂層頭文件,并且可以選擇性包含某一特定的
STM32F4 系列芯片的頭文件(比如包含:F407頭文件 stm32f407xx.h)CMSIS
核心層是 core_cm4.h 同 標準外設庫
一樣CMSIS
核心層是 cmsis_armcc.h
cmsis_armclang.h
cmsis_compiler.h
cmsis_version.h
mpu_armv7.h內核頭文件,一般都不需要去了解 CMSIS
核心層是 sm32f4xx_hal.c
stm32f4xx_hal.hHAL 庫的初始化、系統滴答,HAL 庫延時函數等功能 設備
驅動層是 stm32f4xx_hal_def.h 通用 HAL 庫資源定義 設備
驅動層是 stm32f4xx_hal_ppp.c
stm32f4xx_hal_ppp.h外設的操作 API 函數文件 設備
驅動層是 stm32f4xx_hal_ppp_ex.c
stm32f4xx_hal_ppp_ex.h拓展外設特性的 API 函數文件 設備
驅動層是 stm32f4xx_II_ppp.c
stm32f4xx_II_ppp.hLL 庫文件
,在一些復雜外設中實現底層功能設備
驅動層是 ?
HAL庫各文件間的關系:
3.4 HAL庫、LL庫、標準庫和寄存器對比
HAL庫 標準庫 LL庫 寄存器 使用頻率 最高 逐漸減少 逐漸增加 較低 優點 開發效率高 代碼簡潔,代碼效率較高 代碼效率高,高于標準庫 代碼效率最高 缺點 代碼體積大,執行效率低 已停止維護 開發效率略低于HAL庫 開發難度大,可移植性差 使用場景 快速開發、跨平臺移植 老項目、簡單應用 性能與開發效率平衡的場景 高性能需求、底層開發 開發效率 最高 較高 中等 最低 代碼性能 較低 中等 較高 最高
3.5 庫開發和寄存器的關系
??寄存器(Register)是單片機內部一種特殊的內存,它可以實現對單片機各個功能的控制,簡單的來說可以把寄存器當成一些控制開關,控制包括內核及外設的各種狀態。所以無論是 51單片機還是 STM32,都需要用寄存器來實現各種控制,以完成不同的功能。
??由于寄存器資源非常寶貴,一般都是一個位或者幾個位控制一個功能,對于 STM32 來說,其寄存器是 32 位的,一個 32 位的寄存器,可能會有 32 個控制功能,相當于 32 個開關,由于STM32 的復雜性,它內部有幾百個寄存器,所以整體來說 STM32 的寄存器還是比較復雜的。不過,我們不要被其嚇到了,實際上 STM32 是由于內部有很多外設,所以導致寄存器很多,實際上我們把它分好類,每個外設也就那么幾個或者幾十個寄存器,學起來就不難了。
??從大方向來區分,STM32 寄存器分為兩類,如表所示:
其中,內核寄存器,我們一般只需要關心中斷控制寄存器和 SysTick 寄存器即可,其他三大類,我們一般很少直接接觸。?
對于STM32 來說,以 GPIOB 的 ODR 寄存器為例,其寄存器地址為:0X40010C0C,我們對其賦值 0XFFFF,表示 GPIOB 所有 IO 口(16 個 IO 口)都輸出高電平:(*(unsigned int *))(0X40010C0C) = 0XFFFF;
雖然上面的代碼實現了我們需要的功能,但是從實用的角度來說,這么寫肯定是不好的,可讀性極差,可維護性也很差,所以一般我們使用結構體來訪問,比如改寫成這樣:
GPIOB->ODR = 0XFFFF;
這種方法當然可以,但是這種方法的劣勢是你需要去掌握每個寄存器的用法,你才能正確使用STM32,而對于 STM32 這種級別的 MCU,數百個寄存器記起來又是談何容易。于是 ST(意法半導體)推出了官方固件庫,固件庫將這些寄存器底層操作都封裝起來,提供一整套接口(API)供開發者調用,大多數場合下,你不需要去知道操作的是哪個寄存器,你只需要知道調用哪些函數即可。
比如控制 BSRRL 寄存器實現電平控制,官方 HAL 庫封裝了一個函數:void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) {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這個函數就可以了。在你對外設的工作原理有一定的了解之后,你再去看固件庫函數,基本上函數名字能告訴你這個函數的功能是什么,該怎么使用,這樣開發起來會方便很多。
??任何處理器,不管它有多么的高級,歸根結底都是要對處理器的寄存器進行操作。但是固件庫不是萬能的,如果想要把 STM32 學透,光讀 STM32 固件庫是遠遠不夠的。你還是要了解一下 STM32 的原理,了解 STM32 各個外設的運行機制。只有了解了這些原理,你在進行固件庫開發過程中才可能得心應手游刃有余。只有了解了原理,才能做到“知其然知其所以然”,所以在學習庫函數的同時,別忘了要了解一下寄存器大致配置過程。
??標準庫
函數是對寄存器簡單的進行了一次封裝
。將每個功能都獨立的封裝成一個函數。每個函數的功能比較單一。而HAL庫
相當于對寄存器進行了二次或者三次的封裝
,它將能合并的功能都合并在了一起。減小了寫代碼的難度。但是庫函數本身閱讀起來要比標準庫要費勁一些。這樣就導致,如果程序出錯的話調試起來要比標準庫難一點。但是HAL寫程序卻比較簡單,函數的名字也更容易理解。更接近于面向對象的思想。沒有哪種方式更好,每種都有自己的優缺點,根據實際情況,自己喜歡用哪種就用那種。通過對官方的這兩種庫的對比,可以看出在產品開發中代碼永遠都有優化和改進的空間。以后自己在開發項目的時候,也可以用這兩種不同的方式對自己的代碼進行優化升級。?
描述 標準外設庫 HAL / LL庫 內核寄存器 封裝文件
core_cm4.h core_cm4.h 內核寄存器 操作文件
1.
core_cm4.h
2.
misc.c / misc.h : 封裝NVIC、SysTick等
操作
3.
system_stm32f4xx.c : 系統初始化和時鐘配置函數,涉及對內核寄存器的操作
4.
startup_stm32f40xx.s: 底層匯編代碼,涉及內核寄存器初始化1.
core_cm4.h
2.
stm32f4xx_hal_cortex.c : 封裝對內核寄存器的操作
3.
system_stm32f4xx.c : 系統初始化和時鐘配置函數,涉及對內核寄存器的操作
4.
startup_stm32f40xx.s: 底層匯編代碼,涉及內核寄存器初始化
5.
stm32f4xx_hal.c: 間接操作內核寄存器外設寄存器 封裝文件
stm32f4xx.h stm32f4xx.h 外設寄存器 操作文件
stm32f4xx_ppp.c
stm32f4xx_ppp.hstm32f4xx_hal_ppp.c
stm32f4xx_hal_ppp.h
stm32f4xx_hal_ppp_ex.c
stm32f4xx_hal_ppp_ex.h
stm32f4xx_II_ppp.c
stm32f4xx_II_ppp.h
4. STM32CubeMX工具的作用
STM32CubeMX是一款圖形化配置工具,主要用于STM32微控制器的初始化和代碼生成。 其主要作用包括:
引腳配置:
可視化配置引腳功能,如GPIO、外設接口等,避免沖突。時鐘樹配置:
通過圖形界面配置系統時鐘、外設時鐘等,確保時鐘設置正確。外設配置:
配置外設參數,如UART、SPI、I2C、ADC等,生成初始化代碼。中間件配置:
配置FreeRTOS、FATFS、USB庫等中間件,簡化開發。功耗配置:
配置低功耗模式,優化功耗管理。代碼生成:
生成初始化代碼,支持多種IDE(如Keil、IAR、STM32CubeIDE等),并提供HAL庫和LL庫選項。項目管理:
創建和管理項目,支持多種開發環境和工具鏈。固件更新:
集成STM32固件更新功能,方便升級。?
通過STM32CubeMX工具自動生成驅動代碼,讓開發者只需專注實現 應用邏輯。