第9章 初識STM32固件庫—零死角玩轉STM32-F429系列


第9章     初識STM32固件庫

全套200集視頻教程和1000PDF教程請到秉火論壇下載:www.firebbs.cn

野火視頻教程優酷觀看網址:http://i.youku.com/firege

 

本章參考資料:《STM32F4xx參考手冊》、《STM32F4xx規格書》、《Cortex-M3權威指南》, STM32標准庫幫助文檔:《stm32f4xx_dsp_stdperiph_lib_um.chm》。

在上一章中,我們構建了幾個控制GPIO外設的函數,算是實現了函數庫的雛形,但GPIO還有很多功能函數我們沒有實現,而且STM32芯片不僅僅只有GPIO這一個外設。如果我們想要親自完成這個函數庫,工作量是非常巨大的。ST公司提供的標准軟件庫,包含了STM32芯片所有寄存器的控制操作,我們直接學習如何使用ST標准庫,會極大地方便控制STM32芯片。

9.1 CMSIS標准及庫層次關系

因為基於Cortex系列芯片采用的內核都是相同的,區別主要為核外的片上外設的差異,這些差異卻導致軟件在同內核,不同外設的芯片上移植困難。為了解決不同的芯片廠商生產的Cortex微控制器軟件的兼容性問題,ARM與芯片廠商建立了CMSIS標准(Cortex MicroController Software Interface Standard)

所謂CMSIS標准,實際是新建了一個軟件抽象層。見圖 91

91 CMSIS架構

CMSIS標准中最主要的為CMSIS核心層,它包括了:

    內核函數層:其中包含用於訪問內核寄存器的名稱、地址定義,主要由ARM公司提供。

    設備外設訪問層:提供了片上的核外外設的地址和中斷定義,主要由芯片生產商提供。

可見CMSIS層位於硬件層與操作系統或用戶層之間,提供了與芯片生產商無關的硬件抽象層,可以為接口外設、實時操作系統提供簡單的處理器軟件接口,屏蔽了硬件差異,這對軟件的移植是有極大的好處的。STM32的庫,就是按照CMSIS標准建立的。

9.1.1 庫目錄、文件簡介

STM32標准庫可以從官網獲得,也可以直接從本書的配套資料得到。本書講解的例程全部采用1.5.1庫文件。以下內容請大家打開STM32標准庫文件配合閱讀。

解壓庫文件后進入其目錄:

"STM32F4xx_DSP_StdPeriph_Lib_V1.5.1\"

軟件庫各文件夾的內容說明見圖 92。

92 ST標准庫    目錄:STM32F4xx_DSP_StdPeriph_Lib_V1.5.1\

    Libraries:文件夾下是驅動庫的源代碼及啟動文件。

    Project :文件夾下是用驅動庫寫的例子和工程模板。

    Utilities:包含了基於ST官方實驗板的例程,以及第三方軟件庫,如emwin圖形軟件庫、fatfs文件系統。

    MCD-ST Liberty…:庫文件的License說明。

    Release_Note.html::庫的版本更新說明。

    stm32f4xx_dsp_stdperiph…: 庫幫助文檔,這是一個已經編譯好的HTML文件,主要講述如何使用驅動庫來編寫自己的應用程序。說得形象一點,這個HTML就是告訴我們:ST公司已經為你寫好了每個外設的驅動了,想知道如何運用這些例子就來向我求救吧。不幸的是,這個幫助文檔是英文的,這對很多英文不好的朋友來說是一個很大的障礙。但這里要告訴大家,英文僅僅是一種工具,絕對不能讓它成為我們學習的障礙。其實這些英文還是很簡單的,我們需要的是拿下它的勇氣。

在使用庫開發時,我們需要把libraries目錄下的庫函數文件添加到工程中,並查閱庫幫助文檔來了解ST提供的庫函數,這個文檔說明了每一個庫函數的使用方法。

進入Libraries文件夾看到,關於內核與外設的庫文件分別存放在CMSISSTM32F4xx_StdPeriph_Driver文件夾中。

先看看CMSIS文件夾。

STM32F4xx_DSP_StdPeriph_Lib_V1.5.1\Libraries\CMSIS\文件夾下內容見圖 93

93 CMSIS文件夾內容目錄:Libraries\CMSIS\

其中DeviceInclude中的文件是我們使用得最多的,先講解這兩個文件夾中的內容。

1.    Include文件夾

