天天看點

《51單片機應用開發從入門到精通》——2.5 用取表方式實作燈移動

本節書摘來異步社群《51單片機應用開發從入門到精通》一書中的第2章,第2.5節,作者:張華傑 ,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視

51單片機應用開發從入門到精通

功能說明:單片機端口接8隻led,程式設計時利用取表的方法,使端口p1的led先一次點亮1隻跳躍左移,點亮順序為p1.0、p1.2、p1.4、p1.6;接着一次點亮2隻,從左向右移動2次;一次點亮3隻,左右移3次;然後4隻燈p1.0、p1.2、p1.4、p1.6與p1.1、p1.3、p1.5、p1.7互動點亮4次;最後8隻燈閃爍6次,不斷循環。

1.流程圖

程式設計流程如圖2-3所示。

《51單片機應用開發從入門到精通》——2.5 用取表方式實作燈移動

2.程式

彙編語言編寫的用取表方式實作燈移動源程式代碼如下:

1.标号說明

start:起始程式的進入點。

loop:循環操作的進入點。

loop1:輸出循環的進入點。

delay:延時子程式的進入點。

del1:延時重複遞減判斷的進入點1。

del2:延時重複遞減判斷的進入點2。

table:代碼表的進入點。

2.寄存器使用配置設定情況

程式中a、p、r5、r6、r7、dptr為寄存器,其中a、p、r5、r6、r7寄存器的作用與前節相同。

dptr是新用到的寄存器,也是唯一的16位專用寄存器,它是由兩個8位寄存器dph和dpl拼裝而成,其中dph為dptr的高8位,dpl為dptr的低8位。它既可作為一個16位寄存器來使用,也可以作為兩個獨立的8位寄存器(dph和dpl)來使用。

我們把代碼表存入dptr,确切地說是将代碼表的首位址table送到dptr中作基位址,a作為變址寄存器,基址寄存器和變址寄存器的内容相加(@a + dptr)形成16位位址,該位址既是操作數的位址,也是存入位址指針(也叫資料指針)。知道了位址指針,按照位址指針所指,自然就能取到代碼表中的控制碼了。

3.程式分析解釋

本程式利用取表方式實作亮燈的移動。

利用取表的方式将控制碼建成一個表,利用“mov dptr, #table”語句存表,再利用“movc a, @a + dptr”語句從表中讀取出控制碼,這種方法可友善地處理一些複雜的控制動作,下面重點介紹這一部分。

第01~09行代碼的作用是存表、讀取表并輸出,是程式的主要部分。

01:存入table表,用來控制燈的一組組十六進制數控制碼建成一個表,取表名為table。将table表存放的位址存入特殊功能寄存器dptr中,以便查找。

所謂存表是指存入表的首位址,即表的位址指針或資料指針。位址指針指向第1行第1位控制碼的位置。總之,位址指針指向哪個位置就到哪個位置讀取控制碼。

02:将寄存器a中的内容清除為0。

03:查表讀取控制碼。“movc a, @a + dptr”是一條很重要的查表語句,它将a + dptr指定的表位址的資料送入寄存器a中。當程式第一次運作時,位址指針指向的位置是表中首位放置的控制碼0feh,将0feh取出并存入寄存器a中。

04:判斷讀取出的控制碼是否為結束碼01h,如果不是則跳轉到loop1處。cjne指令的功能是比較兩個操作數,若不相等就跳轉,隻有相等時才繼續向下運作。01h是結束标志碼,放在表中的最後位置。

如果寄存器a中的數不是01h,即不相等,說明表還沒有查完,程式跳轉到loop1處繼續查表讀取出控制碼并輸出。

若寄存器a中的數是01h,即兩個操作數相等了,說明表已經查完一遍,程式執行下一條語句。

05:程式跳轉到标号start處,即跳轉到程式開始處,重新設定顯示值。

06:将取來的控制碼送入p1并輸出。

07:調用0.5s延時子程式。

08:資料指針加1,指向下一個操作碼。inc指令的功能是使寄存器a中的資料加1,即位址指針向下移動一個位置,指向第二個控制碼,為下一次取碼做準備。

09:跳轉到loop處,重新開始,不斷循環。

10~16:0.5s延時子程式。

第18~32行代碼為控制碼編制表,表名為table。

18:單燈跳躍左移控制碼。

20~23:兩隻燈從左向右移動控制碼。

