官术网_书友最值得收藏!

第1部分 從項目起步,學習單片機

第1章 單片機的前世今生

學習,從來就是一件嚴肅的事情!關于單片機的入門方法,有人習慣研究datasheet,把單片機的寄存器一個一個看一遍,然后再去寫代碼,設計電路;有人建議買開發(fā)板,在一個規(guī)劃好的平臺上進行學習。

而編者更喜歡在實戰(zhàn)中入門與學習,為什么?當我們學習走路的時候,不需要知道腳面與地面成多少角度,不需要知道左右腳要用多少力,只是去模仿別人就行了。亞里士多德曾經說過,一切學習都是從模仿開始的!

1.1 老生常談單片機

1.1.1 你好,單片機

到底什么是單片機?根據百度百科的定義,單片機(microcontroller)是一種集成電路芯片,采用超大規(guī)模集成電路技術把具有數據處理能力的中央處理器(CPU)、隨機存儲器(RAM)、只讀存儲器(ROM)、多種I/O口和中斷系統、定時器/計數器等功能(可能還包括顯示驅動電路、脈寬調制電路、模擬多路轉換器、A/D轉換器等電路)集成到一塊硅片上構成的一個小而完善的微型計算機系統,在工業(yè)控制領域廣泛應用。

說實話,編者不是很喜歡這個定義,因為對于一個新手來說,這個定義貌似給不了他想要的東西,反而帶來了更多的疑問。例如,什么是RAM,什么是ROM,什么是I/O,什么是定時器/計數器等。對于一個新人來說,這些問題估計他想破頭也想不出來。

換個說法,單片機是一種芯片,可以通過對其編寫程序來控制它進行工作。其中,ROM用來存儲編寫的程序;RAM用來提供程序執(zhí)行和運算所需的空間;I/O就是芯片上的引腳,通過編程可以控制I/O輸出不同的電平信號;定時器/計數器可以實現定時和計數的功能。把這些功能(高級單片機還有其他功能)集成到一塊芯片上,這就是單片機。圖1.1就是一個單片機的框架結構。

圖1.1 單片機的框架結構

舉個例子,小明要參加一場數學考試,需要準備什么?草稿紙、筆、手表,同時要背誦大量的計算公式等。在這個過程中,計算公式就是程序,小明要按照公式的規(guī)則去計算,才能得出正確的結果;大腦是ROM,用于存儲公式;草稿紙是RAM,當處理問題的時候,那些處理的流程和中間結果都要在草稿紙上體現出來;小明的手是I/O口,用于輸出計算得到的結果;手表是計時器,當一道題花費時間太多的時候,就要放棄,進行下一道題。

這樣一來,對單片機的理解是不是深入了很多?

在編者剛接觸電子的時候,對單片機有一個誤解,覺得所有的芯片都是單片機,或者都是可編程的。例如編者小的時候拆解自己家里的電子設備,看到每一個引腳多的芯片,都以為是單片機,現在想想,還是挺單純的。那么單片機在一個電路里到底充當什么角色呢?通過一個原理圖來說明,如圖1.2所示,這是一個MP3的解決方案。

圖1.2 MP3的解決方案

這是一個基于Atmega_32+VS1003B+SD卡+LCD的MP3的解決方案。在圖中, Atmega_32是ATMEL公司的單片機,SD卡(Secure Digital Memory Card)即常用的半導體閃存卡,VS1003B是VLSI公司生成的一款內置DSP核心、具有音頻編解碼功能的集成電路,LCD為液晶屏。

在這個系統中,電源電路為整套設備供電,需要播放的歌曲存儲在SD卡中。播放歌曲時,單片機(Atmega_32)從SD卡中讀取歌曲的數據。關于歌曲的屬性方面的信息,例如作者、歌曲名、時長,顯示在液晶屏上面;關于歌曲的音頻方面的數據,傳送到集成電路VS1003B里面,經過解碼,轉換為旋律,只要插上耳機,即可聽到美妙的音樂。

在這個過程中,單片機實現的是數據的讀取、運輸以及簡單的分析、處理的功能。最終音頻數據的解碼通過芯片VS1003B實現,歌曲信息的顯示通過液晶屏來實現,都是借助外部電路。打個比方,單片機就好像變形金剛的大腦,給它裝上一個軀體,再輸入相應的程序,就可以實現想要的功能。而這些軀體有的是不具備可編程能力的,只能被動地接收一些指令或數據。

1.1.2 為什么學習51單片機

一說起51單片機,最先想到的型號是什么?8051,8031,還有89C51,89S51,89C52,它們之間究竟是什么關系?

MCS-51其實是美國Intel公司(是的,就是大名鼎鼎的英特爾)生產的一系列單片機的總稱,這一系列單片機包括很多品種,例如8031、8051、8751、8032、8052、8752等,其中8051是最早、最典型的產品,該系列的其他單片機都是在8051的基礎上進行功能的增、減、改變而得來的,所以人們習慣于用8051來稱呼MCS-51這一系列單片機,或者直接說51單片機。8031是前些年在我國流行的單片機,它和8051相比最大的特點是沒有程序存儲空間。后來Intel公司將MCS-51的內核技術轉讓給了很多其他公司,所以市面上出現了很多以8051為核心的單片機。各家公司根據自身的技術實力對單片機的功能進行了一些優(yōu)化,以滿足不同的需求,但是整體架構不會變。