Include文件夾中包含了的是位於CMSIS標准的核內設備函數層的Cortex-M核通用的頭文件,它們的作用是為那些采用Cortex-M核設計SOC的芯片商設計的芯片外設提供一個進入內核的接口,定義了一些內核相關的寄存器(類似我們前面寫的stm32f4xx.h文件,但定義的是內核部分的寄存器)。這些文件在其它公司的Cortex-M系列芯片也是相同的。至於這些功能是怎樣用源碼實現的,可以不用管它,只需把這些文件加進我們的工程文件即可,有興趣的朋友可以深究,關於內核的寄存器說明,需要查閱《cortex_m4_Technical Reference Manual》及《Cortex-M4內核參考手冊》文檔,《STM32參考手冊》只包含片上外設說明,不包含內核寄存器。

我們寫STM32F4的工程,必須用到其中的四個文件:core_cm4.hcore_cmFunc.hcorecmInstr.hcore_cmSimd.h,其它的文件是屬於其它內核的,還有幾個文件是DSP函數庫使用的頭文件。

core_cm4.c文件有一些與編譯器相關條件編譯語句,用於屏蔽不同編譯器的差異。里面包含了一些跟編譯器相關的信息,如:"__CC_ARM "(本書采用的RVMDKKEIL),"__GNUC__ "(GNU編譯器)、"ICC Compiler" (IAR編譯器)。這些不同的編譯器對於C嵌入匯編或內聯函數關鍵字的語法不一樣,這段代碼統一使用"__ASM__INLINE"宏來定義,而在不同的編譯器下,宏自動更改到相應的值,實現了差異屏蔽,見代碼清單91

 

 

代碼清單91core_cm3.c文件中對編譯器差異的屏蔽

1 #if defined ( __CC_ARM )

2 #define __ASM __asm /*!< asm keyword for ARM Compiler */

3 #define __INLINE __inline /*!< inline keyword for ARM Compiler*/

4 #define __STATIC_INLINE static __inline

5

6 #elif defined ( __GNUC__ )

7 #define __ASM __asm /*!< asm keyword for GNU Compiler */

8 #define __INLINE inline /*!< inline keyword for GNU Compiler */

9 #define __STATIC_INLINE static inline

10

11 #elif defined ( __ICCARM__ )

12 #define __ASM __asm /*!< asm keyword for IAR Compiler */

13 /*!< inline keyword for IAR Compiler. */

14 #define __STATIC_INLINE static inline

15 #define __INLINE inline

16

17 #elif defined ( __TMS470__ )

18 #define __ASM __asm /*!< asm keyword for TI CCS Compiler */

19 #define __STATIC_INLINE static inline

20

21 #elif defined ( __TASKING__ )

22 #define __ASM __asm /*!< asm keyword for TASKING Compiler */

23 #define __INLINE inline /*!< inline keyword for TASKING Compiler */

24 #define __STATIC_INLINE static inline

25

26 #elif defined ( __CSMC__ )

27 #define __packed

28 #define __ASM _asm /*!< asm keyword for COSMIC Compiler */

29 /*use -pc99 on compile line !< inline keyword for COSMIC Compiler */

30 #define __INLINE inline

31 #define __STATIC_INLINE static inline

32

33 #endif

較重要的是在core_cm4.c文件中包含了"stdint.h"這個頭文件,這是一個ANSI C 文件,是獨立於處理器之外的,就像我們熟知的C語言頭文件"stdio.h"文件一樣。位於RVMDK這個軟件的安裝目錄下,主要作用是提供一些類型定義。見代碼清單92

代碼清單92stdint.c文件中的類型定義

1.    /* exact-width signed integer types */  

2.    typedef   signed          char int8_t;   

3.    typedef   signed short     int int16_t;   

4.    typedef   signed           int int32_t;   

5.    typedef   signed       __int64 int64_t;   

6.      

7.    /* exact-width unsigned integer types */  

8.    typedef unsigned          char uint8_t;   

9.    typedef unsigned short     int uint16_t;   

10.    typedef unsigned           int uint32_t;   

11.    typedef unsigned       __int64 uint64_t;  

這些新類型定義屏蔽了在不同芯片平台時,出現的諸如int的大小是16位,還是32位的差異。所以在我們以后的程序中,都將使用新類型如uint8_t uint16_t等。

在稍舊版的程序中還經常會出現如u8u16u32這樣的類型,分別表示的無符號的8位、16位、32位整型。初學者碰到這樣的舊類型感覺一頭霧水,它們定義的位置在STM32f4xx.h文件中。建議在以后的新程序中盡量使用uint8_t uint16_t類型的定義。

