STM32單片機(jī)學(xué)習(xí)
《STM32單片機(jī)學(xué)習(xí)》由會(huì)員分享,可在線閱讀,更多相關(guān)《STM32單片機(jī)學(xué)習(xí)(12頁珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1、 前言:從51開始,單片機(jī)玩了很長時(shí)間了,有51,PIC,AVR等等,早就想跟潮流玩玩ARM,但一直沒有開始,原因-----不知道玩了ARM可以做什么(對(duì)我自己而言)。如果為學(xué)習(xí)而學(xué)習(xí),肯定學(xué)不好。然后cortex-m3出來了,據(jù)說,這東西可以替代單片機(jī),于是馬上開始關(guān)注。也在第一時(shí)間開始學(xué)習(xí),可惜一開始就有點(diǎn)站錯(cuò)了隊(duì),選錯(cuò)了型(仍是對(duì)我自己而言)。我希望這種芯片應(yīng)該是滿大街都是,隨便哪里都可以買得到,但我選的第一種顯然做不到。為此,大概浪費(fèi)了一年多時(shí)間吧,現(xiàn)在,回到對(duì)我來說是正確的道路上來啦,邊學(xué)邊寫點(diǎn)東西。 這里寫的是我的學(xué)習(xí)的過程,顯然,很多時(shí)候會(huì)是不全面的,不系統(tǒng)的,感悟式
2、的,甚至有時(shí)會(huì)是錯(cuò)誤的,有些做法會(huì)是不專業(yè)的。那么,為什么我還要寫呢?這是一個(gè)有趣的問題,它甚至涉及到博客為什么要存在的問題。顯然,博客里面的寫的東西,其正確性、權(quán)威性大多沒法和書比,可為什么博客會(huì)存在呢?理由很多,我非專家,只說我的感慨。 我們讀武俠小說,總會(huì)有一些創(chuàng)出獨(dú)門功夫的宗師,功夫極高,然后他的弟子則基本上無法超越他。我在想,這位宗師在創(chuàng)造他自己的獨(dú)門功夫時(shí),必然會(huì)有很多的次的曲折、彎路、甚至失敗,會(huì)浪費(fèi)他的很多時(shí)間,而他教給弟子時(shí),則已去掉了這些曲折和彎路,當(dāng)然更不會(huì)把失敗教給弟子,按理說,效率應(yīng)該更高,可是沒用,弟子大都不如師。為什么呢?也許知識(shí)本身并不是最重要的,獲取知識(shí)
3、的過程才是最重要的?也許所謂的知識(shí),并不僅僅是一條條的結(jié)論,而是附帶著很多說不清道不明的東西?如植物的根,一條主根上必帶有大量的小小的觸須? 閑話多了些,就權(quán)當(dāng)前言了。下面準(zhǔn)備開始。 一、條件的準(zhǔn)備 我的習(xí)慣,第一步是先搭建一個(gè)學(xué)習(xí)的平臺(tái)。原來學(xué)51,PIC,AVR時(shí),都是想方設(shè)法自己做些工具,實(shí)驗(yàn)板之類,現(xiàn)在人懶了,直接購買成品了。 硬件電路板:火牛板 軟件:有keil和iar可供選擇。網(wǎng)上的口水仗不少,我選keil,理由很簡單,這個(gè)我熟。目前要學(xué)的知識(shí)中,軟、硬件我都不熟,所以找一個(gè)我有點(diǎn)熟的東西就很重要。在我相當(dāng)熟練之前,肯定不會(huì)用到IAR,如果真的有一天不
4、得不用IAR,相信學(xué)起來也很容易,因?yàn)檫@個(gè)時(shí)候硬件部分我肯定很熟了,再加上有 keil的基礎(chǔ),所以應(yīng)該很容易學(xué)會(huì)了。 調(diào)試工具:JLINK V8。這個(gè)不多說了,價(jià)格便宜又好用,就是它了。 二、熱身 細(xì)細(xì)端詳,做工精良,尤其那上面的3.2吋屏,越看越喜歡。接下來就是一陣折騰了,裝JLINK軟件,給板子通電,先試試JLINK能不能與電腦和板子通信上了。真順,一點(diǎn)問題也沒有。于是準(zhǔn)備將附帶的程序一個(gè)一個(gè)地寫進(jìn)去試一試。一檢查,大部分例子的HEX文件并沒有給出,這要下一步自己生成,但是幾個(gè)大工程的例子都有HEX文件,如MP3,如UCCGI測試等,寫完以后觀察程序運(yùn)行的效果。因?yàn)橹耙沧鲞^
5、彩屏的東西,知道那玩藝代碼量很大,要流暢地顯示并不容,當(dāng)時(shí)是用AVR做的,在1.8吋屏上顯示一幅畫要有一段時(shí)間?,F(xiàn)在看起來,用STM32做的驅(qū)動(dòng)顯示出來的畫面還是很快的,不過這里顯示的大部分是自畫圖,并沒有完整地顯示一整幅的照片,所以到底快到什么程度還不好說,看來不久以后這可以作為一個(gè)學(xué)習(xí)點(diǎn)的。 一個(gè)晚上過去了,下一篇就是要開始keil軟件的學(xué)習(xí)了。 三、開始編程 硬件調(diào)通后,就要開始編程了。 編程的方法有兩種,一種是用st提供的庫,另一種是從最底層開始編程,網(wǎng)上關(guān)于使用哪種方法編程的討論很多,據(jù)說用庫的效率要低一些。但是用庫編程非常方便,所以我還是從庫開始啦。
6、庫是ST提供的,怎么說也不會(huì)差到哪里,再說了,用32位ARM的話,開發(fā)的觀念也要隨之改變一點(diǎn)了。 說說我怎么學(xué)的吧。 找個(gè)例子,如GPIO,可以看到其結(jié)構(gòu)如下: SOURCE(文件夾) - APP(文件夾) -CMSIS(文件夾) -STM32F10x_StdPeriph_Driver(文件夾) Lis(文件夾) OBJ(文件夾) 其中SOURCE中保存的是應(yīng)用程序,其中又有好多子文件夾,而CMSIS文件夾中和STM32F10x_StdPeriph_Driver文件夾中是ST提供的庫,這樣,如果要做新的工程只要將這個(gè)文件夾整個(gè)復(fù)制過來就行,
7、其中APP中保存自己的代碼。 因?yàn)槲覀冇?1單片機(jī)時(shí)一般比較簡單,有時(shí)就一個(gè)文件,所以通常不設(shè)置專門的輸出文件夾,而這里做開發(fā),通常會(huì)有很多個(gè)文件加入一個(gè)工程中,編譯過程中會(huì)產(chǎn)生很多中間文件,因此設(shè)置專門的文件夾LIS和OBJ用來保存中間文件。 下面就將設(shè)置簡單描述一下。 將復(fù)到過來的GPIO根目錄下的所有文件刪除,因?yàn)槲覀円獙W(xué)著自己建立工程。 用菜單Project--》New uVision Porject.。.建立新的工程,選擇目標(biāo)器件為STM32103VC,這個(gè)過程與建立51單片機(jī)的工程沒有什么區(qū)別,這里就偷點(diǎn)懶,不上圖了。接下來看一看怎么設(shè)置。 點(diǎn)
8、那個(gè)品字形,打開對(duì)話框 這里就給個(gè)圖了,相信有一定操作基礎(chǔ)的人應(yīng)該會(huì)用。順便提一下,原來用VC或者IAR時(shí)總覺得它們的一個(gè)功能:就是建立一個(gè)是Debug組和Release組,這個(gè)功能挺好的,從這個(gè)圖可在Keil里也是一樣可以建的。 將剛才那個(gè)文件夾圖中CMSIS中的文件加入CMSIS組,一共3個(gè),其中\(zhòng)Source\CMSIS\Core\CM3有兩個(gè)C語言源程序文件全部加入,另外還有一個(gè)在 \Source\CMSIS\Core\CM3\startup\arm文件夾中,這個(gè)文件夾中有4個(gè).s文件, 我們選擇其中的 startup_stm32f10x_hd.s文件。這是根
9、據(jù)項(xiàng)目所用CPU來選擇的,我們用的CPU是103VC的,屬于高密度的芯片,所以選這個(gè)。 至于LIB中的文件,就在這兒:\Source\STM32F10x_StdPeriph_Driver\src啦。這里有很多個(gè)文件,把什么文件加進(jìn)去呢?怕麻煩的話,把所有文件全部加進(jìn)去,這并不會(huì)增加編譯后的代碼量,但會(huì)增加很多的編譯時(shí)間。 接下來設(shè)定目標(biāo)輸出文件夾。上面這個(gè)圖怎么出來的就不說啦,單擊“Select Foler for Objects。”,在彈出來的對(duì)話框中選擇OBJ文件夾。 同樣方法,選擇List文件的輸出文件夾。 設(shè)置好后,如果直接編譯是不行的,會(huì)出錯(cuò)。
10、還需要提供頭文件所在位置。單擊c/C++標(biāo)簽頁。 第一次進(jìn)入時(shí)Include Paths 文本框中是空白的,點(diǎn)擊其后的按鈕打開對(duì)話框,增加相應(yīng)的路徑 這樣路徑就設(shè)好了。單擊OK,回到上一界面,然后再單擊OK,退出設(shè)置,即可編譯、鏈接。 下一會(huì)要試一試新的3.12版的庫效果如何了。 升級(jí)庫 光盤中所帶的例子是3.10的,另外還有一個(gè)3.12的,我 試著將3.12的庫替代原來的庫,還真有問題,下面就簡述問題及解決方法。 ?。?)將庫文件解壓 庫文件名是:stm32f10x_stdperiph_lib.zip,解壓后放在任意一個(gè)文件夾中。 ?。?/p>
11、2)由于原作者做了很好的規(guī)劃,每一個(gè)項(xiàng)目中都分成三個(gè)文件夾,并且在source文件夾中又做了3個(gè)文件夾,其中APP文件夾是放自己寫的文件的,其他的兩個(gè)是從庫中復(fù)制過來的,因此,想當(dāng)然地把3.1.2版本中相同的兩個(gè)文件夾: CMSIS和STM32F10x_StdPeriph_Driver直接復(fù)制過來,以為一切OK,結(jié)果一編譯,出來一堆錯(cuò)誤。 其中有錯(cuò)誤: Source\App\main.c(7): error: #20: identifier “GPIO_InitTypeDef” is undefined 。..。 還有大量的警告: Source\STM32F
12、10x_StdPeriph_Driver\src\stm32f10x_flash.c(130): warning: #223-D: function “assert_param” declared implicitly 看了看,在APP文件夾中還有一些不屬于自己的東西: stm32f10x_conf.h,stm32f10x_it.h,stm32f10x_it.c,打開一看,果然是3.10版本的,沒說的,換。。。。,找到STM32F10x_StdPeriph_Lib_V3.1.2\Project\Template文件夾,用里面的同樣的文件替換掉這幾個(gè)文件,這回應(yīng)該萬事大吉了吧。
13、 再一看,依然如故,,沒辦法了,只好細(xì)細(xì)研究了。通過觀察,發(fā)現(xiàn)原來可以編譯通過的工程,在main.c下面掛滿了.h文件,而這個(gè)通不過的,則少得很。 這是編譯能通過的工程 這是編譯通不過的工程 顯然,有些文件沒有被包含進(jìn)來。一點(diǎn)一點(diǎn)跟蹤,發(fā)現(xiàn)大部分的頭文件都包含在stm32f10x_conf.h中,而這個(gè)文件又出現(xiàn)在stm32f10x.h中,其中有這樣的一行: #ifdef USE_STDPERIPH_DRIVER #include “stm32f10x_conf.h” #endif 看來,是這個(gè)USE_STDPERIPH_DRIVER沒有被
14、定義啊,于是,人為地去掉條件: //#ifdef USE_STDPERIPH_DRIVER #include “stm32f10x_conf.h” //#endif 再次編譯,果然就OK了??墒牵墒?,也不能就這么去掉啊,怎么辦呢?萬能的網(wǎng)啊,一搜果然就有了。 到設(shè)置 C/C++頁面 在那個(gè)define中加入“USE_STDPERIPH_DRIVER,STM32F10X_HD” 當(dāng)然,去掉條件編譯前面的注釋,回到原樣。 再次編譯,一切順利。可是,原來的工程例子也沒有加這個(gè)啊,怎么回事呢?再次打開原來的例子,找到stm32f10x.h,可以
15、看到有這么一行: 而新的stm32f10x.h中則是這樣的: 原來那個(gè)3.1.0版的stm32f10x.h被人為地修改了一下,所以,不在define中定義也不要緊,而新升級(jí)的3.1.2則不行了。 至此,簡單的升級(jí)搞定。 內(nèi)存學(xué)習(xí) ARM中的RO、RW和ZI DATA 一直以來對(duì)于ARM體系中所描述的RO,RW和ZI數(shù)據(jù)存在似是而非的理解,這段時(shí)間對(duì)其仔細(xì)了解了一番,發(fā)現(xiàn)了一些規(guī)律,理解了一些以前書本上有的但是不理解的東西,我想應(yīng)該有不少人也有和我同樣的困惑,因此將我的一些關(guān)于RO,RW和ZI的理解寫出來,希望能對(duì)大家有所幫助。 要了解R
16、O,RW和ZI需要首先了解以下知識(shí): ARM程序的組成 此處所說的“ARM程序”是指在ARM系統(tǒng)中正在執(zhí)行的程序,而非保存在ROM中的bin映像(image)文件,這一點(diǎn)清注意區(qū)別。 一個(gè)ARM程序包含3部分:RO,RW和ZI RO是程序中的指令和常量 RW是程序中的已初始化變量 ZI是程序中的未初始化的變量 由以上3點(diǎn)說明可以理解為: RO就是readonly, RW就是read/write, ZI就是zero ARM映像文件的組成 所謂ARM映像文件就是指燒錄到ROM中的bin文件,也稱為image文件。以下用Imag
17、e文件來稱呼它。 Image文件包含了RO和RW數(shù)據(jù)。 之所以Image文件不包含ZI數(shù)據(jù),是因?yàn)閆I數(shù)據(jù)都是0,沒必要包含,只要程序運(yùn)行之前將ZI數(shù)據(jù)所在的區(qū)域一律清零即可。包含進(jìn)去反而浪費(fèi)存儲(chǔ)空間。 Q:為什么Image中必須包含RO和RW? A:因?yàn)镽O中的指令和常量以及RW中初始化過的變量是不能像ZI那樣“無中生有”的。 ARM程序的執(zhí)行過程 從以上兩點(diǎn)可以知道,燒錄到ROM中的image文件與實(shí)際運(yùn)行時(shí)的ARM程序之間并不是完全一樣的。因此就有必要了解ARM程序是如何從ROM中的image到達(dá)實(shí)際運(yùn)行狀態(tài)的。 實(shí)際上,RO中的指令至少應(yīng)該有這
18、樣的功能: 1. 將RW從ROM中搬到RAM中,因?yàn)镽W是變量,變量不能存在ROM中。 2. 將ZI所在的RAM區(qū)域全部清零,因?yàn)閆I區(qū)域并不在Image中,所以需要程序根據(jù)編譯器給出的ZI地址及大小來將相應(yīng)得RAM區(qū)域清零。ZI中也是變量,同理:變量不能存在ROM中 在程序運(yùn)行的最初階段,RO中的指令完成了這兩項(xiàng)工作后C程序才能正常訪問變量。否則只能運(yùn)行不含變量的代碼。 說了上面的可能還是有些迷糊,RO,RW和ZI到底是什么,下面我將給出幾個(gè)例子,最直觀的來說明RO,RW,ZI在C中是什么意思。 1; RO 看下面兩段程序,他們之間差了一條語句,這條語句就
19、是聲明一個(gè)字符常量。因此按照我們之前說的,他們之間應(yīng)該只會(huì)在RO數(shù)據(jù)中相差一個(gè)字節(jié)(字符常量為1字節(jié))。 Prog1: #include 《stdio.h》 void main(void) { ; } Prog2: #include 《stdio.h》 const char a = 5; void main(void) { ; } Prog1編譯出來后的信息如下: =======================================================================
20、========= Code RO Data RW Data ZI Data Debug 948 60 0 96 0 Grand Totals ================================================================================ Total RO Size(Code + RO Data) 1008 ( 0.98kB) Total RW Size(RW Data + ZI Data) 96 ( 0.09kB) Total ROM Size(Code + RO Data + RW Dat
21、a) 1008 ( 0.98kB) ================================================================================ Prog2編譯出來后的信息如下: ================================================================================ Code RO Data RW Data ZI Data Debug 948 61 0 96 0 Grand Totals =======================
22、========================================================= Total RO Size(Code + RO Data) 1009 ( 0.99kB) Total RW Size(RW Data + ZI Data) 96 ( 0.09kB) Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB) ================================================================================
23、 以上兩個(gè)程序編譯出來后的信息可以看出: Prog1和Prog2的RO包含了Code和RO Data兩類數(shù)據(jù)。他們的唯一區(qū)別就是Prog2的RO Data比Prog1多了1個(gè)字節(jié)。這正和之前的推測一致。 如果增加的是一條指令而不是一個(gè)常量,則結(jié)果應(yīng)該是Code數(shù)據(jù)大小有差別。 2; RW 同樣再看兩個(gè)程序,他們之間只相差一個(gè)“已初始化的變量”,按照之前所講的,已初始化的變量應(yīng)該是算在RW中的,所以兩個(gè)程序之間應(yīng)該是RW大小有區(qū)別。 Prog3: #include 《stdio.h》 void main(void) { ; } Pro
24、g4: #include 《stdio.h》 char a = 5; void main(void) { ; } Prog3編譯出來后的信息如下: ================================================================================ Code RO Data RW Data ZI Data Debug 948 60 0 96 0 Grand Totals ==================================================
25、============================== Total RO Size(Code + RO Data) 1008 ( 0.98kB) Total RW Size(RW Data + ZI Data) 96 ( 0.09kB) Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB) ================================================================================ Prog4編譯出來后的信息如下: ======
26、========================================================================== Code RO Data RW Data ZI Data Debug 948 60 1 96 0 Grand Totals ================================================================================ Total RO Size(Code + RO Data) 1008 ( 0.98kB) Total RW Size(RW Data
27、+ ZI Data) 97 ( 0.09kB) Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB) ================================================================================ 可以看出Prog3和Prog4之間確實(shí)只有RW Data之間相差了1個(gè)字節(jié),這個(gè)字節(jié)正是被初始化過的一個(gè)字符型變量“a”所引起的。 3; ZI 再看兩個(gè)程序,他們之間的差別是一個(gè)未初始化的變量“a”,從之前的了解中,應(yīng)該可以推測,這兩個(gè)程序之間應(yīng)該
28、只有ZI大小有差別。 Prog3: #include 《stdio.h》 void main(void) { ; } Prog4: #include 《stdio.h》 char a; void main(void) { ; } Prog3編譯出來后的信息如下: ================================================================================ Code RO Data RW Data ZI Data Debug 948
29、 60 0 96 0 Grand Totals ================================================================================ Total RO Size(Code + RO Data) 1008 ( 0.98kB) Total RW Size(RW Data + ZI Data) 96 ( 0.09kB) Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB) =================================
30、=============================================== Prog4編譯出來后的信息如下: ================================================================================ Code RO Data RW Data ZI Data Debug 948 60 0 97 0 Grand Totals =============================================================================
31、=== Total RO Size(Code + RO Data) 1008 ( 0.98kB) Total RW Size(RW Data + ZI Data) 97 ( 0.09kB) Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB) ================================================================================ 編譯的結(jié)果完全符合推測,只有ZI數(shù)據(jù)相差了1個(gè)字節(jié)。這個(gè)字節(jié)正是未初始化的一個(gè)字符型變量“a”所引起的。
32、 注意:如果一個(gè)變量被初始化為0,則該變量的處理方法與未初始化華變量一樣放在ZI區(qū)域。 即:ARM C程序中,所有的未初始化變量都會(huì)被自動(dòng)初始化為0。 總結(jié): 1; C中的指令以及常量被編譯后是RO類型數(shù)據(jù)。 2; C中的未被初始化或初始化為0的變量編譯后是ZI類型數(shù)據(jù)。 3; C中的已被初始化成非0值的變量編譯后市RW類型數(shù)據(jù)。 附: 程序的編譯命令(假定C程序名為tst.c): armcc -c -o tst.o tst.c armlink -noremove -elf -nodebug -info totals -info sizes -map -list aa.map -o tst.elf tst.o 編譯后的信息就在aa.map文件中。 ROM主要指:NAND Flash,Nor Flash RAM主要指:PSRAM,SDRAM,SRAM,DDRAM
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 六級(jí)上冊(cè)科學(xué)ppt課件-誰選擇了它們-教科版
- 護(hù)理核心制度培訓(xùn)一_圖文課件
- 部編《池子與河流》課件
- SWOT分析法(非常全面)課件
- 主題班會(huì)我的成長目標(biāo)課件
- 城市交通擁堵及治理總結(jié)課件
- 輸血相關(guān)性急性肺損傷課件
- 議論文的謀篇布局與論點(diǎn)的提出ppt課件
- 六級(jí)上冊(cè)科學(xué)ppt課件-地球的近鄰——月球-冀人版
- 疾病預(yù)防、冬季保暖-課件
- 中考英語語法復(fù)習(xí)之狀語從句ppt課件集4
- 《百分?jǐn)?shù)的意義和讀寫》參考ppt課件
- 主題班會(huì)堅(jiān)持就是勝利課件
- 第二章--用人單位對(duì)大學(xué)生的要求概況ppt課件
- 教科版六年級(jí)科學(xué)上冊(cè)第三單元檢測卷(含答案)課件