其中89C51與89C52這幾年在我國非常流行,兩者的主要區(qū)別在于89C51有兩個定時器/計數器,它的程序存儲空間是4KB;89C52有三個定時器/計數器,它的程序存儲空間是8KB。

因此51單片機是上述這幾種單片機型號的統稱,而在舊型號不斷被淘汰的今天,51主要用來特指89C51或89C52這兩種型號。

為什么選擇學習51單片機,原因有以下幾點。

第一,學習資料豐富,無論是書籍、視頻、源碼還是開發(fā)板,51的學習資料太全了。想看書,圖書館里有好多種供你選擇——講匯編語言的,講C語言的,講寄存器的;想看視頻,優(yōu)酷、土豆視頻網上有,各個大學的老師還有一些MCU愛好者自己錄制的學習視頻;或者買一套開發(fā)板,也會送相應的配套視頻;源碼,就更不用提了,電子工程世界、電子發(fā)燒友網站等提供了大量的源碼供你學習;開發(fā)板,上某寶一搜,鋪天蓋地。所以,學51單片機的時候,千萬不要擔心資料不夠多,因為它的資料是最多的!

第二,遇到問題的時候求助方便。因為學習51單片機的人多,所以,當你學習的時候遇到解決不了的問題時,可以輕易地找到解決的方案。為什么?因為你遇到的90%的問題,別人已經遇到并且解決了,所以當你向別人求助的時候,很輕易就能得到答案。

例如,用51單片機設計一款產品,它能夠把運行過程中產生的重要數據存儲到AT24C01里面。用過的人都知道,這個芯片是IIC接口的,正常來說,需要單片機有相應的硬件接口,然后配置一下相應的寄存器就行了。但是在51單片機里面是沒有IIC接口的,那就需要用普通的I/O引腳來模擬IIC總線的運行時序,進行數據的讀寫。

如果是沒做過模擬的人,第一次自己寫肯定很頭疼。但是你有沒有想過,中國有這么多工程師學習51單片機,他們是不是早就遇到了你遇到的問題?他們是不是已經把問題解決了?如果你能夠想明白這一點,再去學習單片機,就會事半功倍了!只要在百度中輸入“51單片機模擬IIC總線”,如圖1.3所示,就能得到你想要的答案。

圖1.3 51單片機模擬IIC總線搜索結果

第三,也是最重要的一點,學習51單片機是學習其他單片機的一個橋梁!51單片機從配置上說算是低端單片機了,但正是由于功能低端,學習方便,反而是入門的良好選擇。通過51單片機入門以后,再去學習任意一款單片機,都會有一種水到渠成的感覺。

單片機從IC結構上說,有哈佛結構和馮·諾依曼結構的分別;從指令集復雜程度上區(qū)分,會有復雜指令集和精簡指令集的區(qū)別;從運算的數據長度區(qū)分,會有8位單片機、16位單片機和32位單片機的分別。但是在應用上,單片機就是單片機,沒有太多花哨的說法,會用才是硬道理!

1.1.3 常見的單片機類型

8051單片機最早由Intel公司推出,一經面世就受到了無數電子工程師的熱愛。然后在20世紀80年代,Intel公司將MCS-51的內核技術轉讓給了各大芯片廠家,于是市面上出現了帶有各個廠家標志的51單片機:ATMEL、STC、WINBOND、飛利浦等。那么市面上到底有多少種單片機呢?這個還真不好說,就編者經常看到的而言有以下幾種:

(1)AVR單片機,1997年由ATMEL公司設計并推廣開來的一款高性能、低成本、精簡指令集的8位單片機。關于AVR的名字還很有意思,因為它是由ATMEL公司挪威設計中心的A先生與V先生基于精簡指令集(RISC)設計出來的一款單片機,所以以AVR命名。

(2)MSP430單片機。提到430,所有人腦子里都會反映出一個詞:超低功耗!現在編者還記得一本430書籍的封面上使用水果電池給單片機供電,段碼液晶顯示時間。現在想想,也是醉了!雖然它和AVR單片機都是精簡指令集,且推出時間相差只有一年,但是MSP430和AVR相比最大的區(qū)別在于它是16位單片機。同時由于它的超低功耗性能,在儀器儀表上的應用比較廣泛。

(3)STM32單片機,由意法半導體公司推出的近幾年最火的32位單片機,沒有之一!它具有高性能、低成本、低功耗的專為嵌入式應用設計的ARM Cortex-M內核,一流的外設,超高的運算速度。有人說它有著單片機的外表,ARM的內心!很多人學完51單片機以后,直接去學STM32,這也體現了它的火熱程度。

(4)PIC單片機,由美國Microchip公司推出的精簡指令集單片機,功耗低,驅動能力強,可以和51單片機一樣進行I/O的位定義。在漢化這方面PIC做得非常好,因為很多型號的PIC單片機在它的官網上能找到中文的datasheet。很多時候,可能產品質量、價格都差不多,但是服務做到了,競爭力自然就凸顯出來了。

(5)Freescale單片機,也就是飛思卡爾單片機。它種類齊全,從8位單片機到32位單片機,各個系列幾乎都覆蓋到了。它有多種通信模塊接口:IIC、SPI、CAN、LIN、SCI等,可以根據需求進行配置和價格的選型。從每年一次由飛思卡爾冠名的大學生智能車競賽就能看出該類型的單片機覆蓋范圍有多廣。而且它憑借超強的抗干擾能力在汽車電子中占有很高的市場份額。