core_cm4.c跟啟動文件一樣都是底層文件,都是由ARM公司提供的,遵守CMSIS標准,即所有CM4芯片的庫都帶有這個文件,這樣軟件在不同的CM4芯片的移植工作就得以簡化。

2.    Device文件夾

Device文件夾下的是具體芯片直接相關的文件,包含啟動文件、芯片外設寄存器定義、系統時鍾初始化功能的一些文件,這是由ST公司提供的。

    system_stm32f4xx.c文件

文件目錄:\Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates

這個文件包含了STM32芯片上電后初始化系統時鍾、擴展外部存儲器用的函數,例如我們前兩章提到供啟動文件調用的"SystemInit"函數,用於上電后初始化時鍾,該函數的定義就存儲在system_stm32f4xx.c文件。STM32F429系列的芯片,調用庫的這個SystemInit函數后,系統時鍾被初始化為180MHz,如有需要可以修改這個文件的內容,設置成自己所需的時鍾頻率。

    啟動文件

文件目錄:Libraries\CMSIS\Device\ST\STM32F4xx\Source\Templates

在這個目錄下,還有很多文件夾,如"ARM"、"gcc_ride7"、"iar"等,這些文件夾下包含了對應編譯平台的匯編啟動文件,在實際使用時要根據編譯平台來選擇。我們使用的MDK啟動文件在"ARM"文件夾中。其中的"strartup_stm32f429_439xx.s"即為STM32F429芯片的啟動文件,前面兩章工程中使用的啟動文件就是從這里復制過去的。如果使用其它型號的芯片,要在此處選擇對應的啟動文件,如STM32F446型號使用"startup_stm32f446xx.s"文件。

    stm32f4xx.h文件

文件目錄: Libraries\CMSIS\Device\ST\STM32F4xx\Include

stm32f4xx.h 這個文件非常重要,是一個STM32芯片底層相關的文件。它是我們前兩章自己定義的"stm32f4xx.h"文件的完整版,包含了STM32中所有的外設寄存器地址和結構體類型定義,在使用到STM32標准庫的地方都要包含這個頭文件。

CMSIS文件夾中的主要內容就是這樣,接下來我們看看STM32F4xx_StdPeriph_Driver文件夾。

3.    STM32F10x_StdPeriph_Driver文件夾

文件目錄:Libraries\STM32F4xx_StdPeriph_Driver

進入libraries目錄下的STM32F4xx_StdPeriph_Driver文件夾,見圖 94

94 外設驅動

STM32F4xx_StdPeriph_Driver文件夾下有incinclude的縮寫)跟srcsource的簡寫)這兩個文件夾,這里的文件屬於CMSIS之外的的、芯片片上外設部分。src里面是每個設備外設的驅動源程序,inc則是相對應的外設頭文件。srcinc文件夾是ST標准庫的主要內容,甚至不少人直接認為ST標准庫就是指這些文件,可見其重要性。

src inc文件夾里的就是ST公司針對每個STM32外設而編寫的庫函數文件,每個外設對應一個 .c .h 后綴的文件。我們把這類外設文件統稱為:stm32f4xx_ppp.c stm32f4xx_ppp.h文件,PPP表示外設名稱。如在上一章中我們自建的stm32f4xx_gpio.cstm32f4xx_gpio.h文件,就屬於這一類。

如針對模數轉換(ADC)外設,在src文件夾下有一個stm32f4xx_adc.c源文件,在inc文件夾下有一個stm32f4xx_adc.h頭文件,若我們開發的工程中用到了STM32內部的ADC,則至少要把這兩個文件包含到工程里。見圖 95

95 驅動的源文件及頭文件

這兩個文件夾中,還有一個很特別的misc.c文件,這個文件提供了外設對內核中的NVIC(中斷向量控制器)的訪問函數,在配置中斷時,我們必須把這個文件添加到工程中。

4.    stm32f4xx_it.c、 stm32f4xx_conf.h文件

文件目錄:STM32F4xx_DSP_StdPeriph_Lib_V1.5.1\Project\STM32F4xx_StdPeriph_Templates

在這個文件目錄下,存放了官方的一個庫工程模板,我們在用庫建立一個完整的工程時,還需要添加這個目錄下的stm32f4xx_it.cstm32f4xx_it.hstm32f4xx_conf.h這三個文件。

stm32f4xx_it.c:這個文件是專門用來編寫中斷服務函數的,在我們修改前,這個文件已經定義了一些系統異常(特殊中斷)的接口,其它普通中斷服務函數由我們自己添加。但是我們怎么知道這些中斷服務函數的接口如何寫?是不是可以自定義呢?答案當然不是的,這些都有可以在匯編啟動文件中找到,在學習中斷和啟動文件的時候我們會詳細介紹