25:3隻燈左右移控制碼。

27:4隻燈互動點亮控制碼。

亮燈的移動是由控制碼控制的,控制碼采用十六進制數,如果将十六進制碼換成二進制碼就可以清楚地看出燈是怎樣被控制的。

29~31:閃爍6次控制碼。控制碼00h表示8個燈都亮(0表示亮);控制碼0ffh表示8個燈都滅(1表示滅)。一亮一滅形成一次閃爍,共6對控制碼,閃爍6次。

32:結束控制碼。結束碼可以是任意的數,存放的位置要在表的最後,标志控制碼已經結束。此時,由于第04行語句的作用,當寄存器a中的數是01h,即兩個操作數相等,程式将執行下一條語句,即跳轉到标号loop處,程式重新開始。

如果沒有結束碼,當取表碼結束後,程式運作下一行end指令,使整個程式結束。

此外,制表時要注意,每一行控制碼的前邊都要加僞指令db,db是定義位元組的指令。

33:程式結束。

4.邊用邊學指令

本節使用新的指令有:movc、inc、clr、cjne和db。

movc:movc和前邊經常用到的mov指令都屬于資料傳送類指令,基本功能是傳送資料,但使用上有所差別。movc的功能是将表中查到的一組資料送到寄存器a。常用形式如“movc a, @a + dptr”,意思是将a + dptr指定的記憶體位址的資料傳送到寄存器a,是以也稱查表指令movc。

inc:是算術運算類指令。算術運算類指令包括有加、減、乘和除法指令,其中inc指令的功能是使累加器加1。

clr:屬于位移類指令。clr的功能是将累加器a清0。

cjne:屬于控制轉移類指令。cjne與前邊介紹的djnz指令都是有條件轉移指令,djnz的條件是寄存器減1不為0轉移,一般是與寄存器配合使用,用在控制已知循環次數的循環結構程式中。而cjne的條件是對兩數進行比較,不相等則轉移,多用在分支結構的程式中。

db:是僞指令。其功能是從指定的位址單元開始,定義若幹個位元組作為記憶體單元的内容。

5.本章用過的指令歸類

資料傳送類指令:mov、movc。

算術運算類指令:inc。

邏輯運算及位移類指令:rl、rr、clr。

控制轉移類指令:jmp、djnz、acall、ret、cjne。

位操作類指令:cpl。

僞指令:end、db。

本節模拟仿真時主要注意觀察取控制碼的過程。

運作程式第1行語句時,把表table的首位址存入到dptr寄存器。

注意,在特殊功能寄存器視窗中看不到dptr,而是看到兩個獨立的8位寄存器dph和dpl,dptr寄存器是由dph和dpl組成的。此時dpl = 1ch,此位址是表的開頭第1個控制碼的位址,也稱位址指針或資料指針,即該指針指向表中的第1個控制碼0feh。

運作程式第2行語句時将寄存器a清0。

運作程式第3行語句時,由于在第3行語句中是将a和dptr兩個寄存器内容相加,此時a為0,相加後仍為原dptr的位址,此位址指針指向的是第1個控制碼0feh,是以,送入寄存器a的控制碼是0feh。

接下來再運作第6行語句時将控制碼0feh送入p1并輸出。

運作到第8行語句“inc dptr”時,位址指針加1即1ch + 01h = 1dh,是以dpl = 1dh,此位址指針指向的是第2個控制碼0fbh,依次不斷循環。

将寫入程式的單片機插入實驗闆接通電源後,會看到單燈向左跳移1次,雙燈向右移動2次,3隻燈左右移動3次,4隻燈互動點亮,8隻燈閃爍6次,不斷循環。

如果将程式改動一下,把表table中的結束碼取消,再在實驗闆上運作程式,會看到亮燈在進行閃爍後,程式馬上停止,不再循環。

這是因為當表查完後,程式要執行下一個語句“end”,end是程式結束指令,是以程式就此結束。

如果想查完一遍表後程式不立即結束,需要在表中最後一行設定一個結束标志碼,當程式取到該結束标志碼時,通過判斷語句(如“cjne a,#01h,loop1”)的作用,使程式不運作結束語句end,而跳轉執行其他程式段。

利用查表方法編寫程式,可以很友善地完成一些複雜的控制功能。

首先通過db僞指令把控制碼制成一個表table,然後再通過查表的指令查表取碼。用于查表的指令有兩條:

繼續閱讀