上述幾種單片機都是市面上比較常見的類型,除此以外,還有很多,這里不再一一說明。如果大家對這些單片機感興趣,在學完51單片機以后,可以選擇其中一款進行學習。

1.2 因材施教,因物施法

記得高中的時候上微機課,因為計算機數量有限,所有班級都是先上理論課,等排上實操課了,再去機房上課。那個時候,老師經常講的內容就是Word的菜單里有哪些內容,然后在黑板上把菜單欄畫出來,完全用話來解釋什么是對話框,什么是菜單。當時聽得云里霧里,但是當上實操課的時候,操作了幾下就全都懂了。現在回想起來,那種授課方式真的是浪費時間。那么學習單片機該用什么方法呢?

1.2.1 通過Proteus仿真學習單片機

先說一下Proteus是什么。Proteus是英國Lab Center Electronics公司設計的一款EDA(Electronic Design Automation)仿真軟件,具有原理圖設計、單片機程序仿真、外圍電路仿真等強大的功能,它的處理器平臺支持8086、51、AVR、DSP、MSP430、HC11、PIC、ARM7和Cortex-M3/M0等。

它的虛擬器件庫包含超過27000種的電子元件,像那些電阻、電容、LED之類的東西完全不在話下。更重要的是,它自帶很多虛擬仿真器:虛擬串口、SPI、IIC、邏輯分析儀、頻率計、示波器,這些器件在實際的電路設計中起到的作用是非常重要的。

該軟件在實際應用中是如何協助電子愛好者開展設計的呢?以原理和代碼的驗證為目的,就個人經驗而言,分為以下幾步:

(1)原理圖設計。根據項目所需的功能要求,選定該項目所需的硬件,包括MCU和外圍器件。在Proteus中找到相應器件,進行擺放和各個元件之間的導線連接。

(2)源代碼編寫。功能的實現除了硬件的支持,少不了程序的幫助。

(3)驗證及修改。將寫好的程序進行編譯,一般是生成hex文件,然后把hex文件導入Proteus中調用的單片機上,使程序運行,觀察輸出是否符合要求。

一般來說,一段程序從開始編寫到最后確定版本會修改很多次(那種點亮LED的小程序除外)。也就是說,上述的步驟(2)和(3)會重復多次,甚至功能要求有變動時,步驟(1)也會重復進行。

那么Proteus的優(yōu)勢就很明顯了,要知道,在實際工作中,進行原理驗證是很麻煩的一件事,需要購買元器件、在洞洞板(也稱萬能電路板、萬用板或實驗板)或者樣板上焊接、下載、調試。如果焊接有失誤,還要進行故障排查。也就是說,需要大量的人力和物力。然而有了Proteus,大部分工序都可以省了,只需要動動鼠標和鍵盤,所有的器件都能夠聽從你的安排,仿真結果一目了然,進行修改也不會有多麻煩。

那么,通過該軟件進行單片機的入門學習是不是很好呢?不見得!再看一下上面的步驟:原理圖設計,源代碼編寫,驗證及修改。這些步驟針對的都是已經學會單片機的人,他們知道89C52有多少個I/O,所以知道可以外接多少設備;他們知道89C52有多大的ROM,所以知道源代碼最多能寫多少;他們知道單片機和外圍電路如何匹配,所以知道原理圖該如何設計。但是新人呢?他們貌似什么都不知道。

是的,通過學習可以掌握Proteus的大部分功能,但是學到最后,可能很多人都不知道真實的單片機長什么樣子,電阻長什么樣子,電容長什么樣子。就好像很多人玩反恐精英CS這個游戲一樣,在游戲里面很厲害,在現實生活中也能這么厲害嗎?

因此編者建議:新人少碰Protues。什么時候接觸?當你已經基本掌握了單片機的應用,想要在某個項目中驗證原理和程序的可行性的時候,它會是你的利器。

1.2.2 通過開發(fā)板學習單片機

在網上買一塊開發(fā)板,然后根據配套視頻,輸入相應的代碼,然后編譯、下載,這種方式是當前比較流行的學習方式。編者也買了很多塊開發(fā)板,有51的,有430的,有AVR的,有STM32的,通過這種方式也掌握了很多知識。那么這種方式是否是學習單片機的最佳方式呢?

老實說,買現成的開發(fā)板固然方便,但是硬件電路都是已經設計好的。雖然廠商會提供開發(fā)板的原理圖,但是缺少了手動搭建的過程,難免會對硬件原理的理解不是很深刻。例如,為什么LED要下拉驅動,上拉可不可以?為什么要用鎖存器驅動數碼管,三極管行不行?多按鍵掃描一定要排成矩陣的形式嗎,別的樣式行不行?驅動蜂鳴器多是PNP三極管,NPN為什么用得少?

如果是通過開發(fā)板學習的朋友,上面的問題估計不是很好回答。單片機的學習不只是寫代碼、編譯、下載,還會有單片機外圍電路的設計。要熟悉LED如何跟電阻匹配才能正常點亮;要了解數碼管如何設計驅動電路最省成本,不傷害單片機性能。如果購買開發(fā)板進行學習,相當于在一定程度上拋開了電路設計的內容,只學習程序的編寫,對于外部元器件為什么這樣放置只能知其然不知其所以然。甚至在應用到特殊環(huán)境時,一些在實驗室工作正常的電路有可能無法正常工作。