stm32f4xx_conf.h:這個文件被包含進stm32f4xx.h 文件。ST標准庫支持所有STM32F4型號的芯片,但有的型號芯片外設功能比較多,所以使用這個配置文件根據芯片型號增減ST庫的外設文件。見代碼清單93,針對STM32F429STM32F427型號芯片的差異,它們實際包含不一樣的頭文件,我們通過宏來指定芯片的型號。

代碼清單93 stm32f4xx_conf.h文件配置軟件庫

1

2 #if defined (STM32F429_439xx) || defined(STM32F446xx)

3 #include "stm32f4xx_cryp.h"

4 #include "stm32f4xx_hash.h"

5 #include "stm32f4xx_rng.h"

6 #include "stm32f4xx_can.h"

7 #include "stm32f4xx_dac.h"

8 #include "stm32f4xx_dcmi.h"

9 #include "stm32f4xx_dma2d.h"

10 #include "stm32f4xx_fmc.h"

11 #include "stm32f4xx_ltdc.h"

12 #include "stm32f4xx_sai.h"

13 #endif /* STM32F429_439xx || STM32F446xx */

14

15 #if defined (STM32F427_437xx)

16 #include "stm32f4xx_cryp.h"

17 #include "stm32f4xx_hash.h"

18 #include "stm32f4xx_rng.h"

19 #include "stm32f4xx_can.h"

20 #include "stm32f4xx_dac.h"

21 #include "stm32f4xx_dcmi.h"

22 #include "stm32f4xx_dma2d.h"

23 #include "stm32f4xx_fmc.h"

24 #include "stm32f4xx_sai.h"

25 #endif /* STM32F427_437xx */

26

27 #if defined (STM32F40_41xxx)

stm32f4xx_conf.h這個文件還可配置是否使用"斷言"編譯選項,見代碼清單 94

代碼清單 94 斷言配置

1 #ifdef USE_FULL_ASSERT

2

3 /**

4 * @brief The assert_param macro is used for parameters check.

5 * @param expr: If expr is false, it calls assert_failed function

6 * which reports the name of the source file and the source

7 * line number of the call that failed.

8 * If expr is true, it returns no value.

9 * @retval None

10 */

11 #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

12 /* Exported functions ---------------------------------- */

13 void assert_failed(uint8_t* file, uint32_t line);

14 #else

15 #define assert_param(expr) ((void)0)

16 #endif /* USE_FULL_ASSERT */

ST標准庫的函數中,一般會包含輸入參數檢查,即上述代碼中的"assert_param"宏,當參數不符合要求時,會調用"assert_failed"函數,這個函數默認是空的。

實際開發中使用斷言時,先通過定義USE_FULL_ASSERT宏來使能斷言,然后定義"assert_failed"函數,通常我們會讓它調用printf函數輸出錯誤說明。使能斷言后,程序運行時會檢查函數的輸入參數,當軟件經過測試,可發布時,會取消USE_FULL_ASSERT宏來去掉斷言功能,使程序全速運行。

9.1.2 庫各文件間的關系

前面向大家簡單介紹了各個庫文件的作用,庫文件是直接包含進工程即可,絲毫不用修改,而有的文件就要我們在使用的時候根據具體的需要進行配置。接下來從整體上把握一下各個文件在庫工程中的層次或關系,這些文件對應到CMSIS標准架構上。見圖 96

96 庫各文件關系

96描述了STM32庫各文件之間的調用關系,這個圖省略了DSP核和實時系統層部分的文件關系。在實際的使用庫開發工程的過程中,我們把位於CMSIS層的文件包含進工程,除了特殊系統時鍾需要修改system_stm32f4xx.c,其它文件絲毫不用修改,也不建議修改。

對於位於用戶層的幾個文件,就是我們在使用庫的時候,針對不同的應用對庫文件進行增刪(用條件編譯的方法增刪)和改動的文件。

9.2 使幫助文檔

我堅信,授之以魚不如授之以漁。官方資料是所有關於STM32知識的源頭,所以在本小節介紹如何使用官方資料。官方的幫助手冊,是最好的教程,幾乎包含了所有在開發過程中遇到的問題。這些資料已整理到了本書附錄資料中。

9.2.1 常用官方資料

    《STM32F4xx參考手冊》

