新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應用 > 單片機學習之六:基本I/O口試驗二:跑馬燈

單片機學習之六:基本I/O口試驗二:跑馬燈

作者: 時間:2016-09-18 來源:網(wǎng)絡 收藏

  一、試驗現(xiàn)象:

本文引用地址:http://m.butianyuan.cn/article/201609/297082.htm

  二極管從右至左依次發(fā)光。

  二、試驗目的:

  l 掌握寄存器A,Rn的使用方法

  l 掌握左移指令

  l 掌握延時程序的編寫

  三、任務分析:

  電路圖同試驗1,有了上一個試驗的基礎(chǔ),這個程序?qū)ξ覀兙蜎]有什么難度啦。我們可以這樣作:

  首先:mov p0,#ofeh(讓最右邊的燈亮),然后經(jīng)過一段延時,再:mov p1,#ofdh,這樣依次賦值,直到:mov p0,#07fh(最左面的燈亮)。然后用ajmp指令返回,讓燈光再重新開始循環(huán)。

  這樣固然可以,但是程序不夠簡單明了,我們要寫8個mov語句。設(shè)想一下,假如有幾十個燈,那寫起來不是麻煩死啦?

  好在有一條左移指令rl a,它的作用是把累加器a中的數(shù)循環(huán)左移。

  順便說一下累加器a,它是中的最常用的寄存器,大部分單操作數(shù)的指令都以a作為操作對象(例如rl a);也有很多雙操作數(shù)指令的一個操作數(shù)取自a(例如mov a,#00h);還有加、減、乘、除等算數(shù)指令的運算結(jié)果也經(jīng)常保留在a中,或者ab寄存器對中。

  所以我們的程序就可以這樣來實現(xiàn)啦:首先給a賦值,再輸出到p0;然后延時;接下來把a中的數(shù)進行左移。然后重復上面的過程就可以啦。

  四、試驗程序

  org 0000h

  start: clr p1.5

  mov a,#0feh ;給a賦立即數(shù),執(zhí)行之后,a中的數(shù)據(jù)是11111110

  loop: mov p0,a ;把a中的數(shù)據(jù)傳輸?shù)絧0

  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

  注釋:

  1、這是一個子程序調(diào)用指令。在程序設(shè)計中,常常把具有一定功能的公用程序編成子程序,以便讓主程序調(diào)用。

  該指令的執(zhí)行過程是這樣的:當執(zhí)行l(wèi)call指令后,程序就轉(zhuǎn)到lcall后面標號delay指定的程序處往下執(zhí)行,當執(zhí)行遇到ret指令時,就返回lcall指令下面的一條指令,即rl a指令。

  從上面的分析,我們可以知道:標號為delay的程序應該是一段延時程序,那么它到底延時了多長時間呢?我們一會給大家講解這個時間的計算方法,先往下看吧。

  同樣,子程序調(diào)用也有兩條指令:acall和lcall。兩者的區(qū)別是:acall指令調(diào)用的子程序起始地址必須和acall后面的第一條指令在同一個2k區(qū)域的程序存儲器內(nèi);而lcall指令可以調(diào)用存放在程序存儲器中64K字節(jié)范圍內(nèi)的任何地方的子程序。簡單的說就是acall調(diào)用的范圍小,而lcall的范圍大。如果你拿不準的話,就用lcall吧。

  2、這條指令的功能是:把累加器a中的內(nèi)容向左移動一位,最高位的內(nèi)容A7被移動到最低位A0,圖示如下:

  

 

  3、現(xiàn)在我們來分析delay子程序的延時時間:

  我們先看(3)(4)(5)(6)(7)這樣幾個語句:

  (3)的意思是給r6賦值02h。r6是什么?我們好像以前沒有說過。大家先知道它也是一個8位的寄存器就行啦,關(guān)于它的內(nèi)容,我們下面在介紹。

  (4)的意思和(3)類似,不再贅述。

  (5)應用了djnz指令,這個指令的意思是:減1不為0轉(zhuǎn)移。因此語句(6)的意思是:把r5中間存的內(nèi)容減去1,如果不是0,就繼續(xù)執(zhí)行該條語句,否則,執(zhí)行下面的語句。

  (6)根據(jù)上面的分析我們知道:(6)的意思是:把r6中的內(nèi)容減1,如果不是0,就返回標號為del1的程序,重新給r5賦值0ffh,然后在對r5進行減1運算。

  從分析可見,如果延時程序執(zhí)行完,djnz指令總的執(zhí)行次數(shù)是:02h×0ffh,即2×255=510次。

  可見,如果我們知道執(zhí)行一次djnz指令的時間,我們就可以算出這個程序的延時時間了。那么執(zhí)行一次djnz指令需要多少時間呢?

  的指令執(zhí)行起來所花費的時間是不一樣的,有的指令執(zhí)行時間短,只需要1個機器周期,而有的指令執(zhí)行時間長,需要4個機器周期。Djnz指令的執(zhí)行時間是2個機器周期。

  每一個機器周期又是多長呢?從相關(guān)教材上,我們知道1個機器周期是振蕩周期的12倍。

  而振蕩周期T=1/振蕩頻率=1/12MHZ

  所以延時程序的總的延時時間是:2×255×2×12×(1/12MHZ)=1ms

  好啦,現(xiàn)在把上面的程序下載到單片機中,你看到了什么?

  怎么回事,所有的燈都亮啦!

  當然啦,因為我們的延時太短啦,只有1ms,所以我們的眼睛根本分辨不出來。我們現(xiàn)在把延時增加為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延時子程序執(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)在來看看寄存器R的問題

  單片機的存儲器結(jié)構(gòu)和常見的微型計算機的配置方式不同,把程序存儲器和數(shù)據(jù)存儲器分開。程序存儲器用來存放程序,數(shù)據(jù)存儲器用來存放程序運行需要的常數(shù)和變量。

  單片機的數(shù)據(jù)存儲器分為內(nèi)部存儲器和外部存儲器,用mov訪問內(nèi)部數(shù)據(jù)存儲器,用movx訪問外部數(shù)據(jù)存儲器。

  內(nèi)部數(shù)據(jù)存儲器是最靈活的地址空間,一共有256字節(jié)。這256個字節(jié)被分為兩組:00h~7fh的低128字節(jié)是內(nèi)部RAM區(qū);80h~ffh的高128字節(jié)為特殊功能寄存器區(qū)。其中低128字節(jié)的地址分配如下圖所示:

  

 

  從圖上可見,低128字節(jié)中,從00h~1fh共32個字節(jié)是四個通用的工作寄存器區(qū),每一個區(qū)有8個工作寄存器,編號均為從R0~R7。

  大家可能會問,既然四個工作寄存器組的名字都叫R0~R7,那么,上面的程序中間用的寄存器到底是哪個呢?

  當前程序使用的工作寄存器區(qū)是有程序狀態(tài)字PSW決定的。

  那么PSW又在哪里呢?

  剛才我們說到80h~ffh的高128字節(jié)是特殊功能寄存器區(qū),PSW就在這個區(qū)里面。這個區(qū)域還有很多別的特殊功能寄存器,大家可以參考相關(guān)資料。

  PSW是一個8位的寄存器,它各位的說明如下:

  

 

  其中,決定選擇哪個寄存器區(qū)的是RS1和RS0這兩位,為00時,選擇0區(qū);01時選擇1區(qū);10時選擇2區(qū);11時選擇3區(qū)。

  大家可能會問,程序中間并沒有給這個寄存器賦值,那么它到底選擇哪個區(qū)域呢?

  由于單片機被復位后,所有的寄存器請零,所以在本程序中,缺省的使用的是0區(qū)的寄存器組。

  5、課后練習

  (1)、學習該試驗中出現(xiàn)的理論知識,包括程序存儲器,數(shù)據(jù)存儲器的地址分配,和相關(guān)指令。

  (2)、編寫一個程序,讓二極管從左至右發(fā)光,延遲時間是1s,即1000ms。注意,可不是把上面程序中的mov r7,#100,改成mov r7,#1000,那么簡單哦。



關(guān)鍵詞: 單片機 跑馬燈

評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