這里,編者并不是說開發(fā)板沒有用,當你已經掌握單片機常用外圍電路,想要學習高級單片機的內核時,開發(fā)板會非常有幫助。入門階段,還是多動手為好。

1.2.3 逆向學習

什么是逆向學習?先了解一下正向學習,就是按照學校里的學習步驟,先了解一項事務的概況,然后了解該事務運行的基本規(guī)則、專有名詞等,逐步深入地學習、研究。舉個例子,中國的孩子學習英語都是首先學26個英文字母;然后是音標——元音、輔音;然后背單詞,還要區(qū)分動詞、名詞、系動詞、形容詞、副詞;然后熟悉語法;最后可能會要求背誦課文。

美國的小朋友是如何學習英文的?估計不會有哪位媽媽整天對著自己一兩歲的孩子說:這個是動詞,你要記住!那個語法比較特殊,你要理解!每個孩子都是從牙牙學語開始的,他(她)不會管什么語法,什么詞性,別人怎么說,他(她)就怎么學,首先是爸爸、媽媽,然后是吃、拿、爺爺、奶奶等。其實,無論是中國孩子還是美國孩子,他(她)們學習母語的過程都是逆向學習的過程,在這個過程里摒棄了大部分的語法、規(guī)則,一切都以實用為主,先用后學,用到什么就學習什么,這就是逆向學習。

因此,在這本書里,希望大家跟隨編者一起動手搭建電路,以制作出一個小產品為目標,從點亮一個LED開始,邊做邊學。遇到難點或者不懂的地方,有針對性地深入了解,當你把整個流程都走一遍之后,51單片機基本上就入門了。

說了這么多,那么到底用什么學習呢?編者想了又想,決定用51最小系統板+洞洞板(或面包板)+零散的元器件等進行教學。

什么是51最小系統板?還記得1.1節(jié)講到的51開發(fā)板嗎?開發(fā)板上有很多已經連接好的硬件電路,最小系統上沒有這些硬件,它配備單片機、時鐘電路、復位電路、下載線接口、電源接口、電源開關和電源指示燈,同時,把單片機的I/O口使用排針全部引出來,這樣的一款板子叫做最小系統板,如圖1.4所示。因為它簡潔,不啰嗦,越來越受到電子愛好者的推崇。高端學習板的設計也是越來越傾向這種風格。最小系統板對于使用者來說非常方便。

圖1.4 最小系統板

為什么選它?理想狀態(tài)下,最好的學習方式自然是讓初學者從搭建一個最小系統開始學習,但是那樣的話,需要初學者自己去選購、焊接元器件。焊接周期可能要幾個小時,如果焊接過程中出現問題,修改、調試會花費更多的時間,初學者的熱情很快就會被磨滅,這是編者不想看到的。而51最小系統板恰好解決了這個問題,它給了初學者一個完美的起步的平臺,在這個平臺上,你可以快速開始學習,驗證你的程序。

注意:如果自己購買的話,每家的最小系統板樣式可能多少會有一些不同,但是差別不大,因為整體架構都是一樣的。

1.3 軟件入門基礎

1.3.1 匯編語言與C語言的那些事

說到編程語言,免不了要把匯編語言與C語言放在一起比較。

什么是匯編語言?它是計算機語言的一種,屬于低級的計算機語言。說它低級,并不是因為它功能低級,而是有兩個原因,一是因為它出現在計算機發(fā)展的早期,二是拿它和C語言作比較,它屬于低級語言。同時因為它低級,所以很難被一般人掌握,需要一定的硬件基礎和計算機原理方面的知識。

什么是C語言?它是國際上廣泛流行的計算機高級語言。它的祖先是BCPL語言, 1967年BCPL語言誕生,1970年它被改進為B語言,1972—1973年,美國貝爾實驗室在B語言的基礎上設計出了C語言。它是如此美好,可以作為系統設計語言,編寫工作系統應用程序,也可以作為應用程序設計語言,編寫不依賴計算機硬件的應用程序。因此,它的應用范圍非常廣泛。

學習單片機到底是用匯編語言好還是C語言好?其實,社會早已給出了答案。最簡單的驗證方法是,打開招聘網站,輸入“單片機”這個關鍵字,看看每一家公司對這個職業(yè)的技能要求,相信只要不是特別奇葩的公司,都會要求你用C語言。

圖1.5是某招聘網上隨意點開的兩家公司的招聘信息,一家的任職要求是了解匯編語言,熟練使用C語言,另一家只提到了C語言,沒有提到匯編語言。

圖1.5 招聘網站搜索結果

首先,編者當年學單片機是從匯編語言開始的,但是使用了一個月后,老師就建議我們轉向了C語言。用我老師的話說,使用匯編語言,只是為了更好地理解單片機的底層架構,實際做項目還是要使用C語言。而且在那一個月里,我們確實被匯編語言折騰得很慘。

其次,匯編語言的缺點在哪里?移植性太差!就這一點就足夠了!開始工作后,你會發(fā)現工作中可能會用到多種單片機,例如有的時候用MSP430單片機,有的時候用PIC單片機。如果使用的是匯編語言,麻煩來了,因為這兩款單片機都有自己的匯編指令,幾乎是完全不一樣的。假設用PIC單片機實現了一款液晶屏的驅動和應用,想在MSP430單片機上實現同樣控制的時候,之前做的努力白費,依然需要從頭開始寫相關的控制程序。但如果是使用C語言,那就不一樣了,驅動層的程序肯定需要重寫,但是應用層的程序幾乎不需要做變動,拿來就能用,而且?guī)缀跛械膯纹瑱C編譯器都支持C語言。

最后,優(yōu)勝劣汰。市場大環(huán)境已經決定了這一點,可能老項目維護會繼續(xù)使用匯編語言,前提是老項目就是用匯編做的。但是大部分公司做新項目都是用C語言,用匯編語言的比較少。像編者工作的第一家公司,他的老項目是用匯編語言做的,進去以后也僅僅是修補之前的缺陷。而且有的同事擔心后續(xù)的維護工作不好進行,已經開始進行程序的重寫了,就是說重新寫一套C語言的代碼,替換之前的匯編語言的程序。編者看了他寫的一部分程序,代碼簡潔、易讀,相比匯編語言,維護起來太容易了。

比較尷尬的一點就是,一些學校依然在使用匯編語言作為單片機的編程語言。可能是因為對這個行業(yè)的了解程度還處于十幾年前,也可能是懶得更新教程,導致學生花費大量的時間去學習一些今后幾乎用不到的編程語言,這是非常可惜的一件事。

1.3.2 C語言入門五式

“工欲善其事,必先利其器。”講了那么多的理論,從現在開始講點實用的。雖然單片機的入門門檻很低,但是有些東西是必然要掌握的。先從C語言的5個常用語句開始。

(1)i=1;賦值語句。

(2)if…else條件語句。

(3)for循環(huán)語句。

(4)while循環(huán)語句。

(5)switch…case多分支選擇語句。

第一說賦值語句。從小學學習1+1=2開始,“=”這個符號就一直陪伴著我們,它的含義也一直沒變過。但是,到了C語言這里就全然不同了。在C語言中“=”的意義是賦值,顧名思義,把一個值賦予變量或者其他的量。賦值語句是把“=”右邊的那個值或者說一個數賦給“=”左邊的變量。例如,a的值為20,經過如下語句,a變成了多少?

        a = 1;

經過上面的語句后,a現在的值是1。

再如,a的值為20, b的值為2,經過如下語句,a變成了多少?

        a= b;

經過上面的語句后,a現在的值是2。有沒有覺得神奇而又簡單?

第二是if…else條件語句。學過初中英語的人都知道,if的意思是如果,else的意思是否則。這個語句也很好理解:如果if后面的括號里的條件是真的,那么執(zhí)行if后面的語句,否則執(zhí)行else后面的語句,就是說if和else后面的語句只能執(zhí)行一種。

例如,a的值為1,經過如下語句,b變成了多少?

        if(a==1)                           //判斷a是否等于1
            b=1;
        else
            b=0;

剛剛知道“=”在C語言中是賦值的意思,又出來一個“==”,什么情況?不要慌,還記得“=”原來的意思嗎?不錯,就是等于。所以,在表達式a==1中進行的是一個判斷:如果a等于1成立,那么執(zhí)行if后面的語句;如果a等于1不成立,則執(zhí)行else后面的指令。所以,執(zhí)行完上面的指令,b等于1。

第三,for循環(huán)語句。它進行的也是一個判斷,為什么說它是循環(huán)語句?因為只要括號內的條件滿足,它會一直執(zhí)行下去。例如:

        for(i=0 ; i<10; i=i+1)               //當i小于10的時候,a等于1
        {
            a=1;
        }
        a=0; //當i大于或等于 10的時候,a等于0

在上述代碼中,先解讀一下for(i=0; i=i+1; i<10)這個語句,它的執(zhí)行過程如下:

(1)把整數0賦值給變量i。

(2)在i等于0的情況下,判斷i<10是否正確。0<10當然正確,然后執(zhí)行大括號里面的指令a=1; ,然后執(zhí)行第(3)步。

(3)執(zhí)行i=i+1。在這里,i等于0,0加1等于1,然后把1賦值給i,所以得到的結果就是i等于1。

(4)跳回到第(2)步繼續(xù)進行判斷。此時i等于1, i<10依然正確,繼續(xù)執(zhí)行大括號里面的指令,然后執(zhí)行第(3)步。依次循環(huán),一直到i等于10,此時i<10不成立,不執(zhí)行大括號里面的指令,跳出循環(huán),執(zhí)行第(5)步。

(5)循環(huán)結束,執(zhí)行for語句下面的指令,也就是a=0;執(zhí)行完了之后,a的值又變成了0。

以上就是for語句的工作流程。如果你覺得簡單,說明你悟性很高;如果覺得有點難也沒有關系,在后面的實戰(zhàn)里可以邊用邊學。

第四,while循環(huán)語句。for語句是循環(huán)語句,while語句也是循環(huán)語句,主要的區(qū)別在于for語句的表達式多一些。while語句的一般形式如下:

        while(表達式)
        {
            語句
        }

只要表達式成立,while語句會一直執(zhí)行下去。例如,a的值為1,執(zhí)行以下語句:

        while(a<100)
        {
            a=a+1;
        }

在上述指令中,解讀一下while(a<100)這個語句,它的執(zhí)行過程如下:

(1)判斷a<100是否成立,因為當前條件下a的值為1,所以a<100肯定成立。

(2)執(zhí)行a=a+1; ,因為當前條件下a的值為1,1加1等于2。

(3)跳回步驟(1),此時a的值為2,所以a<100肯定成立。如此循環(huán),一直到a的值為100。此時a<100不成立,跳出循環(huán),執(zhí)行while語句后面的語句。

以上即為while語句的執(zhí)行過程。在實際應用中,你會發(fā)現它的用途非常廣,使用方法也非常簡單。

第五,switch…case多分支選擇語句。其實if語句也是分支選擇語句,只不過它只有兩個分支,而switch語句里面可以有很多分支。它的一般形式如下:

        switch(表達式)
        {
            case 常量 1:語句 1
            case 常量2:語句2
            …
            case 常量n:語句n
            default:    語句n+1
        }

它的執(zhí)行方式也很簡單,先計算括號里面的表達式,用計算出的值和每一個case后面的常量進行比較,如果相等,那么執(zhí)行后面的語句。在這個過程中,它只能或者跟一個case后面的常量相等,然后執(zhí)行后面的語句,或者都不相等,執(zhí)行default后面的語句,不會出現執(zhí)行兩個case后面的語句的情況。例如a的值為3,如下所示,執(zhí)行完之后b等于多少?

        switch(a)
        {
            case 1:b=a+1; break;
            case 2:b=a+2; break;
            case 3:b=a+3; break;
            case 4:b=a+4; break;
            default:b=a; break;
        }

在上述指令中,switch語句執(zhí)行的流程如下:

(1)判斷括號內的值是多少,通過已知條件,可知a的值為3。

(2)將a與case后面的值進行比較。a與1進行比較,不相等。

(3)a與2進行比較,不相等。

(4)a與3進行比較,相等。執(zhí)行其后面的語句b=a+3; , a的值為3,3加3等于6,所以b的值為6。然后執(zhí)行break語句,該語句可以使程序跳出switch的結構。

注意:每個case語句后面都要跟一個break,用來跳出switch的結構。

switch語句的使用量相比前面幾個略少,但是依舊是最常用的幾個語句之一。學習的時候可以把它和if語句放在一起,便于理解和區(qū)分。

以上就是單片機C語言中最常用的5個語句。編者盡量把它們寫得簡單一些,以免大家理解上有困難。而且,本書的目的是讓大家入門,并不是成為C語言的高手,所以內容上盡量精簡。如果學完本書,真的激發(fā)了你的學習熱情,可以買一本譚浩強老師的《C程序設計》,在那本書中,讀者會學到很多高大上的技能。現在還是跟編者快快樂樂地玩單片機吧!

1.3.3 加減乘除

本節(jié)內容相對簡單很多,因為大部分都是借用數學運算中的符號和方法,只需要把賦值的理念結合一下就可以了。C語言中的常用運算符號如表1.1所示。

表1.1 常用運算符號

估計大家看到這里長長地出了一口氣,原來C語言的加減乘除運算這么簡單,跟數學里面的差不多嘛。但是,可能多少還是會有疑問。

:等等,9除以4為什么等于2?應該是2.25啊!

:因為存儲結果的a為整型變量,簡單理解,就是它只能進行整數的存儲,小數點后面的數全都丟棄。

:無符號整型變量是什么意思?聽起來很神秘啊!

:這個在后面實戰(zhàn)的時候會講給你,現在只要知道就好。

一般來說,在C語言的計算過程中,加法和減法用得多一些,乘法和除法因為受到運算速度的限制而用得少,或者用移位的方式來實現相應的結果。

1.3.4 數制三變

什么是數制?用一組固定的數字和一套統一的規(guī)則來表示數字的方法,就叫做數制。

:什么!沒聽懂?好吧,舉個例子,從0開始,一個一個的數字往上寫,1、2、3一直到9,下一個數字是多少?

路人甲:當然是“10”啊!

:Good boy!不錯,這就是數制的一種:十進制,逢十進一!小學的時候老師有沒有講過?

路人甲:這么一說,好像有點印象。那你今天講的“數制三變”是啥意思?

:意思是說,在寫程序的時候,不光要用到十進制,還有兩種常用的數制:二進制和十六進制!這三種數制是C語言編程的時候較為常用的,啥?八進制?那個用得不多,暫時不用考慮。

路人甲:好麻煩地說,不學了,我還是安靜地做一個美男子吧!

其實數制是非常簡單的。二進制,顧名思義,逢二進一;十六進制,逢十六進一。所有的秘密都在表1.2中一覽無余!

表1.2 十進制、二進制與十六進制換算

怎么樣,看到這個表格后,對這3種數制直接的關系是不是更了解了?十進制的數字5就是二進制的數字101,十進制的數字7就是二進制的數字111……十進制的數字5對應的二進制數101和十進制的數字101一模一樣,這讓人怎么區(qū)分?

不用擔心,當然有辦法區(qū)分!以賦值為例,把一個同樣大小的數字的十進制、二進制、十六進制數分別賦給一個變量a,語句如下:

        a = 10; //十進制
        a = 0B1010; //二進制
        a = 0xA; //十六進制

