本文內(nèi)容基于作者對(duì)固件庫(kù)的理解,按照便于理解的順序進(jìn)行整理介紹,部分參考了固件庫(kù)的說明,但是也基本上重新表述并按照作者理解的順序進(jìn)行重新編寫。
1.1 基于標(biāo)準(zhǔn)外設(shè)庫(kù)的軟件開發(fā)
1.1.1 STM32標(biāo)準(zhǔn)外設(shè)庫(kù)概述
STM32標(biāo)準(zhǔn)外設(shè)庫(kù)之前的版本也稱固件函數(shù)庫(kù)或簡(jiǎn)稱固件庫(kù),是一個(gè)固件函數(shù)包,它由程序、數(shù)據(jù)結(jié)構(gòu)和宏組成,包括了微控制器所有外設(shè)的性能特征。
該函數(shù)庫(kù)還包括每一個(gè)外設(shè)的驅(qū)動(dòng)描述和應(yīng)用實(shí)例,為開發(fā)者訪問底層硬件提供了一個(gè)中間API,通過使用固件函數(shù)庫(kù),無(wú)需深入掌握底層硬件細(xì)節(jié),開發(fā)者就可以輕松應(yīng)用每一個(gè)外設(shè)。因此,使用固態(tài)函數(shù)庫(kù)可以大大減少用戶的程序編寫時(shí)間,進(jìn)而降低開發(fā)成本。
每個(gè)外設(shè)驅(qū)動(dòng)都由一組函數(shù)組成,這組函數(shù)覆蓋了該外設(shè)所有功能。每個(gè)器件的開發(fā)都由一個(gè)通用API (application programming interface 應(yīng)用編程界面)驅(qū)動(dòng),API對(duì)該驅(qū)動(dòng)程序的結(jié)構(gòu),函數(shù)和參數(shù)名稱都進(jìn)行了標(biāo)準(zhǔn)化。
ST公司2007年10月發(fā)布了V1.0版本的固件庫(kù),MDK ARM3.22之前的版本均支持該庫(kù)。2008年6月發(fā)布了V2.0版的固件庫(kù),從2008年9月推出的MDK ARM3.23版本至今均使用V2.0版本的固件庫(kù)。V3.0以后的版本相對(duì)之前的版本改動(dòng)較大,本書使用目前較新的V3.4版本。
1.1.2 使用標(biāo)準(zhǔn)外設(shè)庫(kù)開發(fā)的優(yōu)勢(shì)
簡(jiǎn)單的說,使用標(biāo)準(zhǔn)外設(shè)庫(kù)進(jìn)行開發(fā)最大的優(yōu)勢(shì)就在于可以使開發(fā)者不用深入了解底層硬件細(xì)節(jié)就可以靈活規(guī)范的使用每一個(gè)外設(shè)。標(biāo)準(zhǔn)外設(shè)庫(kù)覆蓋了從GPIO到定時(shí)器,再到CAN、I2C、SPI、UART和ADC等等的所有標(biāo)準(zhǔn)外設(shè)。對(duì)應(yīng)的C源代碼只是用了最基本的C編程的知識(shí),所有代碼經(jīng)過嚴(yán)格測(cè)試,易于理解和使用,并且配有完整的文檔,非常方便進(jìn)行二次開發(fā)和應(yīng)用。
1.1.3 STM32F10XXX標(biāo)準(zhǔn)外設(shè)庫(kù)結(jié)構(gòu)與文件描述
標(biāo)準(zhǔn)外設(shè)庫(kù)的文件結(jié)構(gòu)
對(duì)標(biāo)準(zhǔn)外設(shè)庫(kù)的熟悉程度直接影響到程序的編寫,下面讓我們來認(rèn)識(shí)一下STM32F10XXX的標(biāo)準(zhǔn)外設(shè)庫(kù)。STM32F10XXX的標(biāo)準(zhǔn)外設(shè)庫(kù)經(jīng)歷眾多的更新目前已經(jīng)更新到最新的3.5版本,開發(fā)環(huán)境中自帶的標(biāo)準(zhǔn)外設(shè)庫(kù)為2.0.3版本,本書中以比較穩(wěn)定而且較新的V3.4版本為基礎(chǔ)介紹標(biāo)準(zhǔn)外設(shè)庫(kù)的結(jié)構(gòu)。
可以從ST的官方網(wǎng)站下載到各種版本的標(biāo)準(zhǔn)外設(shè)庫(kù),首先看一下3.4版本標(biāo)準(zhǔn)外設(shè)庫(kù)的文件結(jié)構(gòu),如圖 5?3所示。3.0以上版本的文件結(jié)構(gòu)大致相同,每個(gè)版本可能略有調(diào)整。
圖 5?3 STM32F10XXX V3.4標(biāo)準(zhǔn)外設(shè)庫(kù)文件結(jié)構(gòu)
表 5?4中介紹了每個(gè)文件夾所包含的主要內(nèi)容。
表 5?4 STM32F10XXX V3.4標(biāo)準(zhǔn)外設(shè)庫(kù)文件夾描述
STM32F10x_StdPeriph_Lib_V3.4.0 | _htmresc | 包含了所有的html頁(yè)面資源 |
---|---|---|
Li aries |
CMSIS | 見表 5?6 |
STM32F10x_StdPeriph_Driver | inc | 標(biāo)準(zhǔn)外設(shè)庫(kù)驅(qū)動(dòng)頭文件 |
src | 標(biāo)準(zhǔn)外設(shè)庫(kù)驅(qū)動(dòng)源文件 | ? |
Project | Examples | 標(biāo)準(zhǔn)外設(shè)庫(kù)驅(qū)動(dòng)的完整例程 |
Template | MDK-ARM | KEIL RVMDK的項(xiàng)目模板示例 |
RIDE | Raisonance RIDE的項(xiàng)目模板示例 | ? |
EWARM | IAR EWARM的項(xiàng)目模板示例 | ? |
Utilities | STM3210-EVAL | 包含了用于STM3210B-EVAL和STM3210E-EVAL評(píng)估板的專用驅(qū)動(dòng) |
標(biāo)準(zhǔn)外設(shè)庫(kù)的第一部分是CMSIS 和STM32F10x_StdPeriph_Driver,CMSIS是獨(dú)立于供應(yīng)商的Cortex-M處理器系列硬件抽象層,為芯片廠商和中間件供應(yīng)商提供了簡(jiǎn)單的處理器軟件接口,簡(jiǎn)化了軟件復(fù)用工作,降低了Cortex-M 操作系統(tǒng)的移植難度,并減少了新入門的微控制器開發(fā)者的學(xué)習(xí)曲線和新產(chǎn)品的上市時(shí)間。
STM32F10x_StdPeriph_Driver則包括了分別對(duì)應(yīng)包括了所有外設(shè)對(duì)應(yīng)驅(qū)動(dòng)函數(shù),這些驅(qū)動(dòng)函數(shù)均使用C語(yǔ)言編寫,并提供了統(tǒng)一的易于調(diào)用的函數(shù)接口,供開發(fā)者使用。
Project文件夾中則包括了ST官方的所有例程和基于不同編譯器的項(xiàng)目模板,這些例程是學(xué)習(xí)和使用STM32的重要參考。Utilities包含了相關(guān)評(píng)估板的示例程序和驅(qū)動(dòng)函數(shù),供使用官方評(píng)估板的開發(fā)者使用,很多驅(qū)動(dòng)函數(shù)同樣可以作為學(xué)習(xí)的重要參考。
STM32F10xxx標(biāo)準(zhǔn)外設(shè)庫(kù)體系結(jié)構(gòu)如圖 5?4所示。圖中很好的展示了各層以及具體文件之間的聯(lián)系,各文件的具體功能說明如表 5?5所示。
圖 5?4 STM32F10xxx標(biāo)準(zhǔn)外設(shè)庫(kù)體系結(jié)構(gòu)
表 5?5 文件功能說明
文件名 | 功能描述 | 具體功能說明 |
---|---|---|
core_cm3.hcore_cm3.c | Cortex-M3內(nèi)核及其設(shè)備文件 | 訪問Cortex-M3內(nèi)核及其設(shè)備:NVIC,SysTick等訪問Cortex-M3的CPU寄存器和內(nèi)核外設(shè)的函數(shù) |
stm32f10x.h | 微控制器專用頭文件 | 這個(gè)文件包含了STM32F10x全系列所有外設(shè)寄存器的定義(寄存器的基地址和布局)、位定義、中斷向量表、存儲(chǔ)空間的地址映射等 |
system_stm32f10x.hsystem_stm32f10x.c | 微控制器專用系統(tǒng)文件 | 函數(shù)SystemInit,用來初始化微控制器函數(shù)Sysem_ExtMemCtl,用來配置外部存儲(chǔ)器控制器。它位于文件startup_stm32f10x_xx.s /.c,在跳轉(zhuǎn)到main前調(diào)用SystemFrequncy,該值代表系統(tǒng)時(shí)鐘頻率 |
startup_stm32f10x_Xd.s | 編譯器啟動(dòng)代碼 | 微控制器專用的中斷處理程序列表(與頭文件一致)弱定義(Weak)的中斷處理程序默認(rèn)函數(shù)(可以被用戶代碼覆蓋) 該文件是與編譯器相關(guān)的 |
stm32f10x_conf.h | 固件庫(kù)配置文件 | 通過更改包含的外設(shè)頭文件來選擇固件庫(kù)所使用的外設(shè),在新建程序和進(jìn)行功能變更之前應(yīng)當(dāng)首先修改對(duì)應(yīng)的配置。 |
stm32f10x_it.hstm32f10x_it.c | 外設(shè)中斷函數(shù)文件 | 用戶可以相應(yīng)的加入自己的中斷程序的代碼,對(duì)于指向同一個(gè)中斷向量的多個(gè)不同中斷請(qǐng)求,用戶可以通過判斷外設(shè)的中斷標(biāo)志位來確定準(zhǔn)確的中斷源,執(zhí)行相應(yīng)的中斷服務(wù)函數(shù)。 |
stm32f10x_ppp.hstm32f10x_ppp.c | 外設(shè)驅(qū)動(dòng)函數(shù)文件 | 包括了相關(guān)外設(shè)的初始化配置和部分功能應(yīng)用函數(shù),這部分是進(jìn)行編程功能實(shí)現(xiàn)的重要組成部分。 |
Application.c | 用戶文件 | 用戶程序文件,通過標(biāo)準(zhǔn)外設(shè)庫(kù)提供的接口進(jìn)行相應(yīng)的外設(shè)配置和功能設(shè)計(jì)。 |
基于CMSIS標(biāo)準(zhǔn)的軟件架構(gòu)
根據(jù)調(diào)查研究,軟件開發(fā)已經(jīng)被嵌入式行業(yè)公認(rèn)為最主要的開發(fā)成本。
對(duì)于ARM公司來說,一個(gè)ARM內(nèi)核往往會(huì)授權(quán)給多個(gè)廠家,生產(chǎn)種類繁多的產(chǎn)品,如果沒有一個(gè)通用的軟件接口標(biāo)準(zhǔn),那么當(dāng)開發(fā)者在使用不同廠家的芯片時(shí)將極大的增加了軟件開發(fā)成本,因此,ARM與Atmel、IAR、Keil、hami-nary Micro、Micrium、NXP、SEGGER和ST等諸多芯片和軟件廠商合作,將所有Cortex芯片廠商產(chǎn)品的軟件接口標(biāo)準(zhǔn)化,制定了CMSIS標(biāo)準(zhǔn)。
此舉意在降低軟件開發(fā)成本,尤其針對(duì)新設(shè)備項(xiàng)目開發(fā),或者將已有軟件移植到其他芯片廠商提供的基于Cortex處理器的微控制器的情況。有了該標(biāo)準(zhǔn),芯片廠商就能夠?qū)⑺麄兊馁Y源專注于產(chǎn)品外設(shè)特性的差異化,并且消除對(duì)微控制器進(jìn)行編程時(shí)需要維持的不同的、互相不兼容的標(biāo)準(zhǔn)的需求,從而達(dá)到降低開發(fā)成本的目的。如圖5?5所示,?基于CMSIS標(biāo)準(zhǔn)的軟件架構(gòu)主要分為以下4層:用戶應(yīng)用層、操作系統(tǒng)及中間件接口層、CMSIS層、硬件寄存器層。?其中CMSIS層起著承上啟下的作用:一方面該層對(duì)硬件寄存器層進(jìn)行統(tǒng)一實(shí)現(xiàn),屏蔽了不同廠商對(duì)Cortex-M系列微處理器核內(nèi)外設(shè)寄存器的不同定義;另一方面又向上層的操作系統(tǒng)及中間件接口層和應(yīng)用層提供接口,簡(jiǎn)化了應(yīng)用程序開發(fā)難度,使開發(fā)人員能夠在完全透明的情況下進(jìn)行應(yīng)用程序開發(fā)。也正是如此,CMSIS層的實(shí)現(xiàn)相對(duì)復(fù)雜。
圖 5?5 CMSIS標(biāo)準(zhǔn)的軟件架構(gòu)
層主要分為以下3 個(gè)部分:
(1) 核內(nèi)外設(shè)訪問層(CPAL,Core Peripheral Access Layer):該層由ARM 負(fù)責(zé)實(shí)現(xiàn)。包括對(duì)寄存器名稱、地址的定義,對(duì)核寄存器、NVIC、調(diào)試子系統(tǒng)的訪問接口定義以及對(duì)特殊用途寄存器的訪問接口(例如:CONTROL,xPSR)定義。由于對(duì)特殊寄存器的訪問以內(nèi)聯(lián)方式定義,所以針對(duì)不同的編譯器ARM 統(tǒng)一用來屏蔽差異。該層定義的接口函數(shù)均是可重入的。
(2) 片上外設(shè)訪問層(DPAL, Device Peripheral Access Layer):該層由芯片廠商負(fù)責(zé)實(shí)現(xiàn)。該層的實(shí)現(xiàn)與CPAL 類似,負(fù)責(zé)對(duì)硬件寄存器地址以及外設(shè)訪問接口進(jìn)行定義。該層可調(diào)用CPAL 層提供的接口函數(shù)同時(shí)根據(jù)設(shè)備特性對(duì)異常向量表進(jìn)行擴(kuò)展,以處理相應(yīng)外設(shè)的中斷請(qǐng)求。
(3) 外設(shè)訪問函數(shù)(AFP, Access Functions for Peripherals):該層也由芯片廠商負(fù)責(zé)實(shí)現(xiàn),主要是提供訪問片上外設(shè)的訪問函數(shù),這一部分是可選的。
對(duì)一個(gè)Cortex-M微控制系統(tǒng)而言,CMSIS通過以上三個(gè)部分實(shí)現(xiàn)了:
定義了訪問外設(shè)寄存器和異常向量的通用方法;
定義了核內(nèi)外設(shè)的寄存器名稱和核異常向量的名稱;
為RTOS 核定義了與設(shè)備獨(dú)立的接口,包括Debug通道。
這樣芯片廠商就能專注于對(duì)其產(chǎn)品的外設(shè)特性進(jìn)行差異化,并且消除他們對(duì)微控制器進(jìn)行編程時(shí)需要維持的不同的、互相不兼容的標(biāo)準(zhǔn)需求,以達(dá)到低成本開發(fā)的目的。CMSIS中的具體文件結(jié)構(gòu)如表 5?6所示。
表 5?6 CMSIS文件夾結(jié)構(gòu)
CMSIS | Core | Documentation | CMSIS文檔 | ? |
---|---|---|---|---|
CM3 | Startup | arm | MDK ARM編譯器啟動(dòng)文件 | startup_stm32f10x_hd.s: 大容量產(chǎn)品啟動(dòng)文件startup_stm32f10x_md.s: 中容量產(chǎn)品啟動(dòng)文件startup_stm32f10x_ld.s: 小容量產(chǎn)品啟動(dòng)文件 |
gcc_ride7 | GCC編譯器啟動(dòng)文件 | ? | ? | ? |
iar | IAR編譯器啟動(dòng)文件 | ? | ? | ? |
TrueSTUDIO | TrueSTUDIO編譯器啟動(dòng)文件 | ? | ? | ? |
本文件夾包含STMF10xxx CMSIS文件:微控制器外設(shè)訪問層和內(nèi)核設(shè)備訪問層:core_cm3.h:CMSIS的Cortex-M3內(nèi)核設(shè)備訪問層頭文件core_cm3.c:CMSIS的Cortex-M3內(nèi)核設(shè)備訪問層源文件stm32f10x.h:CMSIS的Cortex-M3 STM32f10xxx微控制器外設(shè)訪問層頭文件system_stm32f10x.h:CMSIS的Cortex-M3 STM32f10xxx微控制器外設(shè)訪問層頭文件system_stm32f10x.c:CMSIS的Cortex-M3 STM32f10xxx微控制器外設(shè)訪問層源文件 | ? | ? | ? | ? |
在實(shí)際開發(fā)過程中,根據(jù)應(yīng)用程序的需要,可以采取2種方法使用標(biāo)準(zhǔn)外設(shè)庫(kù)(StdPeriph_Lib):
(1) 使用外設(shè)驅(qū)動(dòng):這時(shí)應(yīng)用程序開發(fā)基于外設(shè)驅(qū)動(dòng)的API(應(yīng)用編程接口)。用戶只需要配置文件”stm32f10x_conf.h”,并使用相應(yīng)的文件”stm32f10x_ppp.h/.c”即可。
(2) 不使用外設(shè)驅(qū)動(dòng):這時(shí)應(yīng)用程序開發(fā)基于外設(shè)的寄存器結(jié)構(gòu)和位定義文件。
這兩種方法的優(yōu)缺點(diǎn)在“使用標(biāo)準(zhǔn)外設(shè)庫(kù)開發(fā)的優(yōu)勢(shì)”小節(jié)中已經(jīng)有了具體的介紹,這里仍要說明的是,使用使用標(biāo)準(zhǔn)外設(shè)庫(kù)進(jìn)行開發(fā)可以極大的減小軟件開發(fā)的工作量,也是目前嵌入式系統(tǒng)開發(fā)的一個(gè)趨勢(shì)。
標(biāo)準(zhǔn)外設(shè)庫(kù)(StdPeriph_Lib)支持STM32F10xxx系列全部成員:大容量,中容量和小容量產(chǎn)品。?從表 5?6中也可以看出,啟動(dòng)文件已經(jīng)對(duì)不同的系列進(jìn)行了劃分,實(shí)際開發(fā)中根據(jù)使用的STM32產(chǎn)品具體型號(hào),用戶可以通過文件”stm32f10x.h”中的預(yù)處理define或者通過開發(fā)環(huán)境中的全局設(shè)置來配置標(biāo)準(zhǔn)外設(shè)庫(kù)(StdPeriph_Lib),一個(gè)define對(duì)應(yīng)一個(gè)產(chǎn)品系列。
下面列出支持的產(chǎn)品系列
STM32F10x_LD:STM32小容量產(chǎn)品
STM32F10x_MD:STM32中容量產(chǎn)品
STM32F10x_HD:STM32大容量產(chǎn)品
在庫(kù)文件中這些define的具體作用范圍是:
文件“stm3210f.h”中的中斷IRQ定義
啟動(dòng)文件中的向量表,小容量,中容量,大容量產(chǎn)品各有一個(gè)啟動(dòng)文件
外設(shè)存儲(chǔ)器映像和寄存器物理地址
產(chǎn)品設(shè)置:外部晶振(HSE)的值等
系統(tǒng)配置函數(shù)
因此通過宏定義這種方式,可以使標(biāo)準(zhǔn)外設(shè)庫(kù)適用于不同系列的產(chǎn)品,同時(shí)也方便與不同產(chǎn)品之間的軟件移植,極大的方便了軟件的開發(fā)。
1.1.4 STM32F10XXX標(biāo)準(zhǔn)外設(shè)庫(kù)的使用
標(biāo)準(zhǔn)外設(shè)庫(kù)中包含了眾多的變量定義和功能函數(shù),如果不能了解他們的命名規(guī)范和使用規(guī)律將會(huì)給編程帶來很大的麻煩,本節(jié)將主要敘述標(biāo)準(zhǔn)外設(shè)庫(kù)中的相關(guān)規(guī)范,通過這些規(guī)范的學(xué)習(xí)可以更加靈活的使用固件庫(kù),同時(shí)也將極大增強(qiáng)程序的規(guī)范性和易讀性,同時(shí)標(biāo)準(zhǔn)外設(shè)庫(kù)中的這種規(guī)范也值得我們?cè)谶M(jìn)行其他相關(guān)的開發(fā)時(shí)使用和借鑒。
縮寫定義
標(biāo)準(zhǔn)外設(shè)庫(kù)中的主要外設(shè)均采用了縮寫的形式,通過這些縮寫可以很容易的辨認(rèn)對(duì)應(yīng)的外設(shè)。
縮寫 | 外設(shè)/單元 |
---|---|
ADC | 模數(shù)轉(zhuǎn)換器 |
BKP | 備份寄存器 |
CAN | 控制器局域網(wǎng)模塊 |
CEC | ? |
CRC | CRC計(jì)算單元 |
DAC | 數(shù)模轉(zhuǎn)換器 |
DBGMCU | 調(diào)試支持 |
DMA | 直接內(nèi)存存取控制器 |
EXTI | 外部中斷事件控制器 |
FLASH | 閃存存儲(chǔ)器 |
FSMC | 靈活的靜態(tài)存儲(chǔ)器控制器 |
GPIO | 通用輸入輸出 |
I2C | I2C接口 |
IWDG | 獨(dú)立看門狗 |
PWR | 電源/功耗控制 |
RCC | 復(fù)位與時(shí)鐘控制器 |
RTC | 實(shí)時(shí)時(shí)鐘 |
SDIO | SDIO接口 |
SPI | 串行外設(shè)接口 |
TIM | 定時(shí)器 |
USART | 通用同步/異步收發(fā)器 |
WWDG | 窗口看門狗 |
命名規(guī)則
標(biāo)準(zhǔn)外設(shè)庫(kù)遵從以下命名規(guī)則 PPP表示任一外設(shè)縮寫,例如:ADC。源程序文件和頭文件命名都以“stm32f10x_”作為開頭,例如:stm32f10x_conf.h。常量?jī)H被應(yīng)用于一個(gè)文件的,定義于該文件中;被應(yīng)用于多個(gè)文件的,在對(duì)應(yīng)頭文件中定義。所有常量都由英文字母大寫書寫。
寄存器作為常量處理。他們的命名都由英文字母大寫書寫。在大多數(shù)情況下,他們采用與縮寫規(guī)范一致。外設(shè)函數(shù)的命名以該外設(shè)的縮寫加下劃線為開頭。每個(gè)單詞的第一個(gè)字母都由英文字母大寫書寫,例如:SPI_SendData。
在函數(shù)名中,只允許存在一個(gè)下劃線,用以分隔外設(shè)縮寫和函數(shù)名的其它部分。對(duì)于函數(shù)命名,總的來說有以下規(guī)則:
名為PPP_Init的函數(shù),其功能是根據(jù)PPP_InitTypeDef中指定的參數(shù),初始化外設(shè)PPP,例如TIM_Init.
名為PPP_DeInit的函數(shù),其功能為復(fù)位外設(shè)PPP的所有寄存器至缺省值,例如TIM_DeInit.
名為PPP_Init的函數(shù),其功能為通過設(shè)置PPP_InitTypeDef 結(jié)構(gòu)中的各種參數(shù)來定義外設(shè)的功能,例如:USART_Init .
名為PPP_Cmd的函數(shù),其功能為使能或者失能外設(shè)PPP,例如:SPI_Cmd.
名為PPP_ITConfig的函數(shù),其功能為使能或者失能來自外設(shè)PPP某中斷源,例如:RCC_ITConfig.
名為PPP_DMAConfig的函數(shù),其功能為使能或者失能外設(shè)PPP的DMA接口,例如:TIM1_DMAConfig.
用以配置外設(shè)功能的函數(shù),總是以字符串“Config”結(jié)尾,例如GPIO_PinRemapConfig.
名為PPP_GetFlagStatus的函數(shù),其功能為檢查外設(shè)PPP某標(biāo)志位被設(shè)置與否,例如:I2C_GetFlagStatus.
名為PPP_ClearFlag的函數(shù),其功能為清除外設(shè)PPP標(biāo)志位,例如:I2C_ClearFlag.
名為PPP_GetITStatus的函數(shù),其功能為判斷來自外設(shè)PPP的中斷發(fā)生與否,例如:I2C_GetITStatus.
名為PPP_ClearITPendingBit的函數(shù),其功能為清除外設(shè)PPP中斷待處理標(biāo)志位,例如:I2C_ClearITPendingBit.
這樣的命名方式非常便于程序的編寫和閱讀,以標(biāo)準(zhǔn)外設(shè)庫(kù)中的示例函數(shù)為例,下面摘錄了STM32F10x_StdPeriph_ExamplesADCADCs_DMAmian.c中的一段程序。
?
DMA_InitType Def DMA_InitStructure; /*?DMA1?channel1?configuration?*/ DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr?=?ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr?=?(uint32_t)&ADC1ConvertedValue; DMA_InitStructure.DMA_DIR?=?DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize?=?1; DMA_InitStructure.DMA_PeripheralInc?=?DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc?=?DMA_MemoryInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize?=?DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize?=?DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode?=?DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M?=?DMA_M2M_Disable; DMA_Init(DMA1_Channel1,?&DMA_InitStructure); /* Enable DMA1 channel1 */ DMA_Cmd(DMA1_Channel1,?ENABLE);??
?
這段程序完成了DMA1通道的配置,首先定義了DMA_InitType DMA_InitStructure,接著配置DMA_InitType的各種參數(shù),各參數(shù)的命名方式也均使用約定的命名方式,從命名就能夠很容易的看出各參數(shù)所指代的具體功能。
功能參數(shù)配置完成后,使用DMA_Init(DMA1_Channel1, &DMA_InitStructure);完成相應(yīng)外設(shè)的初始化,最后使用DMA_Cmd(DMA1_Channel1, ENABLE) 使能相應(yīng)外設(shè)。從這個(gè)例子就能夠很容易的看出標(biāo)準(zhǔn)外設(shè)庫(kù)這種規(guī)范化的命名規(guī)則給編寫和閱讀程序帶來的好處。
3. 變量定義
在早期的版本中有24個(gè)變量定義,在Keil的安裝根目錄下,可以找到對(duì)應(yīng)的定義,路徑為:KeilARMINCSTSTM32F10xstm32f10x_type.h
?
/*?Includes?-------*/ /*?Exported?types?---------*/ typedef?signed?long?s32; typedef?signed?short?s16; typedef?signed?char?s8; typedef signed long const sc32; /* Read Only */ typedef signed short const sc16; /* Read Only */ typedef signed char const sc8; /* Read Only */ typedef volatile signed long vs32; typedef volatile signed short vs16; typedef volatile signed char vs8; typedef volatile signed long const vsc32; /* Read Only */ typedef volatile signed short const vsc16; /* Read Only */ typedef volatile signed char const vsc8; /* Read Only */ typedef unsigned long u32; 30 31 typedef unsigned short u16; typedef unsigned char u8; typedef unsigned long const uc32; /* Read Only */ typedef unsigned short const uc16; /* Read Only */ typedef unsigned char const uc8; /* Read Only */ typedef volatile unsigned long vu32; typedef volatile unsigned short vu16; typedef volatile unsigned char vu8; typedef volatile unsigned long const vuc32; /* Read Only */ typedef volatile unsigned short const vuc16; /* Read Only */ typedef volatile unsigned char const vuc8; /* Read Only */?
3.0以后的版本中使用了CMSIS數(shù)據(jù)類型,變量的定義有所不同,但是出于兼容舊版本的目的,以上的數(shù)據(jù)類型仍然兼容。
CMSIS的IO類型限定詞如表 5?7所示,CMSIS和STM32固件庫(kù)的數(shù)據(jù)類型對(duì)比如表 5?8所示。這些數(shù)據(jù)類型可以在: STM32F10x_StdPeriph_Lib_V3.4.0LibrariesCMSISCM3DeviceSupportSTSTM32F10xstm32f10x.h中找到具體的定義,此部分定義如下。 ?
/*!?
表 5?7 CMSIS IO類型限定詞
IO類限定詞 | #define | 描述 |
---|---|---|
_I | volatile const | 只讀訪問 |
_O | volatile | 只寫訪問 |
_IO | volatile | 讀和寫訪問 |
表 5?8 固件庫(kù)與CMSIS數(shù)據(jù)類型對(duì)比
固件庫(kù)類型 | CMSIS類型 | 描述 |
---|---|---|
s32 | int32_t | 易揮發(fā)只讀有符號(hào)32位數(shù)據(jù) |
s16 | int16_t | 易揮發(fā)只讀有符號(hào)16位數(shù)據(jù) |
s8 | int8_t | 易揮發(fā)只讀有符號(hào)8位數(shù)據(jù) |
sc32 | const int32_t | 只讀有符號(hào)32位數(shù)據(jù) |
sc16 | const int16_t | 只讀有符號(hào)16位數(shù)據(jù) |
sc8 | const int8_t | 只讀有符號(hào)8位數(shù)據(jù) |
vs32 | _IO int32_t | 易揮發(fā)讀寫訪問有符號(hào)32位數(shù)據(jù) |
vs16 | _IO int16_t | 易揮發(fā)讀寫訪問有符號(hào)16位數(shù)據(jù) |
vs8 | _IO int8_t | 易揮發(fā)讀寫訪問有符號(hào)8位數(shù)據(jù) |
vsc32 | _I int32_t | 易揮發(fā)只讀有符號(hào)32位數(shù)據(jù) |
vsc16 | _I int16_t | 易揮發(fā)只讀有符號(hào)16位數(shù)據(jù) |
vsc8 | _I int8_t | 易揮發(fā)只讀有符號(hào)8位數(shù)據(jù) |
u32 | uint32_t | 無(wú)符號(hào)32位數(shù)據(jù) |
u16 | uint16_t | 無(wú)符號(hào)16位數(shù)據(jù) |
u8 | uint8_t | 無(wú)符號(hào)8位數(shù)據(jù) |
uc32 | const uint32_t | 只讀無(wú)符號(hào)32位數(shù)據(jù) |
uc16 | const uint16_t | 只讀無(wú)符號(hào)16位數(shù)據(jù) |
uc8 | const uint8_t | 只讀無(wú)符號(hào)8位數(shù)據(jù) |
vu32 | _IO uint32_t | 易揮發(fā)讀寫訪問無(wú)符號(hào)32位數(shù)據(jù) |
vu16 | _IO uint16_t | 易揮發(fā)讀寫訪問無(wú)符號(hào)16位數(shù)據(jù) |
vu8 | _IO uint8_t | 易揮發(fā)讀寫訪問無(wú)符號(hào)8位數(shù)據(jù) |
vuc32 | _I uint32_t | 易揮發(fā)只讀無(wú)符號(hào)32位數(shù)據(jù) |
vuc16 | _I uint16_t | 易揮發(fā)只讀無(wú)符號(hào)16位數(shù)據(jù) |
vuc8 | _I uint8_t | 易揮發(fā)只讀無(wú)符號(hào)8位數(shù)據(jù) |
stm32f10x.h文件中還包含了常用的布爾形變量定義,如:
?
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; #define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus;?
?
不同版本的標(biāo)準(zhǔn)外設(shè)庫(kù)的變量定義略有不同,如3.4版本中就沒有之前版本的TRUE和FALSE的定義,用戶也可以根據(jù)自己的需求按照上面的格式定義自己的布爾形變量。
在使用標(biāo)準(zhǔn)外設(shè)庫(kù)進(jìn)行開發(fā)遇到相關(guān)的定義問題時(shí)應(yīng)首先找到對(duì)應(yīng)的頭文件定義。
使用步驟
如果在開發(fā)中使用標(biāo)準(zhǔn)外設(shè)庫(kù)需要哪些描述呢?下面就進(jìn)行簡(jiǎn)要的介紹,這兒介紹的使用方法是與開發(fā)環(huán)境無(wú)關(guān)的,在不同的開發(fā)環(huán)境中可能在操作方式上略有不同,但是總體的流程都是一樣的,下一小節(jié)將介紹在MDK ARM開發(fā)環(huán)境下使用標(biāo)準(zhǔn)外設(shè)庫(kù)的詳細(xì)過程。
首先新建一個(gè)項(xiàng)目并設(shè)置工具鏈對(duì)應(yīng)的啟動(dòng)文件,可以使用標(biāo)準(zhǔn)外設(shè)庫(kù)中提供的模板,也可以自己根據(jù)自己的需求新建。標(biāo)準(zhǔn)外設(shè)庫(kù)中已經(jīng)提供了不同工具鏈對(duì)應(yīng)的文件,位于:
STM32F10x_StdPeriph_Lib_V3.4.0LibrariesCMSISCM3DeviceSupportSTSTM32F10xstartup目錄下。
其次按照使用產(chǎn)品的具體型號(hào)選擇具體的啟動(dòng)文件,加入工程。文件主要按照使用產(chǎn)品的容量進(jìn)行區(qū)分,根據(jù)產(chǎn)品容量進(jìn)行選擇即可。每個(gè)文件的具體含義可以在“stm32f10x.h”文件中找到對(duì)應(yīng)的說明,摘錄如下:
?
#if?!defined?(STM32F10X_LD)?&&?!defined?(STM32F10X_LD_VL)? && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL) /*?#define?STM32F10X_LD?*/? /*!< STM32F10X_LD: STM32 Low density devices */ /*?#define?STM32F10X_LD_VL?*/? /*!< STM32F10X_LD_VL: STM32 Low density Value Line devices */ /*?#define?STM32F10X_MD?*/? /*!< STM32F10X_MD: STM32 Medium density devices */ /*?#define?STM32F10X_MD_VL?*/? /*!< STM32F10X_MD_VL: STM32 Medium density Value Line devices */ /* #define STM32F10X_HD */ /*!< STM32F10X_HD: STM32 High density devices */ /*?#define?STM32F10X_HD_VL?*/? /*!< STM32F10X_HD_VL: STM32 High density value line devices */ /*?#define?STM32F10X_XL?*/? /*!< STM32F10X_XL: STM32 XL-density devices */ /* #define STM32F10X_CL */ /*!< STM32F10X_CL: STM32 Connectivity line devices */ #endif /* Tip: To avoid modifying this file each time you need to switch between these devices,?you?can?define?the?device?in?your?toolchain?compiler?preprocessor.? - Low-density devices are STM32F101xx, STM32F102xx and STM32F103xx microcontrollers where the Flash memory density ranges between 16 and 32 Kbytes. - Low-density value line devices are STM32F100xx microcontrollers where the Flash memory density ranges between 16 and 32 Kbytes. - Medium-density devices are STM32F101xx, STM32F102xx and STM32F103xx microcontrollers where the Flash memory density ranges between 64 and 128 Kbytes. - Medium-density value line devices are STM32F100xx microcontrollers where the Flash memory density ranges between 64 and 128 Kbytes. - High-density devices are STM32F101xx and STM32F103xx microcontrollers where the Flash memory density ranges between 256 and 512 Kbytes. - High-density value line devices are STM32F100xx microcontrollers where the Flash memory density ranges between 256 and 512 Kbytes. - XL-density devices are STM32F101xx and STM32F103xx microcontrollers where the Flash memory density ranges between 512 and 1024 Kbytes. - Connectivity line devices are STM32F105xx and STM32F107xx microcontrollers. */
?
“stm32f10x.h”是整個(gè)標(biāo)準(zhǔn)外設(shè)庫(kù)的入口文件,這個(gè)文件包含了STM32F10x全系列所有外設(shè)寄存器的定義(寄存器的基地址和布局)、位定義、中斷向量表、存儲(chǔ)空間的地址映射等。為了是這個(gè)文件適用于不同系列的產(chǎn)品,程序中是通過宏定義來實(shí)現(xiàn)不同產(chǎn)品的匹配的,上面這段程序的注釋中已經(jīng)詳細(xì)給出了每個(gè)啟動(dòng)文件所對(duì)應(yīng)的產(chǎn)品系列,與之對(duì)應(yīng),也要相應(yīng)的修改這個(gè)入口文件,需要根據(jù)所使用的產(chǎn)品系列正確的注釋/去掉相應(yīng)的注釋define。
在這段程序的下方同樣有這樣的一個(gè)注釋程序:
/#define USE_STDPERIPH_DRIVER/
用于選擇是否使用標(biāo)準(zhǔn)外設(shè)庫(kù),如果保留這個(gè)注釋,則用戶開發(fā)程序可以基于直接訪問“stm32f10x.h”中定義的外設(shè)寄存器,所有的操作均基于寄存器完成,目前不使用固件庫(kù)的單片機(jī)開發(fā),如51、AVR、MSP430等其實(shí)都是采用此種方式,通過在對(duì)應(yīng)型號(hào)的頭文件中進(jìn)行外設(shè)寄存器等方面的定義,從而在程序中對(duì)相應(yīng)的寄存器操作完成相應(yīng)的功能設(shè)計(jì)。
如果去掉/#define USE_STDPERIPH_DRIVER/的注釋,則是使用標(biāo)準(zhǔn)外設(shè)庫(kù)進(jìn)行開發(fā),用戶需要使用在文件“stm32f10x_conf.h”中,選擇要用的外設(shè),外設(shè)同樣是通過注釋/去掉注釋的方式來選擇。示例程序如下:
?
/* Uncomment the line below to enable peripheral header file inclusion */ #include?"stm32f10x_adc.h" /* #include "stm32f10x_bkp.h" */ /* #include "stm32f10x_can.h" */ /* #include "stm32f10x_cec.h" */ /* #include "stm32f10x_crc.h" */ /* #include "stm32f10x_dac.h" */ /*?#include?"stm32f10x_dbgmcu.h"?*/ #include?"stm32f10x_dma.h" /* #include "stm32f10x_exti.h" */ /* #include "stm32f10x_flash.h" */ /* #include "stm32f10x_fsmc.h" */ #include "stm32f10x_gpio.h" /* #include "stm32f10x_i2c.h" */ /* #include "stm32f10x_iwdg.h" */ /* #include "stm32f10x_pwr.h" */ #include "stm32f10x_rcc.h" /* #include "stm32f10x_rtc.h" */ /* #include "stm32f10x_sdio.h" */ /* #include "stm32f10x_spi.h" */ /* #include "stm32f10x_tim.h" */ /* #include "stm32f10x_usart.h" */ /* #include "stm32f10x_wwdg.h" */ #include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */? 上面一段程序來自于例程中的AD采集程序,程序使用了AD和DMA,因此去掉相應(yīng)的注釋,同時(shí)幾乎所有的應(yīng)用都需要使用復(fù)位與時(shí)鐘以及通用I/O,因此這兩項(xiàng)是必須的,而多數(shù)程序同樣要使用NVIC中斷IRQ設(shè)置和SysTick時(shí)鐘源設(shè)置,那么 “misc.h”這一項(xiàng)也是必須的。
上面已經(jīng)針對(duì)具體的產(chǎn)品信號(hào)和程序功能進(jìn)行了針對(duì)性的配置,接下來需要配置系統(tǒng)所使用的時(shí)鐘,系統(tǒng)時(shí)鐘在“system_stm32f10x.c”同樣通過注釋的方式來配置,程序如下:? ?
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE HSE_VALUE */ #define SYSCLK_FREQ_24MHz 24000000 #else /* #define SYSCLK_FREQ_HSE HSE_VALUE */ /* #define SYSCLK_FREQ_24MHz 24000000 */ /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 */ #define SYSCLK_FREQ_72MHz 72000000 #endif? 如果這兒沒有明確的定義那么HSI時(shí)鐘將會(huì)作為系統(tǒng)時(shí)鐘。
至此,已經(jīng)配置了系統(tǒng)的主要外部參數(shù),這些參數(shù)主要是通過更改相關(guān)的宏定義來實(shí)現(xiàn)的,有些開發(fā)環(huán)境,例如Keil支持在軟件設(shè)置中加入全局宏定義,因此像芯片系列定義,是否使用固件庫(kù)定義等也可以通過軟件添加來實(shí)現(xiàn)。
完成了主要參數(shù)配置以后就可以進(jìn)行程序的開發(fā)了,標(biāo)準(zhǔn)外設(shè)庫(kù)開發(fā)就可以使用標(biāo)準(zhǔn)外設(shè)庫(kù)中提供的方便的API函數(shù)進(jìn)行相應(yīng)的功能設(shè)計(jì)了。配置完成后,程序中仍然可以直接更改相應(yīng)寄存器的配置,通過對(duì)寄存器的操作可以提高程序的效率,因此可以使用標(biāo)準(zhǔn)外設(shè)庫(kù)和寄存器操作兩種相結(jié)合的方式。
?
審核編輯:湯梓紅
?
評(píng)論
查看更多