平凡老師單片機(jī)教程



《平凡老師單片機(jī)教程》由會員分享,可在線閱讀,更多相關(guān)《平凡老師單片機(jī)教程(57頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
1、 原作: 平凡的單片機(jī) 單片機(jī)教程第一課:單片機(jī)概述 1、何謂單片機(jī) 一臺能夠工作的計(jì)算機(jī)要有這樣幾個(gè)部份構(gòu)成:CPU(進(jìn)行運(yùn)算、控制)、RAM(數(shù)據(jù)存儲)、ROM(程序存儲)、輸入/輸出設(shè)備(例如:串行口、并行輸出口等)。在個(gè)人計(jì)算機(jī)上這些部份被分成若干塊芯片,安裝一個(gè)稱之為主板的印刷線路板上。而在單片機(jī)中,這些部份,全部被做到一塊集成電路芯片中了,所以就稱為單片(單芯片)機(jī),而且有一些單片機(jī)中除了上述部份外,還集成了其它部份如A/D,D/A等。 天!PC中的CPU一塊就要賣幾千塊錢,這么多東西做在一起,還不得
2、買個(gè)天價(jià)!再說這塊芯片也得非常大了。 不,價(jià)格并不高,從幾元人民幣到幾十元人民幣,體積也不大,一般用40腳封裝,當(dāng)然功能多一些單片機(jī)也有引腳比較多的,如68引腳,功能少的只有10多個(gè)或20多個(gè)引腳,有的甚至只8只引腳。為什么會這樣呢? 功能有強(qiáng)弱,打個(gè)比方,市場上面有的組合音響一套才賣幾百塊錢,可是有的一臺功放機(jī)就要賣好幾千。另外這種芯片的生產(chǎn)量很大,技術(shù)也很成熟,51系列的單片機(jī)已經(jīng)做了十幾年,所以價(jià)格就低了。 既然如此,單片機(jī)的功能肯定不強(qiáng),干嗎要學(xué)它呢? 話不能這樣說,實(shí)際工作中并不是任何需要計(jì)算機(jī)的場合都要求計(jì)算機(jī)有很高的性能,一個(gè)控制電冰箱溫度的計(jì)算機(jī)難道要用PIII?應(yīng)用的關(guān)鍵是看
3、是否夠用,是否有很好的性能價(jià)格比。所以8051出來十多年,依然沒有被淘汰,還在不斷的發(fā)展中。 2、MCS51單片機(jī)和8051、8031、89C51等的關(guān)系我們平常老是講8051,又有什么8031,現(xiàn)在又有89C51,它們之間究竟是什么關(guān)系? MCS51是指由美國INTEL公司(對了,就是大名鼎鼎的INTEL)生產(chǎn)的一系列單片機(jī)的總稱,這一系列單片機(jī)包括了好些品種,如8031,8051,8751,8032,8052,8752等,其中8051是最早最典型的產(chǎn)品,該系列其它單片機(jī)都是在8051的基礎(chǔ)上進(jìn)行功能的增、減、改變而來的,所以人們習(xí)慣于用8051來稱呼MCS51系列單片機(jī),而8031是前
4、些年在我國最流行的單片機(jī),所以很多場合會看到8031的名稱。INTEL公司將MCS51的核心技術(shù)授權(quán)給了很多其它公司,所以有很多公司在做以8051為核心的單片機(jī),當(dāng)然,功能或多或少有些改變,以滿足不同的需求,其中89C51就是這幾年在我國非常流行的單片機(jī),它是由美國ATMEL公司開發(fā)生產(chǎn)的。以后我們將用89C51來完成一系列的實(shí)驗(yàn)。 單片機(jī)教程第二課:單片機(jī)的部、外部結(jié)構(gòu)(一) 一、單片機(jī)的外部結(jié)構(gòu) 拿到一塊芯片,想要使用它,首先必須要知道怎樣連線,我們用的一塊稱之為89C51的芯片,下面我們就看一下如何給它連線。 1、 電源:這當(dāng)然是必不可少的了。單片機(jī)使用的是5V電源,其中正極
5、接40引腳,負(fù)極(地)接20引腳。 2、 振蒎電路:單片機(jī)是一種時(shí)序電路,必須提供脈沖信號才能正常工作,在單片機(jī)部已集成了振蕩器,使用晶體振蕩器,接18、19腳。只要買來晶振,電容,連上就可以了,按圖1接上即可。 3、 復(fù)位引腳:按圖1中畫法連好,至于復(fù)位是何含義與為何需要復(fù)要復(fù)位,在單片機(jī)功能中介紹。 4、 EA引腳:EA引腳接到正電源端。 至此,一個(gè)單片機(jī)就接好,通上電,單片機(jī)就開始工作了。 我們的第一個(gè)任務(wù)是要用單片機(jī)點(diǎn)亮一只發(fā)光二極管LED,顯然,這個(gè)LED必須要和單片機(jī)的某個(gè)引腳相連,否則單片機(jī)就沒法控制它了,那么和哪個(gè)引腳相連呢?單片機(jī)上除了剛才用掉的5個(gè)引腳,還有35個(gè),我們將
6、這個(gè)LED和1腳相連。(見圖1,其中R1是限流電阻) 按照這個(gè)圖的接法,當(dāng)1腳是高電平時(shí),LED不亮,只有1腳是低電平時(shí),LED才發(fā)亮。因此要1腳我們要能夠控制,也就是說,我們要能夠讓1引腳按要求變?yōu)楦呋虻碗娖?。即然我們要控?腳,就得給它起個(gè)名字,總不能就叫它一腳吧?叫它什么名字呢?設(shè)計(jì)51芯片的INTEL公司已經(jīng)起好了,就叫它P1.0,這是規(guī)定,不可以由我們來更改。 圖1 名字有了,我們又怎樣讓它變'高'或變'低'呢?叫人做事,說一聲就可以,這叫發(fā)布命令,要計(jì)算機(jī)做事,也得要向計(jì)算機(jī)發(fā)命令,計(jì)算機(jī)能聽得懂的命令稱之為計(jì)算機(jī)的指令。讓一個(gè)引腳輸出高電平的指令是SETB,讓一個(gè)引腳
7、輸出低電平的指令是CLR。因此,我們要P1.0輸出高電平,只要寫SETB P1.0,要P1.0輸出低電平,只要寫 CLR P1.0就可以了。 現(xiàn)在我們已經(jīng)有辦法讓計(jì)算機(jī)去將P10輸出高或低電平了,但是我們怎樣才能計(jì)算機(jī)執(zhí)行這條指令呢?總不能也對計(jì)算機(jī)也說一聲了事吧。要解決這個(gè)問題,還得有幾步要走。第一,計(jì)算機(jī)看不懂SETB CLR之類的指令,我們得把指令翻譯成計(jì)算機(jī)能懂的方式,再讓計(jì)算機(jī)去讀。計(jì)算機(jī)能懂什么呢?它只懂一樣?xùn)|西——數(shù)字。因此我們得把SETB P1.0變?yōu)椋―2H,90H ),把CLR P1.0變?yōu)?(C2H,90H ),至于為什么是這兩個(gè)數(shù)字,這也是由51芯片的設(shè)計(jì)者--INT
8、EL規(guī)定的,我們不去研究。第二步,在得到這兩個(gè)數(shù)字后,怎樣讓這兩個(gè)數(shù)字進(jìn)入單片機(jī)的部呢?這要借助于一個(gè)硬件工具"編程器"。 我們將編程器與電腦連好,運(yùn)行編程器的軟件,然后在編緝區(qū)寫入(D2H,90H)見圖2,寫入……好,拿下片子,把片子插入做好的電路板,接通電源……什么?燈不亮?這就對了,因?yàn)槲覀儗戇M(jìn)去的指令就是讓圖2 P10輸出高電平,燈當(dāng)然不亮,要是亮就錯了?,F(xiàn)在我們再撥下這塊芯片,重新放回到編程器上,將編緝區(qū)的容改為(C2H,90H),也就是CLR P1.0,寫片,拿下片子,把片子插進(jìn)電路板,接電,好,燈亮了。因?yàn)槲覀儗懭氲模ǎ┚褪亲孭10輸出低電平的指令。這樣我們看到,硬件電路的連
9、線沒有做任何改變,只要改變寫入單片機(jī)中的容,就可以改變電路的輸出效果。 三、單片機(jī)部結(jié)構(gòu)分析 我們來思考一個(gè)問題,當(dāng)我們在編程器中把一條指令寫進(jìn)單片要部,然后取下單片機(jī),單片機(jī)就可以執(zhí)行這條指令,那么這條指令一定保存在單片機(jī)的某個(gè)地方,并且這個(gè)地方在單片機(jī)掉電后依然可以保持這條指令不會丟失,這是個(gè)什么地方呢?這個(gè)地方就是單片機(jī)部的只讀存儲器即ROM(READ ONLY MEMORY)。為什么稱它為只讀存儲器呢?剛才我們不是明明把兩個(gè)數(shù)字寫進(jìn)去了嗎?原來在89C51中的ROM是一種電可擦除的ROM,稱為FLASH ROM,剛才我們是用的編程器,在特殊的條件下由外部設(shè)備對ROM進(jìn)行寫的操作,在
10、單片機(jī)正常工作條件下,只能從那面讀,不能把數(shù)據(jù)寫進(jìn)去,所以我們還是把它稱為ROM。 單片機(jī)教程第三課:幾個(gè)基本概念 數(shù)的本質(zhì)和物理現(xiàn)象。 我們知道,計(jì)算機(jī)可以進(jìn)行數(shù)學(xué)運(yùn)算,這可令我們非常的難以理解,計(jì)算機(jī)嗎,我們雖不了解它的組成,但它總只是一些電子元器件,怎么可以進(jìn)行數(shù)學(xué)運(yùn)算呢?我們做數(shù)學(xué)題如37+45是這樣做的,先在紙上寫37,然后在下面寫45,然后大腦運(yùn)算,最后寫出結(jié)果,運(yùn)算的原材料:37、45和結(jié)果:82都是寫在紙上的,計(jì)算機(jī)中又是放在什么地方呢?為了解決這個(gè)問題,先讓我們做一個(gè)實(shí)驗(yàn):這里有一盞燈,我們知道燈要么亮,要么不亮,就有兩種狀態(tài),我們可以用’0’和’1’來代替這兩種狀態(tài)
11、,規(guī)定亮為’1’,不亮為’0’?,F(xiàn)在放上兩盞燈,一共有幾種狀態(tài)呢?我們列表來看一下: 狀態(tài) 表達(dá) 0 0 0 1 1 0 1 1 請大家自已寫上3盞燈的情況000 001 010 011 100 101 110 111 我們來看,這個(gè)000,001,101 不就是我們學(xué)過的的二進(jìn)制數(shù)嗎?本來,燈的亮和滅只是一種物理現(xiàn)象,可當(dāng)我們把它們按一按的順序排更好后,燈的亮和滅就代表了數(shù)字了。讓我們再抽象一步,燈為什么會亮呢?看電路1,是因?yàn)檩敵鲭娐份敵龈唠娖剑o燈通了電。因此,燈亮和滅就可以用電路的輸出是高電平還是低電平來替代了。這樣,數(shù)字就和電平的高、低聯(lián)系上了
12、。(請想一下,我們還看到過什么樣的類似的例子呢?(海軍之)燈語、旗語,電報(bào),甚至紅、綠燈) 位的含義: 通過上面的實(shí)驗(yàn)我們已經(jīng)知道:一盞燈亮或者說一根線的電平的高低,可以代表兩種狀態(tài):0和1。實(shí)際上這就是一個(gè)二進(jìn)制位,因此我們就把一根線稱之為一“位”,用BIT表示。 字節(jié)的含義: 一根線可以表于0和1,兩根線可以表達(dá)00,01,10,11四種狀態(tài),也就是可以表于0到3,而三根可以表達(dá)0-7,計(jì)算機(jī)常用8根線放在一起,同時(shí)計(jì)數(shù),就可以表過到0-255一共256種狀態(tài)。這8根線或者8位就稱之為一個(gè)字節(jié)(BYTE)。不要問我為什么是8根而不是其它數(shù),因?yàn)槲乙膊恢?。(?jì)算機(jī)世界是一個(gè)人造的世
13、界,不是自然界,很多事情你無法問為什么,只能說:它是一種規(guī)定,大家在以后的學(xué)習(xí)過程中也要注意這個(gè)問題) 存儲器的工作原理: 1、存儲器構(gòu)造 存儲器就是用來存放數(shù)據(jù)的地方。它是利用電平的高低來存放數(shù)據(jù)的,也就是說,它存放的實(shí)際上是電平的高、低,而不是我們所習(xí)慣認(rèn)為的1234這樣的數(shù)字,這樣,我們的一個(gè)謎團(tuán)就解開了,計(jì)算機(jī)也沒什么神秘的嗎。 圖2 圖3 讓我們看圖2。這是一個(gè)存儲器的示意圖:一個(gè)存儲器就象一個(gè)個(gè)的小抽屜,一個(gè)小抽屜里有八個(gè)小格子,每個(gè)小格子就是用來存放“電荷”的,電荷通過與它相連的電線傳進(jìn)來或釋放掉,至于電荷在小格子里是怎樣存的,就不用我們操心了,你可以把電線想象成水管
14、,小格子里的電荷就象是水,那就好理解了。存儲器中的每個(gè)小抽屜就是一個(gè)放數(shù)據(jù)的地方,我們稱之為一個(gè)“單元”。 有了這么一個(gè)構(gòu)造,我們就可以開始存放數(shù)據(jù)了,想要放進(jìn)一個(gè)數(shù)據(jù)12,也就是00001100,我們只要把第二號和第三號小格子里存滿電荷,而其它小格子里的電荷給放掉就行了(看圖3)??墒菃栴}出來了,看圖2,一個(gè)存儲器有好多單元,線是并聯(lián)的,在放入電荷的時(shí)候,會將電荷放入所有的單元中,而釋放電荷的時(shí)候,會把每個(gè)單元中的電荷都放掉,這樣的話,不管存儲器有多少個(gè)單元,都只能放同一個(gè)數(shù),這當(dāng)然不是我們所希望的,因此,要在結(jié)構(gòu)上稍作變化,看圖2,在每個(gè)單元上有個(gè)控制線,我想要把數(shù)據(jù)放進(jìn)哪個(gè)單元,就給一
15、個(gè)信號這個(gè)單元的控制線,這個(gè)控制線就把開關(guān)打開,這樣電荷就可以自由流動了,而其它單元控制線上沒有信號,所以開關(guān)不打開,不會受到影響,這樣,只要控制不同單元的控制線,就可以向各單元寫入不同的數(shù)據(jù)了,同樣,如果要某個(gè)單元中取數(shù)據(jù),也只要打開相應(yīng)的控制開關(guān)就行了。 2、存儲器譯碼 那么,我們怎樣來控制各個(gè)單元的控制線呢?這個(gè)還不簡單,把每個(gè)單元元的控制線都引到集成電路的外面不就行了嗎?事情可沒那么簡單,一片27512存儲器中有65536個(gè)單元,把每根線都引出來,這個(gè)集成電路就得有6萬多個(gè)腳?不行,怎么辦?要想法減少線的數(shù)量。我們有一種方法稱這為譯碼,簡單介紹一下:一根線可以代表2種狀態(tài),2根線可
16、以代表4種狀態(tài),3根線可以代表幾種,256種狀態(tài)又需要幾根線代表?8種,8根線,所以65536種狀態(tài)我們只需要16根線就可以代表了。 3、存儲器的選片與總線的概念 至此,譯碼的問題解決了,讓我們再來關(guān)注另外一個(gè)問題。送入每個(gè)單元的八根線是用從什么地方來的呢?它就是從計(jì)算機(jī)上接過來的,一般地,這八根線除了接一個(gè)存儲器之外,還要接其它的器件,如圖4所示。這樣問題就出來了,這八根線既然不是存儲器和計(jì)算機(jī)之間專用的,如果總是將某個(gè)單元接在這八根線上,就不好了,比如這個(gè)存儲器單元中的數(shù)值是0FFH另一個(gè)存儲器的單元是00H,那么這根線到底是處于高電平,還是低電平?豈非要打架看誰歷害了?所以我們要讓它
17、們分離。辦法當(dāng)然很簡單,當(dāng)外面的線接到集成電路的引腳進(jìn)來后,不直接接到各單元去,中間再加一組開關(guān)(參考圖4)就行了。平時(shí)我們讓開關(guān)打開著,如果確實(shí)是要向這個(gè)存儲器中寫入數(shù)據(jù),或要從存儲器中讀出數(shù)據(jù),再讓開關(guān)接通就行了。這組開關(guān)由三根引線選擇:讀控制端、寫控制端和片選端。要將數(shù)據(jù)寫入片中,先選中該片,然后發(fā)出寫信號,開關(guān)就合上了,并將傳過來的數(shù)據(jù)(電荷)寫入片中。如果要讀,先選中該片,然后發(fā)出讀信號,開關(guān)合上,數(shù)據(jù)就被送出去了。注意圖4,讀和寫信號同時(shí)還接入到另一個(gè)存儲器,但是由于片選端不同,所以雖有讀或?qū)懶盘枺珱]有片選信號,所以另一個(gè)存儲器不會“誤會”而開門,造成沖突。那么會不同時(shí)選中兩片芯
18、片呢?只要是設(shè)計(jì)好的系統(tǒng)就不會,因?yàn)樗怯捎?jì)算控制的,而不是我們?nèi)藖砜刂频?,如果真的出現(xiàn)同時(shí)出現(xiàn)選中兩片的情況,那就是電路出了故障了,這不在我們的討論之列。 從上面的介紹中我們已經(jīng)看到,用來傳遞數(shù)據(jù)的八根線并不是專用的,而是很多器件大家共用的,所以我們稱之為數(shù)據(jù)總線,總線英文名為BUS,總即公交車道,誰者可以走。而十六根地址線也是連在一起的,稱之為地址總線。 半導(dǎo)體存儲器的分類 按功能可以分為只讀和隨機(jī)存取存儲器兩大類。所謂只讀,從字面上理解就是只可以從里面讀,不能寫進(jìn)去,它類似于我們的書本,發(fā)到我們手回之后,我們只能讀里面的容,不可以隨意更改書本上的容。只讀存儲器的英文縮寫為ROM(R
19、EAD ONLY MEMORY) 所謂隨機(jī)存取存儲器,即隨時(shí)可以改寫,也可以讀出里面的數(shù)據(jù),它類似于我們的黑板,我可以隨時(shí)寫東西上去,也可以用黑板擦擦掉重寫。隨機(jī)存儲器的英文縮寫為RAM(READ RANDOM MEMORY)這兩種存儲器的英文縮寫一定要記牢。 注意:所謂的只讀和隨機(jī)存取都是指在正常工作情況下而言,也就是在使用這塊存儲器的時(shí)候,而不是指制造這塊芯片的時(shí)候。否則,只讀存儲器中的數(shù)據(jù)是怎么來的呢?其實(shí)這個(gè)道理也很好理解,書本拿到我們手里是不能改了,可以當(dāng)它還是原材料——白紙的時(shí)候,當(dāng)然可以由印刷廠印上去了。 順便解釋一下其它幾個(gè)常見的概念。 PROM,稱之為可編程存儲器。這
20、就象我們的練習(xí)本,買來的時(shí)候是空白的,可以寫東西上去,可一旦寫上去,就擦不掉了,所以它只能用寫一次,要是寫錯了,就報(bào)銷了。 EPROM,稱之為紫外線擦除的可編程只讀存儲器。它里面的容寫上去之后,如果覺得不滿意,可以用一種特殊的方法去掉后重寫,這就是用紫外線照射,紫外線就象“消字靈”,可以把字去掉,然后再重寫。當(dāng)然消的次數(shù)多了,也就不靈光了,所以這種芯片可以擦除的次數(shù)也是有限的——幾百次吧。 FLASH,稱之為閃速存儲器,它和EPROM類似,寫上去的東西也可以擦掉重寫,但它要方便一些,不需要光照了,只要用電學(xué)方法就可以擦除,所以就方便許多,而且壽面也很長(幾萬到幾十萬次不等)。 再次強(qiáng)調(diào),
21、這里的所有的寫都不是指在正常工作條件下。不管是PROM、EPROM還是FLASH ROM,它們的寫都要有特殊的條件,一般我們用一種稱之為“編程器”的設(shè)備來做這項(xiàng)工作,一旦把它裝到它的工作位置,就不能隨便改寫了。 單片機(jī)教程第四課:第一個(gè)小程序 上一次我們的程序?qū)嵲谑菦]什么用,要燈亮還要重寫一下片子,下面我們要讓燈不斷地閃爍,這就有一定的實(shí)用價(jià)值了,比如可以把它當(dāng)成汽車上的一個(gè)信號燈用了。怎樣才能讓燈不斷地閃爍呢?實(shí)際上就是要燈亮一段時(shí)間,再滅一段時(shí)間,也就是說要P10不斷地輸出高和低電平。怎樣實(shí)現(xiàn)這個(gè)要求呢?請考慮用下面的指令是否可行: SETB P10 CLR P10 ……
22、 這是不行的,有兩個(gè)問題,第一,計(jì)算機(jī)執(zhí)行指令的時(shí)間很快,執(zhí)行完SETB P10后,燈是滅了,但在極短時(shí)間(微秒級)后,計(jì)算機(jī)又執(zhí)行了CLR P10指令,燈又亮了,所以根本分辨不出燈曾滅過。第二,在執(zhí)行完CLR P10后,不會再去執(zhí)行SETB P10指令,所以以后再也沒有機(jī)會讓滅了。 為了解決這兩個(gè)問題,我們可以做如下設(shè)想,第一,在執(zhí)行完SETB P10后,延時(shí)一段時(shí)間(幾秒或零點(diǎn)幾秒)再執(zhí)行第二條指令,就可以分辨出燈曾滅過了。第二在執(zhí)行完第二條指令后,讓計(jì)算機(jī)再去執(zhí)行第一條指令,不斷地在原地兜圈,我們稱之為"循環(huán)",這樣就可以完成任務(wù)了。 以下先給出程序(后面括號中的數(shù)字是為了便
23、于講解而寫的,實(shí)際不用輸入): ;主程序: LOOP: SETB P10 ;(1) LCALL DELAY ??;(2) CLR P10 ??;(3) LCALL DELAY ??;(4) AJMP LOOP ??;(5) ;以下子程序 DELAY: MOV R7,#250 ??;(6) D1: MOV R6,#250 ??;(7) D2: DJNZ R6,D2 ?。唬ǎ福? DJNZ R7,D1 ;(9) RET ??;(10) END ;(11) 按上面的設(shè)想分析一
24、下前面的五條指令。 第一條是讓燈滅,第二條應(yīng)當(dāng)是延時(shí),第三條是讓燈亮,第四條和第二條一模一樣,也是延時(shí),第五條應(yīng)當(dāng)是轉(zhuǎn)去執(zhí)行第一條指令。第二和第四條實(shí)現(xiàn)的原理稍后談,先看第五條,LJMP是一條指令,意思是轉(zhuǎn)移,往什么地方轉(zhuǎn)移呢?后面跟的是LOOP,看一下,什么地方還有LOOP,對了,在第一條指令的前面有一個(gè)LOOP,所以很直觀地,我們可以認(rèn)識到,它要轉(zhuǎn)到第一條指令處。這個(gè)第一條指令前面的LOOP被稱之為標(biāo)號,它的用途就是給這一行起一個(gè)名字,便于使用。是否一定要給它起名叫LOOP呢?當(dāng)然不是,起什么名字,完全由編程序的人決定,可以稱它為A,X等等,當(dāng)然,這時(shí),第五條指令LJMP后面的名字也
25、得跟著改了。 第二條和第四條指令的用途是延時(shí),它是怎樣實(shí)現(xiàn)的呢?指令的形式是LCALL,這條指令稱為調(diào)用子程序指令,看一下指令后面跟的是什么,DELAY,找一下DELAY,在第六條指令的前面,顯然,這也是一個(gè)標(biāo)號。這條指令的作用是這樣的:當(dāng)執(zhí)行LCALL指令時(shí),程序就轉(zhuǎn)到LCALL后面的標(biāo)號所標(biāo)定的程序處執(zhí)行,如果在執(zhí)行指令的過程中遇到RET指令,則程序就返回到LCALL指令的下面的一條指令繼續(xù)執(zhí)行,從第六行開始的指令中,可以看到確實(shí)有RET指令。在執(zhí)行第二條指令后,將轉(zhuǎn)去執(zhí)行第6條指令,而在執(zhí)行完6,7,8,9條指令后將遇到第10條令:RET,執(zhí)行該條指令后,程序?qū)⒒貋韴?zhí)行第三條指令
26、,即將P10清零,使燈亮,然后又是第四條指令,執(zhí)行第四條指令就是轉(zhuǎn)去執(zhí)行第6,7,8,9,10條指令,然后回來執(zhí)行第5條指令,第5條指令就是讓程序回到第1條開始執(zhí)行,如此周而復(fù)始,燈就在不斷地亮、滅了。 在標(biāo)號DELAY標(biāo)志的這一行到RET這一行中的所有程序,這是一段延時(shí)程序,大概延時(shí)零點(diǎn)幾秒,至于具體的時(shí)間,以后我們再學(xué)習(xí)如何計(jì)算。 程序的最后一行是END,這不是一條指令,它只是告訴我們程序到此結(jié)束,它被稱為"偽指令"。 單片機(jī)部結(jié)構(gòu)分析:為了知道延時(shí)程序是如何工作的,我們必需首先了解延時(shí)程序中出現(xiàn)的一些符號, 就從R1開始,R1被稱之為工作寄存器。什么是工作寄存器呢?讓我們從現(xiàn)
27、實(shí)生活中來找找答案。如果出一道數(shù)學(xué)題:123+567,讓你回答結(jié)果是多少,你會馬上答出是690,再看下面一道題:123+567+562,要讓你要上回答,就不這么容易了吧?我們會怎樣做呢?如果有紙,就容易了,我們先算出123+567=690,把690寫在紙上,然后再算690+562得到結(jié)果是1552。這其中1552是我們想要的結(jié)果,而690并非我們所要的結(jié)果,但是為了得到最終結(jié)果,我們又不得不先算出690,并記下來,這其實(shí)是一個(gè)中間結(jié)果,計(jì)算機(jī)中做運(yùn)算和這個(gè)類似,為了要得到最終結(jié)果,往往要做很多步的中間結(jié)果,這些中間結(jié)果要有個(gè)地方放才行,把它們放哪呢?放在前面提到過的ROM中可以嗎?顯然不行,因
28、為計(jì)算機(jī)要將結(jié)果寫進(jìn)去,而ROM是不可以寫的,所以在單片機(jī)中另有一個(gè)區(qū)域稱為RAM區(qū)(RAM是隨機(jī)存取存儲器的英文縮寫),它可以將數(shù)據(jù)寫進(jìn)去。 特別地,在MCS-51單片機(jī)中,將RAM中分出一塊區(qū)域,稱為工作寄存器區(qū) 單片機(jī)教程第五課:延時(shí)程序分析 上一次課中,我們已經(jīng)知道,程序中的符號R7、R6是代表了一個(gè)個(gè)的RAM單元,是用來放一些數(shù)據(jù)的,下面我們再來看一下其它符號的含義。 DELAY: MOV R7,#250 ??;(6) D1: MOV R6,#250 ??;(7) D2: DJNZ R6,D2 ??;(8) DJNZ R7,D1 ??;(9) RET
29、 ;(10) ? MOV:這是一條指令,意思是傳遞數(shù)據(jù)。說到傳遞,我們都很清楚,傳東西要從一個(gè)人的手上傳到另一個(gè)人的手上,也就是說要有一個(gè)接受者,一個(gè)傳遞者和一樣?xùn)|西。從指令MOV R7,#250中來分析,R7是一個(gè)接受者,250是被傳遞的數(shù),傳遞者在這條指令中被省略了(注意:并不是每一條傳遞指令都會省的,事實(shí)上大部份數(shù)據(jù)傳遞指令都會有傳遞者)。它的意義也很明顯:將數(shù)據(jù)250送到R7中去,因此執(zhí)行完這條指令后,R7單元中的值就應(yīng)當(dāng)是250。在250前面有個(gè)#號,這又是什么意思呢?這個(gè)#就是用來說明250就是一個(gè)被傳遞的東西本身,而不是傳遞者。那么MOV R6,#250是什么意思
30、,應(yīng)當(dāng)不用分析了吧。 DJNZ:這是另一條指令,我們來看一下這條指令后面跟著的兩個(gè)東西,一個(gè)是R6,一個(gè)是D2,R6我們當(dāng)然已知是什么了,查一下D2是什么。D2在本行的前面,我們已學(xué)過,這稱之為標(biāo)號。標(biāo)號的用途是什么呢?就是給本行起一個(gè)名字。DJNZ指令的執(zhí)行過程是這樣的,它將其后面的第一個(gè)參數(shù)中的值減1,然后看一下,這個(gè)值是否等于0,如果等于0,就往下執(zhí)行,如果不等于0,就轉(zhuǎn)移,轉(zhuǎn)到什么地方去呢?可能大家已猜到了,轉(zhuǎn)到第二個(gè)參數(shù)所指定的地方去(請大家用自已的話講一下這條語句是怎樣執(zhí)行的)。本條指令的最終執(zhí)行結(jié)果就是,在原地轉(zhuǎn)圈250次。 執(zhí)行完了DJNZ R6,D2之后(也就是R6的值等
31、于0之后),就會去執(zhí)行下面一行,也就是DJNZ R7,D1,請大家自行分析一下這句話執(zhí)行的結(jié)果。(轉(zhuǎn)去執(zhí)行MOV R6,#250,同時(shí)R7中的值減1),最終DJNZ R6,D2這句話將被執(zhí)行250*250=62500次,執(zhí)行這么多次同一條指令干嗎?就是為了延時(shí)。 一個(gè)問題:如果在R6中放入0,會有什么樣的結(jié)果。 二、時(shí)序分析: 前面我們介紹了延時(shí)程序,但這還不完善,因?yàn)椋覀冎恢繢JNZ R6,D2這句話會被執(zhí)行62500次,但是執(zhí)行這么多次需要多長時(shí)間呢?是否滿足我們的要求呢?我們還不知道,所以下面要來解決這個(gè)問題。 先提一個(gè)問題:我們學(xué)校里什么是最重要的。(鈴聲)校長可以出差,老
32、師可以休息,但學(xué)校一日無鈴聲必定大亂。整個(gè)學(xué)校就是在鈴聲的統(tǒng)一指揮下,步調(diào)一致,統(tǒng)一協(xié)調(diào)地工作著。這個(gè)鈴是按一定的時(shí)間安排來響的,我們可以稱之為“時(shí)序時(shí)間的順序”。一個(gè)由人組成的單位尚且要有一定的時(shí)序,計(jì)算機(jī)當(dāng)然更要有嚴(yán)格的時(shí)序。事實(shí)上,計(jì)算機(jī)更象一個(gè)大鐘,什么時(shí)候分針動,什么時(shí)候秒針動,什么時(shí)候時(shí)針動,都有嚴(yán)格的規(guī)定,一點(diǎn)也不能亂。計(jì)算機(jī)要完成的事更復(fù)雜,所以它的時(shí)序也更復(fù)雜。 我們已知,計(jì)算機(jī)工作時(shí),是一條一條地從ROM中取指令,然后一步一步地執(zhí)行,我們規(guī)定:計(jì)算機(jī)訪問一次存儲器的時(shí)間,稱之為一個(gè)機(jī)器周期。這是一個(gè)時(shí)間基準(zhǔn),好象我們?nèi)擞谩懊搿弊鳛槲覀兊臅r(shí)間基準(zhǔn)一樣,為什么
33、不干脆用“秒”,多好,很習(xí)慣,學(xué)下去我們就會知道用“秒”反而不習(xí)慣。 一個(gè)機(jī)器周期包括12個(gè)時(shí)鐘周期。下面讓我們算一下一個(gè)機(jī)器周期是多長時(shí)間吧。設(shè)一個(gè)單片機(jī)工作于12M晶振,它的時(shí)鐘周期是1/12(微秒)。它的一個(gè)機(jī)器周期是12*(1/12)也就是1微秒。(請計(jì)算一個(gè)工作于6M晶振的單片機(jī),它的機(jī)器周期是多少)。 MCS-51單片機(jī)的所有指令中,有一些完成得比較快,只要一個(gè)機(jī)器周期就行了,有一些完成得比較慢,得要2個(gè)機(jī)器周期,還有兩條指令要4個(gè)機(jī)器周期才行。這也不難再解,不是嗎?我讓你掃地的執(zhí)行要完成總得比要你完成擦黑板的指令時(shí)間要長。為了恒量指令執(zhí)行時(shí)間的長短,又引入一個(gè)新的概念:指令周
34、期。所謂指令周期就是指執(zhí)行一條指令的時(shí)間。INTEL對每一條指令都給出了它的指令周期數(shù),這些數(shù)據(jù),大部份不需要我們?nèi)ビ洃?,但是有一些指令是需要記住的,如DJNZ指令是雙周期指令。 下面讓我們來計(jì)算剛才的延時(shí)。首先必須要知道晶振的頻率,我們設(shè)所用晶振為12M,則一個(gè)機(jī)器周期就是1微秒。而DJNZ指令是雙周期指令,所以執(zhí)行一次要2個(gè)微秒。一共執(zhí)行62500次,正好125000微秒,也就是125毫秒。 練習(xí):設(shè)計(jì)一個(gè)延時(shí)100毫秒的延時(shí)程序。 要點(diǎn)分析:1、一個(gè)單元中的數(shù)是否可以超過255。2、如何分配兩個(gè)數(shù)。 三、復(fù)位電路 任何單片機(jī)在工作之前都要有個(gè)復(fù)位的過程,復(fù)位是什么意思呢?它就象
35、是我們上課之前打的預(yù)備鈴。預(yù)備鈴一響,大家就自動地從操場、其它地方進(jìn)入教室了,在這一段時(shí)間里,是沒有老師干預(yù)的,對單片機(jī)來說,是程序還沒有開始執(zhí)行,是在做準(zhǔn)備工作。顯然,準(zhǔn)備工作不需要太長的時(shí)間,復(fù)位只需要5ms的時(shí)間就可以了。如何進(jìn)行復(fù)位呢?只要在單片機(jī)的RST引腳上加上高電平,就可以了,按上面所說,時(shí)間不少于5ms。為了達(dá)到這個(gè)要求,可以用很多種方法,這里提供一種供參考,見圖1。實(shí)際上,我們在上一次實(shí)驗(yàn)的圖中已見到過了。 這種復(fù)位電路的工作原理是:通電時(shí),電容兩端相當(dāng)于是短路,于是RST引腳上為高電平,然后電源通過電阻對電容充電,RST端電壓慢慢下降,降到一定程序,即為低電平,單片機(jī)開始
36、正常工作。 ? 單片機(jī)教程第六課:單片機(jī)的外部結(jié)構(gòu)分析(四) 上兩次我們做過兩個(gè)實(shí)驗(yàn),都是讓P1.0這個(gè)引腳使燈亮,我們可以設(shè)想:既然P1.0可以讓燈亮,那么其它的引腳可不可以呢?看一下圖1,它是8031單片機(jī)引腳的說明,在P1.0旁邊有P1.1,P1.2….P1.7,它們是否都可以讓燈亮呢?除了以P1開頭的外,還有以P0,P2,P3開頭的,數(shù)一下,一共是32個(gè)引腳,前面我們以學(xué)過7個(gè)引腳,加上這32個(gè)這39個(gè)了。它們都以P字開頭,只是后面的數(shù)字不一樣,它們是否有什么聯(lián)系呢?它們能不能都讓燈亮呢?在我們的實(shí)驗(yàn)板上,除了P10之外,還有P11P17都與LED相連,下面讓我們
37、來做一個(gè)實(shí)驗(yàn),程序如下: MAIN: MOV P1,#0FFH LCALL DELAY MOV P1,#00H LCALL DELAY LJMP MAIN DELAY:MOV R7,#250 D1: MOV R6,#250 D2: DJNZ R6,D2 DJNZ R7,D1 RET END 將這段程序轉(zhuǎn)為機(jī)器碼,用編程器寫入芯片中,結(jié)果如何?通電以后我們可以看到8只LED全部在閃動。因此,P10P17是全部可以點(diǎn)亮燈的。事實(shí)上,凡以P開頭的這32個(gè)引腳都是可以點(diǎn)亮燈的,也就是說:這32個(gè)引腳都可以作為輸出使用,如果不用來點(diǎn)亮LED,可以用來控制繼電器,可
38、以用來控制其它的執(zhí)行機(jī)構(gòu)。 程序分析:這段程序和前面做過的程序比較,只有兩處不一樣:第一句:原來是SETB P1.0,現(xiàn)在改為MOV P1,#0FFH,第三句:原來是CLR P1.0,現(xiàn)在改為MOV P1.0,#00H。從中可以看出,P1是P1.0P1.7的全體的代表,一個(gè)P1就表示了所有的這八個(gè)管腳了。當(dāng)然用的指令也不一樣了,是用MOV指令。為什么用這條指令?看圖2,我們把P1作為一個(gè)整體,就把它當(dāng)作是一個(gè)存儲器的單元,對一個(gè)單元送進(jìn)一個(gè)數(shù)可以用MOV指令。 二、第四個(gè)實(shí)驗(yàn) 除了可以作為輸出外,這32個(gè)引腳還可以做什么呢?下面再來做一個(gè)實(shí)驗(yàn),程序如下: MAIN: M
39、OV P3,#0FFH LOOP: MOV A,P3 MOV P1,A LJMP LOOP 先看一下實(shí)驗(yàn)的結(jié)果:所有燈全部不亮,然后我按下一個(gè)按鈕,第()個(gè)燈亮了,再按下另一個(gè)按鈕,第()個(gè)燈亮了,松開按鈕燈就滅了。從這個(gè)實(shí)驗(yàn)現(xiàn)象結(jié)合電路來分析一下程序。 從硬件電路的連線可以看出,有四個(gè)按鈕被接入到P3口的P32,P33,P34,P35。第一條指令的用途我們可以猜到:使P3口全部為高電平。第二條指令是MOV A,P3,其中 MOV已經(jīng)見,是送數(shù)的意思,這條指令的意思就是將P3口的數(shù)送到A中去,我們可以把A當(dāng)成是一個(gè)中間單元(看圖3),第三句話是將A中的數(shù)又送到P1口去,第四句話是循環(huán)
40、,就是不斷地重復(fù)這個(gè)過程,這我們已見過。當(dāng)我們按下第一個(gè)按鈕時(shí),第(3)只燈亮了,所以P12口應(yīng)當(dāng)輸出是低電平,為什么P12口會輸出低電平呢?我們看一下有什么被送到了P1口,只有從P3口進(jìn)來的數(shù)送到A,又被送到了P1口,所以,肯定是P3口進(jìn)來的數(shù)使得P12位輸出電平的。P3口的P32位的按鈕被按下,使得P32位的電平為低,通過程序,又使P12口輸出低電平,所以P3口起來了一個(gè)輸入的作用。驗(yàn)證:按第二、三、四個(gè)按鈕,同時(shí)按下2個(gè)、3個(gè)、4個(gè)按鈕都可以得到同樣的結(jié)論,所以P3口確實(shí)起到了輸入作用,這樣,我們可以看到,以P字開頭的管腳,不僅可以用作輸出,還可以用作輸入,其它的管腳是否可以呢?是的,都
41、可以。這32個(gè)引腳就稱之為并行口,下面我們就對并行口的結(jié)構(gòu)作一個(gè)分析,看一下它是怎樣實(shí)現(xiàn)輸入和輸出的。 并行口結(jié)構(gòu)分析: 1、輸出結(jié)構(gòu) 先看P1口的一位的結(jié)構(gòu)示意圖(只畫出了輸出部份):從圖中可以看出,開關(guān)的打開和合上代表了引腳輸出的高和低,如果開關(guān)合上了,則引腳輸出就是低,如果開關(guān)打開了,則輸出高電平,這個(gè)開關(guān)是由一根線來控制的,這根數(shù)據(jù)總線是出自于CPU,讓我們回想一下,數(shù)據(jù)總線是一根大家公用的線,很多的器件和它連在一起,在不同的時(shí)候,不同的器件當(dāng)然需要不同的信號,如某一時(shí)刻我們讓這個(gè)引腳輸出高電平,并要求保持若干時(shí)間,在這段時(shí)間里,計(jì)算機(jī)當(dāng)然在忙個(gè)不停,在與其它器件進(jìn)行聯(lián)絡(luò),這根控
42、制線上的電平未必能保持原來的值不變,輸出就會發(fā)生變化了。怎么解決這個(gè)問題呢?我們在存儲器一節(jié)中學(xué)過,存儲器中是可以存放電荷的,我們不妨也加一個(gè)小的存儲器的單元,并在它的前面加一個(gè)開關(guān),要讓這一位輸出時(shí),就把開關(guān)打開,信號就進(jìn)入存儲器的單元,然后馬上關(guān)閉開關(guān),這樣這一位的狀態(tài)就被保存下來,直到下一次命令讓它把開關(guān)再打開為止。這樣就能使這一位的狀態(tài)與別的器件無關(guān)了,這么一個(gè)小單元,我們給它一個(gè)很形象的名字,稱之為“鎖存器”。 2、輸入結(jié)構(gòu) 這是并行口的一位的輸出結(jié)構(gòu)示意圖,再看,除了輸出之外,還有兩根線,一根從外部引腳接入,另一根從鎖存器的輸出接出,分別標(biāo)明讀引腳和讀鎖存器。這兩根線是用于從外
43、部接收信號的,為什么要兩根呢?原來,在51單片機(jī)中輸入有兩種方式,分別稱為‘讀引腳’和‘讀鎖存器’,第一種方式是將引腳作為輸入,那是真正地從外部引腳讀進(jìn)輸入的值,第二種方式是該引腳處于輸出狀態(tài)時(shí),有時(shí)需要改變這一位的狀態(tài),則并不需要真正地讀引腳狀態(tài),而只是讀入鎖存器的狀態(tài),然后作某種變換后再輸出。 請注意輸入結(jié)構(gòu)圖,如果將這一根引線作為輸入口使用,我們并不能保證在任何時(shí)刻都能得到正確的結(jié)果(為什么?)參考圖2輸入示意圖。接在外部的開關(guān)如果打開,則應(yīng)當(dāng)是輸入1,而如果閉合開關(guān),則輸入0,但是,如果單片機(jī)部的開關(guān)是閉合的,那么不管外部的開關(guān)是開還是閉,單片機(jī)接受到的數(shù)據(jù)都是0。可見,要讓這一端口
44、作為輸入使用,要先做一個(gè)‘準(zhǔn)備工作’,就是先讓部的開關(guān)斷開,也就是讓端口輸出‘1’才行。正因?yàn)橐茸鲞@么一個(gè)準(zhǔn)備工作,所以我們稱之為“準(zhǔn)雙向I/O口”。 以上是P1口的一位的結(jié)構(gòu),P1口其它各位的結(jié)構(gòu)與之一樣,而其它三個(gè)口:P0、P2、P3則除入作為輸入輸出口之外還有其它用途,所以結(jié)構(gòu)要稍復(fù)雜一些,但其用于輸入、輸出的結(jié)構(gòu)是一樣的??磮D()。對我們來說,這些附加的功能不必由我們來控制,所以我們就不去關(guān)心它了。 ? 單片機(jī)教程第七課:單片機(jī)部結(jié)構(gòu)分析(五) 通過前面的學(xué)習(xí),我們已知單片機(jī)的部有ROM、有RAM、有并行I/O口,那么,除了這些東西之外,單片機(jī)部究竟還有些什么,這些個(gè)零碎的東
45、西怎么連在一起的,讓我們來對單片機(jī)部作一個(gè)完整的分析吧! 看圖(1)(本圖太大,請大家找本書看吧,一般講單片機(jī)的書,隨便哪本都有)。從圖中我們可以看出,在51單片機(jī)部有一個(gè)CPU用來運(yùn)算、控制,有四個(gè)并行I/O口,分別是P0、P1、P2、P3,有ROM,用來存放程序,有RAM,用來存放中間結(jié)果,此外還有定時(shí)/計(jì)數(shù)器,串行I/O口,中斷系統(tǒng),以與一個(gè)部的時(shí)鐘電路。在一個(gè)51單片機(jī)的部包含了這么多的東西。 對上面的圖進(jìn)行進(jìn)一步的分析,我們已知,對并行I/O口的讀寫只要將數(shù)據(jù)送入到相應(yīng)I/O口的鎖存器就可以了,那么對于定時(shí)/計(jì)數(shù)器,串行I/O口等怎么用呢?在單片機(jī)中有一些獨(dú)立的存儲單元是用來控制
46、這些器件的,被稱之為特殊功能寄存器(SFR)。事實(shí)上,我們已接觸過P1這個(gè)特殊功能寄存器了,還有哪些呢?看表1 符號 地址 功能介紹 B F0H B寄存器 ACC E0H 累加器 PSW D0H 程序狀態(tài)字 IP B8H 中斷優(yōu)先級控制寄存器 P3 B0H P3口鎖存器 IE A8H 中斷允許控制寄存器 P2 A0H P2口鎖存器 SBUF 99H 串行口鎖存器 SCON 98H 串行口控制寄存器 P1 90H P1口鎖存器 TH1 8DH 定時(shí)器/計(jì)數(shù)器1(高8位) TH0
47、 8CH 定時(shí)器/計(jì)數(shù)器1(低8位) TL1 8BH 定時(shí)器/計(jì)數(shù)器0(高8位) TL0 8AH 定時(shí)器/計(jì)數(shù)器0(低8位) TMOD 89A 定時(shí)器/計(jì)數(shù)器方式控制寄存器 TCON 88H 定時(shí)器/計(jì)數(shù)器控制寄存器 DPH 83H 數(shù)據(jù)地址指針(高8位) DPL 82H 數(shù)據(jù)地址指針(低8位) SP 81H 堆棧指針 P0 80H P0口鎖存器 PCON 87H 電源控制寄存器 表1 下面,我們介紹一下幾個(gè)常用的SFR,看圖2。 ACC:累加器,通常用A表示。這是個(gè)什么東西,可不能從名字上
48、理解,它是一個(gè)寄存器,而不是一個(gè)做加法的東西,為什么給它這么一個(gè)名字呢?或許是因?yàn)樵谶\(yùn)算器做運(yùn)算時(shí)其中一個(gè)數(shù)一定是在ACC中的緣故吧。它的名字特殊,身份也特殊,稍后我們將學(xué)到指令,可以發(fā)現(xiàn),所有的運(yùn)算類指令都離不開它。 2、B:一個(gè)寄存器。在做乘、除法時(shí)放乘數(shù)或除數(shù),不做乘除法時(shí),隨你怎么用。 3、PSW:程序狀態(tài)字。這是一個(gè)很重要的東西,里面放了CPU工作時(shí)的很多狀態(tài),借此,我們可以了解CPU的當(dāng)前狀態(tài),并作出相應(yīng)的處理。它的各位功能請看表2 D7 D6 D5 D4 D3 D2 D1 D0 CY AC F0 RS1 RS0 OV P 表2 下面我們
49、逐一介紹各位的用途 (1)CY:進(jìn)位標(biāo)志。8051中的運(yùn)算器是一種8位的運(yùn)算器,我們知道,8位運(yùn)算器只能表示到0-255,如果做加法的話,兩數(shù)相加可能會超過255,這樣最高位就會丟失,造成運(yùn)算的錯誤,怎么辦?最高位就進(jìn)到這里來。這樣就沒事了。 例:78H+97H(01111000+10010111) (2)AC:半進(jìn)位標(biāo)志。 例:57H+3AH(01010111+00111010) (3)F0:用戶標(biāo)志位,由我們(編程人員)決定什么時(shí)候用,什么時(shí)候不用。 (4)RS1、RS0:工作寄存器組選擇位。這個(gè)我們已知了。 (5)0V:溢出標(biāo)志位。什么是溢出我們稍后再談吧。 (6)P:奇
50、偶校驗(yàn)位:它用來表示ALU運(yùn)算結(jié)果中二進(jìn)制數(shù)位“1”的個(gè)數(shù)的奇偶性。若為奇數(shù),則P=1,否則為0。 例:某運(yùn)算結(jié)果是78H(01111000),顯然1的個(gè)數(shù)為偶數(shù),所以P=0。 4、DPTR(DPH、DPL):數(shù)據(jù)指針,可以用它來訪問外部數(shù)據(jù)存儲器中的任一單元,如果不用,也可以作為通用寄存器來用,由我們自已決定如何使用。 5、P0、P1、P2、P3:這個(gè)我們已經(jīng)知道,是四個(gè)并行輸入/輸出口的寄存器。它里面的容對應(yīng)著管腳的輸出。 6、SP:堆棧指針。 堆棧介紹:日常生活中,我們都注意到過這樣的現(xiàn)象,家里洗的碗,一只一只摞起來,最晚放上去的放在最上面,而最早放上去的則放在最下面,在取的時(shí)
51、候正好相反,先從最上面取,這種現(xiàn)象我們用一句話來概括:“先進(jìn)后出,后進(jìn)先出”。請大家想想,還有什么地方有這種現(xiàn)象?其實(shí)比比皆是,建筑工地上堆放的磚頭、材料,倉庫里放的貨物,都是“先進(jìn)后出,后進(jìn)先出”,這實(shí)際是一種存取物品的規(guī)則,我們稱之為“堆棧”。 在單片機(jī)中,我們也可以在RAM中構(gòu)造這樣一個(gè)區(qū)域,用來存放數(shù)據(jù),這個(gè)區(qū)域存放數(shù)據(jù)的規(guī)則就是“先進(jìn)后出,后進(jìn)先出”,我們稱之為“堆?!?。為什么需要這樣來存放數(shù)據(jù)呢?存儲器本身不是可以按地址來存放數(shù)據(jù)嗎?對,知道了地址的確就可以知道里面的容,但如果我們需要存放的是一批數(shù)據(jù),每一個(gè)數(shù)據(jù)都需要知道地址那不是麻煩嗎?如果我們讓數(shù)據(jù)一個(gè)接一個(gè)地放置,那么我們
52、只要知道第一個(gè)數(shù)據(jù)所在地址單元就可以了(看圖2)如果第一個(gè)數(shù)據(jù)在27H,那么第二、三個(gè)就在28H、29H了。所以利用堆棧這種方法來放數(shù)據(jù)可以簡化操作 那么51中堆棧什么地方呢?單片機(jī)中能存放數(shù)據(jù)的區(qū)域有限,我們不能夠?qū)iT分配一塊地方做堆棧,所以就在存(RAM)中開辟一塊地方,用于堆棧,但是用存的哪一塊呢?還是不好定,因?yàn)?1是一種通用的單片機(jī),各人的實(shí)際需求各不一樣,有人需要多一些堆棧,而有人則不需要那么多,所以怎么分配都不合適,怎樣來解決這個(gè)問題?分不好干脆就不分了,把分的權(quán)利給用戶(編程者),根據(jù)自已的需要去定吧,所以51單片機(jī)中堆棧的位置是可以變化的。而這種變化就體現(xiàn)在SP中值的變化,
53、看圖2,SP中的值等于27H不就相當(dāng)于是一個(gè)指針指向27H單元嗎?當(dāng)然在真正的51機(jī)中,開始指針?biāo)傅奈恢貌⒎蔷褪菙?shù)據(jù)存放的位置,而是數(shù)據(jù)存放的前一個(gè)位置,比如一開始指針是指向27H單元的,那么第一個(gè)數(shù)據(jù)的位置是28H單元,而不是27H單元,為什么會這樣,我們在學(xué)堆棧命令時(shí)再說明。 其它的SFR,我們在用到時(shí)再介紹。 單片機(jī)第八課(尋址方式與指令系統(tǒng)) 通過前面的學(xué)習(xí),我們已經(jīng)了解了單片機(jī)部的結(jié)構(gòu),并且也已經(jīng)知道,要控制單片機(jī),讓它為我們干學(xué),要用指令,我們已學(xué)了幾條指令,但很零散,從現(xiàn)在開始,我們將要系統(tǒng)地學(xué)習(xí)8051的指令部份。 一、概述 1、指令的格式 我們已知,要讓計(jì)算機(jī)做
54、事,就得給計(jì)算機(jī)以指令,并且我們已知,計(jì)算機(jī)很“笨”,只能懂得數(shù)字,如前面我們寫進(jìn)機(jī)器的75H,90H,00H等等,所以指令的第一種格式就是機(jī)器碼格式,也說是數(shù)字的形式。但這種形式實(shí)在是為難我們?nèi)肆?,太難記了,于是有另一種格式,助記符格式,如MOV P1,#0FFH,這樣就好記了。這兩種格式之間的關(guān)系呢,我們不難理解,本質(zhì)上它們完全等價(jià),只是形式不一樣而已。 2、匯編 我們寫指令使用匯編格式,而計(jì)算機(jī)只懂機(jī)器碼格式,所以要將我們寫的匯編格式的指令轉(zhuǎn)換為機(jī)器碼格式,這種轉(zhuǎn)換有兩種方法:手工匯編和機(jī)器匯編。手工匯編實(shí)際上就是查表,因?yàn)檫@兩種格式純粹是格式不同,所以是一一對應(yīng)的,查一表格就行
55、了。不過手工查表總是嫌麻煩,所以就有了計(jì)算機(jī)軟件,用計(jì)算機(jī)軟件來替代手工查表,這就是機(jī)器匯編。 二、尋址 讓我們先來復(fù)習(xí)一下我們學(xué)過的一些指令:MOV P1,#0FFH,MOV R7,#0FFH這些指令都是將一些數(shù)據(jù)送到相應(yīng)的位置中去,為什么要送數(shù)據(jù)呢?第一個(gè)因?yàn)樗腿氲臄?shù)可以讓燈全滅掉,第二個(gè)是為了要實(shí)現(xiàn)延時(shí),從這里我們可以看出來,在用單片機(jī)的編程語言編程時(shí),經(jīng)常要用到數(shù)據(jù)的傳遞,事實(shí)上數(shù)據(jù)傳遞是單片機(jī)編程時(shí)的一項(xiàng)重要工作,一共有28條指令(單片機(jī)共111條指令)。下面我們就從數(shù)據(jù)傳遞類指令開始吧。 分析一下MOV P1,#0FFH這條指令,我們不難得出結(jié)論,第一個(gè)詞MOV是命令
56、動詞,也就是決定做什么事情的,MOV是MOVE少寫了一個(gè)E,所以就是“傳遞”,這就是指令,規(guī)定做什么事情,后面還有一些參數(shù),分析一下,數(shù)據(jù)傳遞必須要有一個(gè)“源”也就是你要送什么數(shù),必須要有一個(gè)“目的”,也就是你這個(gè)數(shù)要送到什么地方去,顯然在上面那條指令中,要送的數(shù)(源)就是0FFH,而要送達(dá)的地方(目的地)就是P1這個(gè)寄存器。在數(shù)據(jù)傳遞類指令中,均將目的地寫在指令的后面,而將源寫在最后。 這條指令中,送給P1是這個(gè)數(shù)本身,換言之,做完這條指令后,我們可以明確地知道,P1中的值是0FFH,但是并不是任何時(shí)候都可以直接給出數(shù)本身的。例如,在我們前面給出的延時(shí)程序例是這樣寫的: MAIN
57、: SETB P1.0 ??;(1) LCALL DELAY ;(2) CLR P1.0 ;(3) LCALL DELAY ;(4) AJMP MAIN ;(5) ;以下子程序 DELAY: MOV R7,#250;(6) D1: MOV R6,#250 ;(7) D2: DJNZ R6,D2 ;(8) DJNZ R7,D1;(9) RET ;(10) END ;(11) 表1 MAIN: SETB P1.0 ;(1) MOV 30H,#255 LCALL DELAY ; CLR P1.0 ;(3) MOV 30H,#200 L
58、CALL DELAY ;(4) AJMP MAIN ;(5) ;以下子程序 DELAY: MOV R7,30H;(6) D1: MOV R6,#250 ;(7) D2: DJNZ R6,D2 ;(8) DJNZ R7,D1;(9) RET ;(10) END ;(11) 這樣一來,我每次調(diào)用延時(shí)程序延時(shí)的時(shí)間都是一樣的(大致都是0.13S),如果我提出這樣的要求:燈亮后延時(shí)時(shí)間為0.13S燈滅,燈滅后延時(shí)0.1秒燈亮,如此循環(huán),這樣的程序還能滿足要求嗎?不能,怎么辦?我們可以把延時(shí)程序改成這樣(見表2):調(diào)用則見表2中的主程,也就是先把一個(gè)數(shù)送入30H,在子程序中R7
59、中的值并不固定,而是根據(jù)30H單元中傳過來的數(shù)確定。這樣就可以滿足要求。 從這里我們可以得出結(jié)論,在數(shù)據(jù)傳遞中要找到被傳遞的數(shù),很多時(shí)候,這個(gè)數(shù)并不能直接給出,需要變化,這就引出了一個(gè)概念:如何尋找操作數(shù),我們把尋找操作數(shù)所在單元的地址稱之為尋址。在這里我們直接使用數(shù)所在單元的地址找到了操作數(shù),所以稱這種方法為直接尋址。除了這種方法之外,還有一種,如果我們把數(shù)放在工作寄存器中,從工作寄存器中尋找數(shù)據(jù),則稱之為寄存器尋址。例:MOV A,R0就是將R0工作寄存器中的數(shù)據(jù)送到累加器A中去。提一個(gè)問題:我們知道,工作寄存器就是存單元的一部份,如果我們選擇工作寄存器組0,則R0就是RAM的00H
60、單元,那么這樣一來,MOV A,00H,和MOV A,R0不就沒什么區(qū)別了嗎?為什么要加以區(qū)分呢?的確,這兩條指令執(zhí)行的結(jié)果是完全一樣的,都是將00H單元中的容送到A中去,但是執(zhí)行的過程不同,執(zhí)行第一條指令需要2個(gè)周期,而第二條則只需要1個(gè)周期,第一條指令變成最終的目標(biāo)碼要兩個(gè)字節(jié)(E5H 00H),而第二條則只要一個(gè)字節(jié)(E8h)就可以了。 這么斤斤計(jì)較!不就差了一個(gè)周期嗎,如果是12M的晶振的話,也就1個(gè)微秒時(shí)間了,一個(gè)字節(jié)又能有多少? 不對,如果這條指令只執(zhí)行一次,也許無所謂,但一條指令如果執(zhí)行上1000次,就是1毫秒,如果要執(zhí)行1000000萬次,就是1S的誤差,這就很可觀了,
61、單片機(jī)做的是實(shí)時(shí)控制的事,所以必須如此“斤斤計(jì)較”。字節(jié)數(shù)同樣如此。 再來提一個(gè)問題,現(xiàn)在我們已知,尋找操作數(shù)可以通過直接給的方式(立即尋址)和直接給出數(shù)所在單元地址的方式(直接尋址),這就夠了嗎? 看這個(gè)問題,要求從30H單元開始,取20個(gè)數(shù),分別送入A累加器。 就我們目前掌握的辦法而言,要從30H單元取數(shù),就用MOV A,30H,那么下一個(gè)數(shù)呢?是31H單元的,怎么取呢?還是只能用MOV A,31H,那么20個(gè)數(shù),不是得20條指令才能寫完嗎?這里只有20個(gè)數(shù),如果要送200個(gè)或2000個(gè)數(shù),那豈不要寫上200條或2000條命令?這未免太笨了吧。為什么會出現(xiàn)這樣的狀況?是因?yàn)槲覀冎粫?/p>
62、地址寫在指令中,所以就沒辦法了,如果我們不是把地址直接寫在指令中,而是把地址放在另外一個(gè)寄存器單元中,根據(jù)這個(gè)寄存器單元中的數(shù)值決定該到哪個(gè)單元中取數(shù)據(jù),比如,當(dāng)前這個(gè)寄存器中的值是30H,那么就到30H單元中去取,如果是31H就到31H單元中去取,就可以解決這個(gè)問題了。怎么個(gè)解決法呢?既然是看的寄存器中的值,那么我們就可以通過一定的方法讓這里面的值發(fā)生變化,比如取完一個(gè)數(shù)后,將這個(gè)寄存器單元中的值加1,還是執(zhí)行同一條指令,可是取數(shù)的對象卻不一樣了,不是嗎。通過例子來說明吧。 MOV R7,#20 MOV R0,#30H LOOP:MOV A,R0 INC R0 DJNZ R7
63、,LOOP 這個(gè)例子部份指令我們是能看懂的,第一句,是將立即數(shù)20送到R7中,執(zhí)行完后R7中的值應(yīng)當(dāng)是20。第二句是將立即數(shù)30H送入R0工作寄存器中,所以執(zhí)行完后,R0單元中的值是30H,第三句,這是看一下R0單元中是什么值,把這個(gè)值作為地址,取這個(gè)地址單元的容送入A中,此時(shí),執(zhí)行這條指令的結(jié)果就相當(dāng)于MOV A,30H。第四句,沒學(xué)過,就是把R0中的值加1,因此執(zhí)行完后,R0中的值就是31H,第五句,學(xué)過,將R7中的值減1,看是否等于0,不等于0,則轉(zhuǎn)到標(biāo)號LOOP處繼續(xù)執(zhí)行,因此,執(zhí)行完這句后,將轉(zhuǎn)去執(zhí)行MOV A,R0這句話,此時(shí)相當(dāng)于執(zhí)行了MOV A,31H(因?yàn)榇藭r(shí)的R0中的值已
64、是31H了),如此,直到R7中的值逐次相減等于0,也就是循環(huán)20次為止,就實(shí)現(xiàn)了我們的要求:從30H單元開始將20個(gè)數(shù)據(jù)送入A中。 這也是一種尋找數(shù)據(jù)的方法,由于數(shù)據(jù)是間接地被找到的,所以就稱之為間址尋址。注意,在間址尋址中,只能用R0或R1存放等尋找的數(shù)據(jù)。 單片機(jī)教程第九課:數(shù)據(jù)傳遞指令 數(shù)據(jù)傳遞類指令 1)以累加器為目的操作數(shù)的指令 MOV A,Rn MOV A,direct MOV A,Ri MOV A,#data 第一條指令中,Rn代表的是R0-R7。第二條指令中,direct就是指的直接地址,而第三條指令中,就是我們剛才講過的。第四條指令是將立即數(shù)data
65、送到A中。 下面我們通過一些例子加以說明: MOV A,R1 ;將工作寄存器R1中的值送入A,R1中的值保持不變。 MOV A,30H ;將存30H單元中的值送入A,30H單元中的值保持不變。 MOV A,R1 ;先看R1中是什么值,把這個(gè)值作為地址,并將這個(gè)地址單元中的值送入A中。如執(zhí)行命令前R1中的值為20H,則是將20H單元中的值送入A中。 MOV A,#34H ;將立即數(shù)34H送入A中,執(zhí)行完本條指令后,A中的值是34H。 2)以寄存器Rn為目的操作的指令 MOV Rn,A MOV Rn,direct MOV Rn,#data 這組指令功能是把源地址單元中的容送入工
66、作寄存器,源操作數(shù)不變。 單片機(jī)指令(二) 數(shù)據(jù)傳遞類指令 (3)以直接地址為目的操作數(shù)的指令MOV direct,A 例: MOV 20H,AMOV direct,Rn MOV 20H,R1 MOV direct1,direct2 MOV 20H,30H MOV direct,Ri MOV 20H,R1 MOV direct,#data MOV 20H,#34H (4)以間接地址為目的操作數(shù)的指令MOV Ri,A 例:MOV R0,AMOV Ri,direct MOV R1,20H MOV Ri,#data MOV R0,#34H (5)十六位數(shù)的傳遞指令MOV DPTR,#data168051是一種8位機(jī),這是唯一的一條16位立即數(shù)傳遞指令,其功能是將一個(gè)16位的立即數(shù)送入DPTR中去。其中高8位送入DPH,低8位送入DPL。例:MOV DPTR,#1234H,則執(zhí)行完了之后DPH中的值為12H,DPL中的值為34H。反之,如果我們分別向DPH,DPL送數(shù),則結(jié)果也一樣。如有下面兩條指令:MOV DPH,#35H,MOV DPL,#12H。則就相當(dāng)于執(zhí)行了MOV
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 離心泵的檢修各零部件檢修標(biāo)準(zhǔn)
- 金屬材料疲勞強(qiáng)度的八大主要影響因素
- 機(jī)械安全知識
- 電機(jī)的工作原理與種類
- 設(shè)備點(diǎn)檢內(nèi)容
- 有效防止液壓系統(tǒng)漏油的技術(shù)要領(lǐng)
- 鈑金和管工機(jī)械安全操作規(guī)程
- 閥門的100個(gè)專業(yè)術(shù)語
- 某單位機(jī)械設(shè)備安全檢查表
- 離心泵的汽蝕與吸入特性
- 過濾網(wǎng)目數(shù)標(biāo)準(zhǔn)
- 減少設(shè)備潤滑故障的措施
- 離心泵機(jī)械密封安裝使用規(guī)則
- 閥門常見故障與原因
- 呼吸閥和真空破壞閥基礎(chǔ)知識總結(jié)