通過在二進制數和十進制數前面添加符號的方式,可以輕易區(qū)分這3種數制的區(qū)別。如果想把一個十進制數換算成二進制數或者十六進制數,該怎么換算?可以使用Windows自帶的計算器,它有一項非常方便的功能,就是數制轉換,例如編者使用的是Win7系統,打開以后如圖1.6所示,選擇“查看”→“程序員”菜單命令,界面如圖1.7所示,數制默認為十進制。

圖1.6 計算器初始頁面和計算器類型選擇頁面

圖1.7 十進制、十六進制和二進制的相互轉換

在該界面下輸入10,然后選擇“十六進制”單選按鈕,看看數字變成了多少?轉換二進制也是一樣,通過這種方式可以實現這3種數制的任意切換。更多功能不作介紹,大家可以自己去摸索!

1.3.5 與或反

1.3.3節(jié)講到了關系運算符加減乘除,本節(jié)主要介紹邏輯運算符。在單片機的C語言中,主要有3種邏輯運算:與操作(&)、或操作(|)、取反操作(~)。這3種運算都是進行位運算。在邏輯運算中,0代表假,非0代表真。例如,0是假,1是真,3是真,254也是真。

首先說與操作,與表示兩個值作比較時,如果都為真,那么結果為真,只要有一方為假,那么結果為假。它的運算符是“&”,有的時候用一個符號&,有的時候用兩個符號 &&,有什么區(qū)別?

例如,a=0B10101111, b=0B11000011, a&b的意思是讓a的每一位和b進行與操作,稱為“按位與”,運算過程如圖1.8所示,得到的結果是0B10000011。

圖1.8 與操作運算

如果是a&&b,是對整個數值進行判斷。a 的值是0B10101111,非零;b 的值是0B11000011,非零。兩個真值相與,結果為1。

然后是或操作,它的運算符是“|”,表示兩個值按位進行比較,只要有一方是1,那么那一位得到的結果就是1。例如,依然是a=0B10101111, b=0B11000011, a|b的運算過程如圖1.9所示,得到的結果是0B11101111。

圖1.9 或操作運算

如果是a||b,也是對整個數值進行判斷,只要有其中一方非零,那么結果就是1。

最后是取反操作,它的運算符是“~”,聽名字就知道,它是進行取反操作。和與、或操作不同,取反的操作對象只有一個,即把被操作數按照二進制的格式展開,逐位取反。例如, a=0B10101111,取反之后再次把值賦給a:

        a = ~a;

運算過程如圖1.10所示,得到的結果是0B01010000,可以發(fā)現,結果的每一位都和原先的值相反。

圖1.10 取反操作運算

1.3.6 常用數據類型與大小

前面曾經提到過,89C51單片機程序存儲空間為4KB,這個KB到底是什么?它是描述計算機數據大小的一種單位。在計算機中,要處理的數據有大有小,它們是怎么分類的?又是怎么存放的?

先說B,它是byte的縮寫,中文意思是字節(jié),在C語言中是存儲空間的基本計量單位,通常是一個8位的二進制數。2的8次方等于256,因此一個字節(jié)可以表示256個數。

再看K。在常用的計量單位中,k表示千的意思,例如1km=1000m,1kg=1000g。在C語言中略有不同,1KB=1024B, K也就是2的十次方。

而無論是B還是KB,都是描述單位或者大小的,而真正起到分類作用的是各種各樣的數據類型。什么是數據類型?數據的格式通常稱為數據類型。標準的C語言的數據類型可分為基本數據類型和組合數據類型,組合數據類型由基本數據類型構造而成。另外,C51中還有專門針對MCS-51單片機的特殊功能寄存器型和位類型。表1.3為Keil C51編譯器能夠識別的基本數據類型。

表1.3 數據類型

在51單片機中較為常用的是sbit、unsigned char和unsigned int。這些數據類型到底怎么用?后面的章節(jié)會詳細說明。除了常用的幾個數據類型外,這個表格不需要大家背下來,只要用的時候查一下就行。

1.4 單片機資料準備

51單片機入門要準備的資料很簡單,手上有一本芯片的datasheet就行了。為什么不提教科書?那里面說的貌似還沒有datasheet詳細。本書里選中的芯片型號是STC89C52RC,接下來要先找到它的datasheet。

1.4.1 找到datasheet

很多人習慣一上來就百度“STC89C52RC datasheet”,并不是說這樣不好,而是思路有些問題。百度是一個幾乎什么都有的地方,什么都有就意味著你什么都能找到,但是同時也意味著你找到的可能不是真的。關于查找資料的方法后面會有專門的章節(jié)解釋,這里只說如何找官方的datasheet。

第一步,STC89C52RC的生產廠家是STC公司,那么需要先找到STC公司的官網。百度搜索“STC單片機官網”或者“STC官網”,得到的結果如圖1.11所示。

圖1.11 STC單片機官網

如圖1.11所示,這是需要的結果,官方網站為www.stcmcu.com。

第二步,打開網站,向下拖動頁面,注意網站的右側。當出現“STC89C51/52/54/58/516系列用戶手冊”時停下,如圖1.12所示,這就是STC89C52的datasheet,也就是用戶手冊。單擊該鏈接,在彈出的頁面中,瀏覽器會自動保存該用戶手冊,若保存速度很慢,可使用迅雷或其他下載工具進行保存。

圖1.12 數據手冊下載位置