這個文件全方位介紹了STM32芯片的各種片上外設,它把STM32的時鍾、存儲器架構、及各種外設、寄存器都描述得清清楚楚。當我們對STM32的外設感到困惑時,可查閱這個文檔。以直接配置寄存器方式開發的話,查閱這個文檔寄存器部分的頻率會相當高,但這樣效率太低了。

    《STM32F4xx規格書》

本文檔相當於STM32datasheet,包含了STM32芯片所有的引腳功能說明及存儲器架構、芯片外設架構說明。后面我們使用STM32其它外設時,常常需要查找這個手冊,了解外設對應到STM32的哪個GPIO引腳。

    Cortex-M4內核參考手冊》

本文檔由ST公司提供,主要講解STM32內核寄存器相關的說明,例如系統定時器、中斷等寄存器。這部分的內容是《STM32F4xx參考手冊》沒涉及到的內核部分的補充。相對來說,本文檔雖然介紹了內核寄存器,但不如以下兩個文檔詳細,要了解內核時,可作為以下兩個手冊的配合資料使用。

    《Cortex-M3權威指南》、《cortex_m4_Technical Reference Manual》。

這兩個手冊是由ARM公司提供的,它詳細講解了Cortex內核的架構和特性,要深入了解Cortex-M內核,這是首選,經典中的經典,其中Cortex-M3版本有中文版,方便學習。因為Cortex-M4內核與Cortex-M3內核大部分相同,可用它來學習,而Cortex-M4新增的特性,則必須參考《cortex_m4_Technical Reference Manual》文檔了,目前只有英文版。

    《stm32f4xx_dsp_stdperiph_lib_um.chm》

這個就是本章提到的庫的幫助文檔,在使用庫函數時,我們最好通過查閱此文件來了解標准庫提供了哪些外設、函數原型或庫函數的調用的方法。也可以直接閱讀源碼里面的函數的函數說明。

9.2.2 初識庫函數

所謂庫函數,就是STM32的庫文件中為我們編寫好的函數接口,我們只要調用這些庫函數,就可以對STM32進行配置,達到控制目的。我們可以不知道庫函數是如何實現的,但我們調用函數必須要知道函數的功能、可傳入的參數及其意義、和函數的返回值。

於是,有讀者就問那么多函數我怎么記呀?我的回答是:會查就行了,哪個人記得了那么多。所以我們學會查閱庫幫助文檔是很有必要的。

打開庫幫助文檔《stm32f4xx_dsp_stdperiph_lib_um.chm》見圖 97

97 庫幫助文檔

層層打開文檔的目錄標簽:

標簽目錄:Modules\STM32F4xx_StdPeriph_Driver\

可看到STM32F4xx _StdPeriph_Driver標簽下有很多外設驅動文件的名字MISCADCBKPCAN等標簽。

我們試着查看GPIO的"位設置函數GPIO_SetBits"看看,打開標簽:

標簽目錄:Modules\STM32F4xx_StdPeriph_Driver\GPIO\Functions\GPIO_SetBits 見圖 98

 

98 庫幫助文檔的函數說明

利用這個文檔,我們即使沒有去看它的具體源代碼,也知道要怎么利用它了。

GPIO_SetBits,函數的原型為void GPIO_SetBits(GPIO_TypeDef * GPIOx , uint16_t GPIO_Pin)。它的功能是:輸入一個類型為GPIO_TypeDef的指針GPIOx參數,選定要控制的GPIO端口;輸入GPIO_Pin_x宏,其中x指端口的引腳號,指定要控制的引腳。

其中輸入的參數 GPIOxST標准庫中定義的自定義數據類型,這兩個傳入參數均為結構體指針。初學時,我們並不知道如GPIO_TypeDef這樣的類型是什么意思,可以點擊函數原型中帶下划線的 GPIO_TypeDef 就可以查看這個類型的聲明了。

就這樣初步了解了一下庫函數,讀者就可以發現STM32的庫是寫得很優美的。每個函數和數據類型都符合見名知義的原則,當然,這樣的名稱寫起來特別長,而且對於我們來說要輸入這么長的英文,很容易出錯,所以在開發軟件的時候,在用到庫函數的地方,直接把庫幫助文檔中的函數名稱復制粘貼到工程文件就可以了。而且,配合MDK軟件的代碼自動補全功能,可以減少輸入量。

有的用戶覺得使用庫文檔麻煩,也可以直接查閱STM32標准庫的源碼,庫幫助文檔的說明都是根據源碼生成的,所以直接看源碼也可以了解函數功能。

9.3 每課一問

1.    打開ST標准庫,查看它的各個文件,對比一下ST標准庫與我們上一章中工程里的同名文件,查看有何差異。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM