單片機(jī)學(xué)習(xí)之六:基本I/O口試驗(yàn)二:跑馬燈
一、試驗(yàn)現(xiàn)象:
本文引用地址:http://www.ex-cimer.com/article/201609/297082.htm二極管從右至左依次發(fā)光。
二、試驗(yàn)?zāi)康模?/strong>
l 掌握寄存器A,Rn的使用方法
l 掌握左移指令
l 掌握延時(shí)程序的編寫
三、任務(wù)分析:
電路圖同試驗(yàn)1,有了上一個(gè)試驗(yàn)的基礎(chǔ),這個(gè)程序?qū)ξ覀兙蜎](méi)有什么難度啦。我們可以這樣作:
首先:mov p0,#ofeh(讓最右邊的燈亮),然后經(jīng)過(guò)一段延時(shí),再:mov p1,#ofdh,這樣依次賦值,直到:mov p0,#07fh(最左面的燈亮)。然后用ajmp指令返回,讓燈光再重新開(kāi)始循環(huán)。
這樣固然可以,但是程序不夠簡(jiǎn)單明了,我們要寫8個(gè)mov語(yǔ)句。設(shè)想一下,假如有幾十個(gè)燈,那寫起來(lái)不是麻煩死啦?
好在單片機(jī)有一條左移指令rl a,它的作用是把累加器a中的數(shù)循環(huán)左移。
順便說(shuō)一下累加器a,它是單片機(jī)中的最常用的寄存器,大部分單操作數(shù)的指令都以a作為操作對(duì)象(例如rl a);也有很多雙操作數(shù)指令的一個(gè)操作數(shù)取自a(例如mov a,#00h);還有加、減、乘、除等算數(shù)指令的運(yùn)算結(jié)果也經(jīng)常保留在a中,或者ab寄存器對(duì)中。
所以我們的程序就可以這樣來(lái)實(shí)現(xiàn)啦:首先給a賦值,再輸出到p0;然后延時(shí);接下來(lái)把a(bǔ)中的數(shù)進(jìn)行左移。然后重復(fù)上面的過(guò)程就可以啦。
四、試驗(yàn)程序
org 0000h
start: clr p1.5
mov a,#0feh ;給a賦立即數(shù),執(zhí)行之后,a中的數(shù)據(jù)是11111110
loop: mov p0,a ;把a(bǔ)中的數(shù)據(jù)傳輸?shù)絧0
lcall delay ;(1)
rl a ;(2)
ajmp loop ;返回標(biāo)號(hào)為loop的指令
delay: mov r6,#02h ;(3)
del1: mov r5,#0ffh ;(4)
del2: djnz r5,del2 ;(5)
djnz r6,del1 ;(6)
ret ;(7)
end
注釋:
1、這是一個(gè)子程序調(diào)用指令。在程序設(shè)計(jì)中,常常把具有一定功能的公用程序編成子程序,以便讓主程序調(diào)用。
該指令的執(zhí)行過(guò)程是這樣的:當(dāng)執(zhí)行l(wèi)call指令后,程序就轉(zhuǎn)到lcall后面標(biāo)號(hào)delay指定的程序處往下執(zhí)行,當(dāng)執(zhí)行遇到ret指令時(shí),就返回lcall指令下面的一條指令,即rl a指令。
從上面的分析,我們可以知道:標(biāo)號(hào)為delay的程序應(yīng)該是一段延時(shí)程序,那么它到底延時(shí)了多長(zhǎng)時(shí)間呢?我們一會(huì)給大家講解這個(gè)時(shí)間的計(jì)算方法,先往下看吧。
同樣,子程序調(diào)用也有兩條指令:acall和lcall。兩者的區(qū)別是:acall指令調(diào)用的子程序起始地址必須和acall后面的第一條指令在同一個(gè)2k區(qū)域的程序存儲(chǔ)器內(nèi);而lcall指令可以調(diào)用存放在程序存儲(chǔ)器中64K字節(jié)范圍內(nèi)的任何地方的子程序。簡(jiǎn)單的說(shuō)就是acall調(diào)用的范圍小,而lcall的范圍大。如果你拿不準(zhǔn)的話,就用lcall吧。
2、這條指令的功能是:把累加器a中的內(nèi)容向左移動(dòng)一位,最高位的內(nèi)容A7被移動(dòng)到最低位A0,圖示如下:
3、現(xiàn)在我們來(lái)分析delay子程序的延時(shí)時(shí)間:
我們先看(3)(4)(5)(6)(7)這樣幾個(gè)語(yǔ)句:
(3)的意思是給r6賦值02h。r6是什么?我們好像以前沒(méi)有說(shuō)過(guò)。大家先知道它也是一個(gè)8位的寄存器就行啦,關(guān)于它的內(nèi)容,我們下面在介紹。
(4)的意思和(3)類似,不再贅述。
(5)應(yīng)用了djnz指令,這個(gè)指令的意思是:減1不為0轉(zhuǎn)移。因此語(yǔ)句(6)的意思是:把r5中間存的內(nèi)容減去1,如果不是0,就繼續(xù)執(zhí)行該條語(yǔ)句,否則,執(zhí)行下面的語(yǔ)句。
(6)根據(jù)上面的分析我們知道:(6)的意思是:把r6中的內(nèi)容減1,如果不是0,就返回標(biāo)號(hào)為del1的程序,重新給r5賦值0ffh,然后在對(duì)r5進(jìn)行減1運(yùn)算。
從分析可見(jiàn),如果延時(shí)程序執(zhí)行完,djnz指令總的執(zhí)行次數(shù)是:02h×0ffh,即2×255=510次。
可見(jiàn),如果我們知道執(zhí)行一次djnz指令的時(shí)間,我們就可以算出這個(gè)程序的延時(shí)時(shí)間了。那么執(zhí)行一次djnz指令需要多少時(shí)間呢?
單片機(jī)的指令執(zhí)行起來(lái)所花費(fèi)的時(shí)間是不一樣的,有的指令執(zhí)行時(shí)間短,只需要1個(gè)機(jī)器周期,而有的指令執(zhí)行時(shí)間長(zhǎng),需要4個(gè)機(jī)器周期。Djnz指令的執(zhí)行時(shí)間是2個(gè)機(jī)器周期。
每一個(gè)機(jī)器周期又是多長(zhǎng)呢?從相關(guān)教材上,我們知道1個(gè)機(jī)器周期是振蕩周期的12倍。
而振蕩周期T=1/振蕩頻率=1/12MHZ
所以延時(shí)程序的總的延時(shí)時(shí)間是:2×255×2×12×(1/12MHZ)=1ms
好啦,現(xiàn)在把上面的程序下載到單片機(jī)中,你看到了什么?
怎么回事,所有的燈都亮啦!
當(dāng)然啦,因?yàn)槲覀兊难訒r(shí)太短啦,只有1ms,所以我們的眼睛根本分辨不出來(lái)。我們現(xiàn)在把延時(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í)子程序執(zhí)行100次
del1: mov r6,#02h
del2: mov r5,#0ffh
del3: djnz r5,del3
djnz r6,del2
djnz r7,del1
ret
end
現(xiàn)在再看看,一切正常啦,ok!
4、現(xiàn)在來(lái)看看寄存器R的問(wèn)題
單片機(jī)的存儲(chǔ)器結(jié)構(gòu)和常見(jiàn)的微型計(jì)算機(jī)的配置方式不同,把程序存儲(chǔ)器和數(shù)據(jù)存儲(chǔ)器分開(kāi)。程序存儲(chǔ)器用來(lái)存放程序,數(shù)據(jù)存儲(chǔ)器用來(lái)存放程序運(yùn)行需要的常數(shù)和變量。
單片機(jī)的數(shù)據(jù)存儲(chǔ)器分為內(nèi)部存儲(chǔ)器和外部存儲(chǔ)器,用mov訪問(wèn)內(nèi)部數(shù)據(jù)存儲(chǔ)器,用movx訪問(wèn)外部數(shù)據(jù)存儲(chǔ)器。
內(nèi)部數(shù)據(jù)存儲(chǔ)器是最靈活的地址空間,一共有256字節(jié)。這256個(gè)字節(jié)被分為兩組:00h~7fh的低128字節(jié)是內(nèi)部RAM區(qū);80h~ffh的高128字節(jié)為特殊功能寄存器區(qū)。其中低128字節(jié)的地址分配如下圖所示:
從圖上可見(jiàn),低128字節(jié)中,從00h~1fh共32個(gè)字節(jié)是四個(gè)通用的工作寄存器區(qū),每一個(gè)區(qū)有8個(gè)工作寄存器,編號(hào)均為從R0~R7。
大家可能會(huì)問(wèn),既然四個(gè)工作寄存器組的名字都叫R0~R7,那么,上面的程序中間用的寄存器到底是哪個(gè)呢?
當(dāng)前程序使用的工作寄存器區(qū)是有程序狀態(tài)字PSW決定的。
那么PSW又在哪里呢?
剛才我們說(shuō)到80h~ffh的高128字節(jié)是特殊功能寄存器區(qū),PSW就在這個(gè)區(qū)里面。這個(gè)區(qū)域還有很多別的特殊功能寄存器,大家可以參考相關(guān)資料。
PSW是一個(gè)8位的寄存器,它各位的說(shuō)明如下:
其中,決定選擇哪個(gè)寄存器區(qū)的是RS1和RS0這兩位,為00時(shí),選擇0區(qū);01時(shí)選擇1區(qū);10時(shí)選擇2區(qū);11時(shí)選擇3區(qū)。
大家可能會(huì)問(wèn),程序中間并沒(méi)有給這個(gè)寄存器賦值,那么它到底選擇哪個(gè)區(qū)域呢?
由于單片機(jī)被復(fù)位后,所有的寄存器請(qǐng)零,所以在本程序中,缺省的使用的是0區(qū)的寄存器組。
5、課后練習(xí)
(1)、學(xué)習(xí)該試驗(yàn)中出現(xiàn)的理論知識(shí),包括程序存儲(chǔ)器,數(shù)據(jù)存儲(chǔ)器的地址分配,和相關(guān)指令。
(2)、編寫一個(gè)跑馬燈程序,讓二極管從左至右發(fā)光,延遲時(shí)間是1s,即1000ms。注意,可不是把上面程序中的mov r7,#100,改成mov r7,#1000,那么簡(jiǎn)單哦。
評(píng)論