到了這一步,就找到了官方發(fā)布的關于單片機的datasheet。大家要記住,無論找什么芯片,思路都是先確定該芯片的生產廠家,然后找到廠家的官方網站,最后在網站內查找所需的資料。

直接在百度中搜索不好嗎?個人不建議這樣做,因為百度就好像一個圖書市場,有正規(guī)出版發(fā)行的圖書,也有盜版圖書,還有一些自費印制的小冊子,什么都可能找到。如果直接搜索,很難保證找到的資料是最新的或者是修改過的。

而datasheet就如同一款芯片的使用說明,如果說明書都出錯,就很難知道它怎么用了。

1.4.2 認識STC89C52

圖1.13分別是STC89C52的實物圖和原理圖。

圖1.13 STC89C52的實物圖、原理圖

先看左側的實物圖,前兩行字符為89C52RC和40I-PDIP40,這表示什么意思?這里就體現出datasheet的價值了,打開剛下載的datasheet,第19頁1.5節(jié)為STC89C52系列單片機的命名規(guī)則,通過命名規(guī)則可以知道:

● 該單片機為8051系列。

● 工作電壓為3.8~5.5V。

● 程序存儲空間8KB, RAM空間512B。

● 工作頻率可達到40MHz。

● 工業(yè)級,工作溫度為-40~+80℃。

● 封裝類型是PDIP。

● 引腳數量是40。

第三行字符為該芯片的生產信息,例如生產日期、批次等。

再看圖1.13右側的原理圖,得知它有40個引腳,這些引腳從1~40按照逆時針的順序從芯片的左上角開始向下,再從右側從下往上到右上角。為了讓用戶在焊接或調試的時候快速找到1腳,在1腳和40腳中間放置了一個半圓形的標記。其他類型的芯片也會有相同或類似的標記告訴用戶1腳在什么位置。

STC89C52單片機有4組引腳:P0、P1、P2、P3,每一組有8個引腳。這32個I/O可以通過芯片內部的寄存器進行控制。

其余8個引腳如下:

● 9腳為復位引腳RST,可以通過輸入高電平來實現芯片的復位。

● 20腳與40腳分別為GND和VCC,接電源的負極和正極,通過這兩個引腳給單片機供電。

● 18腳與19腳為時鐘引腳,通常外接時鐘電路。

● 29腳(PSEN)為外部程序存儲器選通引腳,當使用外部程序存儲器的時候,該引腳負責輸出選通信號。使用內部程序存儲器的時候不用理會該引腳。

● 30腳(ALE)輸出地址鎖存允許信號。上電后該引腳持續(xù)輸出正脈沖信號,可通過檢測信號的方式來判斷單片機是否正常運行。

● 31腳(EA)為內外程序存儲器選擇引腳。當使用內部程序存儲器時,該引腳接高電平;使用外部程序存儲器時,該引腳接低電平。

除上述功能以外,大部分引腳還有第二功能。這些第二功能有的不常用,只要看一下datasheet有個初步了解即可;有的較復雜,會在后面的章節(jié)里講解。

1.4.3 STC89C52與AT89S52

初學者經常會被幾個單片機型號所困擾,例如STC89C51、STC89C52、AT89C51、AT89C52、AT89S51、AT89S52。它們之間到底有什么區(qū)別和聯系?

先說51與52。51表示單片機的ROM大小為4KB,有兩個定時器/計數器;52表示單片機的ROM大小為8KB,有3個定時器/計數器。這是最主要的區(qū)別。

那么STC與AT又是什么?它們分別是兩家不同的單片機生產廠家:STC單片機(官方網站http://www.stcmcu.com/)與ATMEL單片機(官方網站http://www.atmel.com/)。就像前面說的,Intel公司把內核技術轉讓給了幾個單片機廠家,它們在各自的基礎上對單片機進行了一些修改。最明顯的區(qū)別是,STC89C52的RAM有512B, AT89S52的RAM只有256B。目前來說,市場上入門用的51單片機以這兩家為主。

那么AT89C52與AT89S52又有什么區(qū)別?它們的主要區(qū)別是,AT89C52需要用并行編程器下載程序,編程電壓12V; AT89S52支持在線編程,使用P1口的5、6、7引腳,編程電壓為5V,當然AT89S52也支持和AT89C52一樣的編程方式。由此可見,AT89S52比AT89C52更加便捷。

本書中為什么選取STC89C52作為學習用的單片機呢?這兩種單片機價格上差別不大。而在下載線的價格上,ATMEL要比STC的貴兩元左右。更主要的是,進行UART口通信時,AT89S52還需要一條單獨的串口線以及電平轉換電路;而STC的單片機的一條下載線既可以用于程序下載,又可以用于串口通信,一舉兩得。

主站蜘蛛池模板: 龙南县| 常山县| 崇文区| 于都县| 桐庐县| 佛学| 诸暨市| 秦安县| 黔江区| 滁州市| 百色市| 汉寿县| 石家庄市| 聂拉木县| 福泉市| 句容市| 尼玛县| 什邡市| 阿荣旗| 和硕县| 玉环县| 长岛县| 集安市| 靖州| 慈溪市| 弥勒县| 舞钢市| 广德县| 惠安县| 宁阳县| 昌吉市| 连南| 城口县| 庐江县| 遵化市| 巫溪县| 鹤峰县| 当雄县| 东至县| 建始县| 曲沃县|