官术网_书友最值得收藏!

任務二 閃爍燈

任務描述

使用跳轉分支指令設計一個延時程序,編寫延時程序實現LED燈閃爍。

任務分析

通過本任務的學習和訓練,我們將實現以下目標:(1)掌握51單片機的分支跳轉指令。

(2)掌握單片機延時程序的嵌套結構。

任務實施

一、匯編語言控制轉移指令

通常情況下,單片機是由PC的自加一順序運行的。控制轉移類指令能使程序功能更加靈活,通過給PC賦值實現程序的分支跳轉。控制轉移類指令可分為6個子類。

1.無條件轉移指令

顧名思義,無條件轉移指令是強制性地更改PC的值,不需要其他條件。無條件轉移指令共有4條。

◆ AJMP addr11;addr11→(PC10-0

說明:短跳轉指令,實現2K字節范圍內的無條件轉移,指令執行后將addr11送入

PC低11位(10-0),高5位保持不變,因此跳轉的目標地址必須與執行后PC值的高5位相同,以保證在2K字節范圍內跳轉。AJMP跳轉示意圖如圖119所示。

例如:AJMP LK

執行前,PC的值為指令“AJMPLK”所在的地址。執行后,PC的值為指令標簽LK所代表的地址。

圖1-19 AJMP跳

轉示意圖

補充:使用AJMP指令相當于將64K分成了32個區間,每個區間2KB字節,每次跳轉只能在固定的某一個2K區間完成。

◆ SJMP rel;(PC)+rel→(PC)

說明:程序分支指令,執行該指令的過程中PC加2之后再與rel相加得出目標地址,rel是8位帶符號的二進制補碼數,因此SJMP可實現向前128字節向后127字節的跳轉功能或原地死循環。

例如:當前“SJMP 22H”指令的地址為1234H,執行該指令過程中PC加2之后,

再計算(PC)+22H=1258H后賦予PC,該指令執行結束。另外可以使用“LOOP:

SJMP LOOP”讓程序原地踏步,在轉移類指令中可以使用“$”來代表當前指令所在地

址標簽,因此“LOOP:SJMP LOOP”可用“SJMP $”代替。

注意:正整數的二進制補碼與原碼相同,如2的補碼為0000 0010B,即02H。負整數的補碼為其絕對值原碼的反碼加1,如-2的絕對值為2,原碼為0000 0010B,反碼為

1111 1101B,加1后為1111 1110B,即FEH。

◆ LJMP addr16

說明:長跳指令,將16位地址addr16賦予PC實現64KB地址范圍的跳轉,即ad

dr16→(PC)。

例如:LJMP MAIN

執行前,PC的值為指令“SJMP MAIN”的地址。

執行后,PC的值為指令標簽MAIN所在指令的地址。

◆ JMP@A+DPTR

說明:間接跳轉指令,將DPTR+A的值賦予PC實現程序的分支跳轉,通常給予

DPTR一個固定的值作為基址,A作為變址,即(A+DPTR)→(PC)。

例如:JMP@A+DPTR

執行前,PC為指令“JMP@A+DPTR”的地址。

執行后,PC的值為A+DPTR,將從此地址開始執行。2.條件轉移指令

需要一定條件才執行程序的轉移,當規定的條件滿足,則進行轉移,否則順序執行。包括字節條件與位條件判斷,共有7條指令。

◆ JZ rel

說明:如果累加器A=0,則(PC)+rel→(PC),否則順序執行。rel為8位帶符號

二進制補碼,可向前128字節或向后127字節分支轉移。該指令框圖如圖1-20所示。

例如:JZ LOOP

若執行前A=0,則執行后跳至LOOP標簽所代表的地址,否則順序執行。

◆ JNZ rel

說明:如果累加器A≠0,則(PC)+rel→

(PC),否則順序執行。

◆ JC rel

圖1-20 有條件跳轉指令框圖

說明:如果PSW寄存器位CY=1,則

(PC)+rel→(PC),否則順序執行。

◆ JNC rel

說明:如果CY≠0,則(PC)+rel→(PC),否則順序執行。◆ JBbit,rel

說明:如果bit位值為1,則(PC)+rel→(PC),否則順序執行。例如:JB54H,RGB

若執行前地址為54H的位內容為1,則跳轉至RGB標簽所代表的地址執行。

◆ JNB bit,rel

說明:如果bit位的值為0,則(PC)+rel→(PC),否則順序執行。◆ JBCbit,rel

說明:如果bit位的值為1,則(PC)+rel→(PC),然后bit位清零,否則順序

執行。

3.子程序調用指令

在一個程序中經常會碰到反復多次執行某個程序段的情況,如果重復編寫這個程序段會使整個程序變得冗長而雜亂,可讀性與可維護性都極低。采用子程序結構便可解決此問題,將在程序中重復出現的程序段作為一個子程序,在程序需要時再調用即可,子程序調用指令的功能便是為了實現子程序的調用與返回。

◆ ACALL addr11

說明:短調用指令,能實現2K字節范圍內的子程序調用,執行后PC的低11位值為

addr11,高5位不變,即目標地址與執行后PC值的高5位必須相同,另外為了保護斷點,把PCL(低8位)與PCH(高8位)

分別順序壓入堆棧,即(SP)+1→(SP),(PCL)→((SP)),(SP)+1→(SP),(PCH)→((SP)),addr11→(PC10-0 )。

ACALL子程序調用示意圖如圖121所示。

例如:ACALL DELAY

圖1-21 ACALL子程序

調用示意圖

執行前,PC為指令“ACALL DELAY”的地址。

執行后,PC的值為指令標簽DELAY所代表的地址。

◆ LCALL addr16

說明:長調用指令,可實現64KB地址范圍跳轉,即(SP)+1→(SP),(PCL)→((SP)),(SP)+1→(SP),(PCH)→((SP)),addr16→(PC)。

例如:LCALL DIS

執行前,PC為指令“LCALL DIS”的地址。

執行后,PC的值為指令標簽DIS所代表的地址。

◆ RET

說明:子程序返回指令,無參數。將堆棧中的地址恢復到PC,即((SP))→

(PCH),(SP)-1→(SP),((SP))→(PCL),(SP)-1→(SP)。

◆ RETI

說明:中斷服務子程序返回指令,無參數,與RET類似,當中斷條件成立,則轉向執行相應中斷服務子程序,同時也要保護斷點,遇RETI返回斷點處繼續執行主程序。不同的是該指令會清除相應的中斷標志位。

4.比較轉移指令

根據比較結果決定是否跳轉,指令格式為“CJNES1,S2,rel”,前兩個操作數為8

位無符號二進制數。S1可為A、Rn或@Ri,S2可為direct或#data,偏移地址rel為8

位二進制補碼數,即可向前128字節或向后127字節跳轉。另外,如果S1<S2,則進位

標志CY=1。

◆ CJNE A,direct,rel

說明:如果(A)≠(direct)則跳轉至目標地址,否則順序執行。

例如:CJNE A,5BH,GOK 24

執行前,(A)=39H,(5BH)=A5H,(C)=0B,PC為將要執行的指令的地址。

執行后,(A)=39H,(5BH)=A5H,(C)=1B,PC指令標簽GOK所代表的地址。◆ CJNEA,#data,rel

說明:若(A)≠data則跳轉至目標地址,否則順序執行。

◆ CJNERn,#data,rel

說明:若(Rn)≠data則跳轉至目標地址,否則順序執行。

◆ CJNE@Ri,#data,rel

說明:若((Ri))≠data則跳轉至目標地址,否則順序執行。5.計數循環指令

功能是將源操作數的內容減1,并判斷是否為0,是則順序運行,否則跳轉。源操作數可以為工作寄存器或存儲器地址,使用該指令可以實現循環計數功能,主要應在延時程序中。

◆ DJNZ Rn,rel

說明:先將(Rn)的內容減1,若(Rn)≠0則跳轉,否則順序運行。

◆ DJNZ direct,rel

說明:將(direct)的內容減1,若(direct)≠0則跳轉,否則順序運行。

6.標簽在控制轉移類中的使用

前面已經介紹了AJMP addr11指令的基本功能和用法,AJMP是2K字節的跳轉指

令,addr11表示一個11位的二進制數。執行完AJMP后PC低11位的值為addr11,能實

現程序的分支跳轉。

假如現在需要根據P1口的輸入狀態不斷地刷新P0口的輸出狀態,程序如下

該程序編譯后總共5字節,“MOV P0,P1”指令3字節存儲在0000H~0002H中,完成讀取輸入刷新輸出的功能。“AJMP 00H”指令2字節存儲在0003H~0004H中,功

能是跳轉到0000H單元(即PC=0000H)重新執行第一個指令,完成不斷刷新輸出的功能。但實際中并不會使用“AJMP 00H”的形式表示,因為一般程序中還會有其他的功能程序段,其跳轉目標地址不清楚或者很難計算,這種形式很不方便,看下面的程序。

因此使用指令標簽來表示,即在指令前加一個標簽表示該指令所在的ROM地址,使用該標簽代替十六進制數形式如下。

FRESH為什么可以代替指令“MOV P0,P1”的地址呢?這是在編譯時自動計算的,編譯過程中會將其實際ROM地址代替FRESH標簽,知道如何使用即可。

另外在控制轉移類中可以使用“$”來代表當前指令的指令標簽,常用于等待延時與循環延時或進入死循環,如上面的“JB P3.4,$”是用于按鍵等待延時,如果P3.4為1則跳回到該指令一直循環判斷,如果為0則順序執行。或使用“DJNZ Rn,$”來進行延時,當(Rn)減1后不為0,則跳回到該指令繼續循環執行,直至(Rn)為0后才順序執行,這就能達到延時的效果。

二、匯編語言空操作指令

空操作指令是一條特殊的跳轉指令,功能是跳轉到下一條指令的地址,相當于什么都不做只等待一個機器周期,該指令用于特殊延時場合。

◆ NOP

說明:無參數,空操作。

三、延時程序設計

單片機的運算速度在幾兆赫茲到幾十兆赫茲的范圍內不等,以12MHz的51單片機為例,每個機器周期剛好為1μs,每條指令執行時間為1μs、2μs或4μs。對于人眼來說,100ms的響應時間都是無法分辨出來的。假如閃爍頻率為1s,要使人能看到LED燈的閃爍,延時要求為500ms,則必須使用延時程序段來實現。在與某些低速設備交互數據時單片機同樣需要等待,這也是對延時另一個主要的需求應用,在后面的實戰中將會描述。

延時的基本結構就是循環,根據給定的條件不停地循環運行直至條件成立退出循環結構,在程序執行過程中實現延時。從前面的控制轉移類指令介紹中,我們知道可用于循環

計數的指令DJNZ Rn,rel或DJNZ direct,rel,它們功能基本相同,只是源操作數不同,

將(Rn)或(direct)的值減1,然后判斷是否為0,不為0則跳轉,為0則順序執行。

例如:

第一條MOV指令在R3中存入立即數200,第二條指令將R3減1為199后,判斷是否為0,不為0則跳回該DJNZ指令繼續循環執行,如此循環執行200次該指令后R3的值變為0,然后順序執行下一條指令。循環的時間為指令執行時間乘以執行次數,即2×200=400μs(DJNZ的雙周期指令)。嚴格說來第1條指令也屬于延時范圍內,但是它只被執行1次因此可忽略不計。上面的例子中源操作數為一個字節,最長延時為255(FFH)×2=510μs,時間遠遠不夠,因此采用二重循環結構:

在兩條賦值指令之后進入循環,首先在第一條循環計數指令執行200次后R4為0,

接著執行DJNZ R3,CIR2指令,R3減1后不為0則跳轉到CIR2標簽處,給R4賦值后

又一次開始200次的循環,循環總次數為20×200=4000次。使用兩重循環最長循環時長

可以達到255×255×2μs,約130ms。離500ms尚有差距,因此需再增加循環次數。

上面為三重循環的延時程序,其執行過程與兩重類似,三重的循環最長循環時長可以

達到2553×2μs,約33s。上面的程序延時為25×50×200×2μs,約0.5s。上面的幾個例

子中都是以12MHz的時鐘周期為前提條件的,不同的時鐘周期執行的時間有差異,頻率越高執行速度越快,時間越短。

延時在LED燈控制中的應用:

LED燈的閃爍就是一個通、斷電的重復過程,讓某一個引腳不斷地重復輸出高電平、延時、輸出低電平、延時即可。例如讓P1.0端口的燈閃爍,設計程序如下。

上面的程序即可實現P1.0端口的LED燈的閃爍,以12MHz晶振計算延時約25×50×200×2≈0.5s。程序中出現了兩個相同的延時程序段,顯得有點冗長多余,因此可以將它作為一個子程序段。

將延時程序編寫為一個子程序DELAY,然后在程序中通過LCALL調用,顯然上面的程序源碼更加簡潔明了,編譯后使用的程序存儲器空間更少。

在新建的“閃爍燈.ASM”文件中輸入上面的程序,如圖1-22所示。

編譯后下載到實驗板中,然后單片機復位開始運行,就可以看到P1.0的LED燈以約1s的頻率在閃爍。

能力檢測

(1)能夠獨立實現點亮實驗板上的每一個小燈,并且可以實現小燈的點亮、關閉以及閃爍。

(2)獨立完成流水燈右移操作以及流水燈先左移后右移等簡單的花樣操作。

圖1-22 在編輯欄輸入閃爍燈程序

主站蜘蛛池模板: 武强县| 安龙县| 重庆市| 临城县| 三门峡市| 南木林县| 武强县| 阜康市| 巴马| 华池县| 仲巴县| 绥阳县| 阜新市| 遂宁市| 内乡县| 凉山| 大埔区| 乐业县| 厦门市| 黄骅市| 鲁甸县| 远安县| 沈阳市| 兴山县| 当雄县| 新昌县| 嘉义县| 肃宁县| 东至县| 仲巴县| 和平区| 寿光市| 巴塘县| 武川县| 夏邑县| 自贡市| 嘉义市| 邯郸市| 长春市| 蕲春县| 新和县|