單片機學(xué)習之六:基本I/O口試驗二:跑馬燈
一、試驗現象:
本文引用地址:http://dyxdggzs.com/article/201609/297082.htm二極管從右至左依次發(fā)光。
二、試驗目的:
l 掌握寄存器A,Rn的使用方法
l 掌握左移指令
l 掌握延時(shí)程序的編寫(xiě)
三、任務(wù)分析:
電路圖同試驗1,有了上一個(gè)試驗的基礎,這個(gè)程序對我們就沒(méi)有什么難度啦。我們可以這樣作:
首先:mov p0,#ofeh(讓最右邊的燈亮),然后經(jīng)過(guò)一段延時(shí),再:mov p1,#ofdh,這樣依次賦值,直到:mov p0,#07fh(最左面的燈亮)。然后用ajmp指令返回,讓燈光再重新開(kāi)始循環(huán)。
這樣固然可以,但是程序不夠簡(jiǎn)單明了,我們要寫(xiě)8個(gè)mov語(yǔ)句。設想一下,假如有幾十個(gè)燈,那寫(xiě)起來(lái)不是麻煩死啦?
好在單片機有一條左移指令rl a,它的作用是把累加器a中的數循環(huán)左移。
順便說(shuō)一下累加器a,它是單片機中的最常用的寄存器,大部分單操作數的指令都以a作為操作對象(例如rl a);也有很多雙操作數指令的一個(gè)操作數取自a(例如mov a,#00h);還有加、減、乘、除等算數指令的運算結果也經(jīng)常保留在a中,或者ab寄存器對中。
所以我們的程序就可以這樣來(lái)實(shí)現啦:首先給a賦值,再輸出到p0;然后延時(shí);接下來(lái)把a中的數進(jìn)行左移。然后重復上面的過(guò)程就可以啦。
四、試驗程序
org 0000h
start: clr p1.5
mov a,#0feh ;給a賦立即數,執行之后,a中的數據是11111110
loop: mov p0,a ;把a中的數據傳輸到p0
lcall delay ;(1)
rl a ;(2)
ajmp loop ;返回標號為loop的指令
delay: mov r6,#02h ;(3)
del1: mov r5,#0ffh ;(4)
del2: djnz r5,del2 ;(5)
djnz r6,del1 ;(6)
ret ;(7)
end
注釋?zhuān)?/p>
1、這是一個(gè)子程序調用指令。在程序設計中,常常把具有一定功能的公用程序編成子程序,以便讓主程序調用。
該指令的執行過(guò)程是這樣的:當執行lcall指令后,程序就轉到lcall后面標號delay指定的程序處往下執行,當執行遇到ret指令時(shí),就返回lcall指令下面的一條指令,即rl a指令。
從上面的分析,我們可以知道:標號為delay的程序應該是一段延時(shí)程序,那么它到底延時(shí)了多長(cháng)時(shí)間呢?我們一會(huì )給大家講解這個(gè)時(shí)間的計算方法,先往下看吧。
同樣,子程序調用也有兩條指令:acall和lcall。兩者的區別是:acall指令調用的子程序起始地址必須和acall后面的第一條指令在同一個(gè)2k區域的程序存儲器內;而lcall指令可以調用存放在程序存儲器中64K字節范圍內的任何地方的子程序。簡(jiǎn)單的說(shuō)就是acall調用的范圍小,而lcall的范圍大。如果你拿不準的話(huà),就用lcall吧。
2、這條指令的功能是:把累加器a中的內容向左移動(dòng)一位,最高位的內容A7被移動(dòng)到最低位A0,圖示如下:

3、現在我們來(lái)分析delay子程序的延時(shí)時(shí)間:
我們先看(3)(4)(5)(6)(7)這樣幾個(gè)語(yǔ)句:
(3)的意思是給r6賦值02h。r6是什么?我們好像以前沒(méi)有說(shuō)過(guò)。大家先知道它也是一個(gè)8位的寄存器就行啦,關(guān)于它的內容,我們下面在介紹。
(4)的意思和(3)類(lèi)似,不再贅述。
(5)應用了djnz指令,這個(gè)指令的意思是:減1不為0轉移。因此語(yǔ)句(6)的意思是:把r5中間存的內容減去1,如果不是0,就繼續執行該條語(yǔ)句,否則,執行下面的語(yǔ)句。
(6)根據上面的分析我們知道:(6)的意思是:把r6中的內容減1,如果不是0,就返回標號為del1的程序,重新給r5賦值0ffh,然后在對r5進(jìn)行減1運算。
從分析可見(jiàn),如果延時(shí)程序執行完,djnz指令總的執行次數是:02h×0ffh,即2×255=510次。
可見(jiàn),如果我們知道執行一次djnz指令的時(shí)間,我們就可以算出這個(gè)程序的延時(shí)時(shí)間了。那么執行一次djnz指令需要多少時(shí)間呢?
單片機的指令執行起來(lái)所花費的時(shí)間是不一樣的,有的指令執行時(shí)間短,只需要1個(gè)機器周期,而有的指令執行時(shí)間長(cháng),需要4個(gè)機器周期。Djnz指令的執行時(shí)間是2個(gè)機器周期。
每一個(gè)機器周期又是多長(cháng)呢?從相關(guān)教材上,我們知道1個(gè)機器周期是振蕩周期的12倍。
而振蕩周期T=1/振蕩頻率=1/12MHZ
所以延時(shí)程序的總的延時(shí)時(shí)間是:2×255×2×12×(1/12MHZ)=1ms
好啦,現在把上面的程序下載到單片機中,你看到了什么?
怎么回事,所有的燈都亮啦!
當然啦,因為我們的延時(shí)太短啦,只有1ms,所以我們的眼睛根本分辨不出來(lái)。我們現在把延時(shí)增加為100ms,程序修改如下:
org 0000h
start: clr p1.5
mov a,#0feh
loop: mov p0,a
lcall delay
rl a
ajmp loop
delay: mov r7,#100 ;把1ms延時(shí)子程序執行100次
del1: mov r6,#02h
del2: mov r5,#0ffh
del3: djnz r5,del3
djnz r6,del2
djnz r7,del1
ret
end
現在再看看,一切正常啦,ok!
4、現在來(lái)看看寄存器R的問(wèn)題
單片機的存儲器結構和常見(jiàn)的微型計算機的配置方式不同,把程序存儲器和數據存儲器分開(kāi)。程序存儲器用來(lái)存放程序,數據存儲器用來(lái)存放程序運行需要的常數和變量。
單片機的數據存儲器分為內部存儲器和外部存儲器,用mov訪(fǎng)問(wèn)內部數據存儲器,用movx訪(fǎng)問(wèn)外部數據存儲器。
內部數據存儲器是最靈活的地址空間,一共有256字節。這256個(gè)字節被分為兩組:00h~7fh的低128字節是內部RAM區;80h~ffh的高128字節為特殊功能寄存器區。其中低128字節的地址分配如下圖所示:

從圖上可見(jiàn),低128字節中,從00h~1fh共32個(gè)字節是四個(gè)通用的工作寄存器區,每一個(gè)區有8個(gè)工作寄存器,編號均為從R0~R7。
大家可能會(huì )問(wèn),既然四個(gè)工作寄存器組的名字都叫R0~R7,那么,上面的程序中間用的寄存器到底是哪個(gè)呢?
當前程序使用的工作寄存器區是有程序狀態(tài)字PSW決定的。
那么PSW又在哪里呢?
剛才我們說(shuō)到80h~ffh的高128字節是特殊功能寄存器區,PSW就在這個(gè)區里面。這個(gè)區域還有很多別的特殊功能寄存器,大家可以參考相關(guān)資料。
PSW是一個(gè)8位的寄存器,它各位的說(shuō)明如下:

其中,決定選擇哪個(gè)寄存器區的是RS1和RS0這兩位,為00時(shí),選擇0區;01時(shí)選擇1區;10時(shí)選擇2區;11時(shí)選擇3區。
大家可能會(huì )問(wèn),程序中間并沒(méi)有給這個(gè)寄存器賦值,那么它到底選擇哪個(gè)區域呢?
由于單片機被復位后,所有的寄存器請零,所以在本程序中,缺省的使用的是0區的寄存器組。
5、課后練習
(1)、學(xué)習該試驗中出現的理論知識,包括程序存儲器,數據存儲器的地址分配,和相關(guān)指令。
(2)、編寫(xiě)一個(gè)跑馬燈程序,讓二極管從左至右發(fā)光,延遲時(shí)間是1s,即1000ms。注意,可不是把上面程序中的mov r7,#100,改成mov r7,#1000,那么簡(jiǎn)單哦。
評論