51微控制器的延時子程式
延時程式在微控制器程式設計中使用非常廣泛,但一些讀者在學習中不知道延時程式怎麼程式設計,不知道機器
週期和指令週期的區別,不知道延時程式指令的用法, ,本文就此問題從延時程式的基本概念、機器週期和指
令週期的區別和聯絡、相關指令的用法等用圖解法的形式詳盡的回答讀者
我們知道程式設計是微控制器開發最重要的工作,而程式在執行過程中常常需要完成延時的功能。例如
在交通燈的控制程式中,需要控制紅燈亮的時間持續30秒,就可以通過延時程式來完成。延時程式是如何
實現的呢?下面讓我們先來了解一些相關的概念。
一、機器週期和指令週期
1.機器週期是指微控制器完成一個基本操作所花費的時間,一般使用微秒來計量微控制器的執行速度,
51 微控制器的一個機器週期包括12 個時鐘振盪週期,也就是說如果51 微控制器採用12MHz 晶振,那麼執行
一個機器週期就只需要1μs;如果採用的是6MHz 的晶振,那麼執行一個機器週期就需要2 μs。
2 .指令週期是指微控制器執行一條指令所需要的時間,一般利用微控制器的機器週期來計量指令週期。
在51 微控制器裡有單週期指令(執行這條指令只需一個機器週期),雙週期指令(執行這條指令只需要兩個
機器週期),四周期指令(執行這條指令需要四個機器週期)。除了乘、除兩條指令是四周期指令,其餘均
為單週期或雙週期指令。也就是說,如果51 微控制器採用的是12MHz 晶振,那麼它執行一條指令一般只需
1~2 微秒的時間;如果採用的是6MH 晶振,執行一條指令一般就需2~4 微秒的時間。
現在的微控制器有很多種型號,但在每個型號的微控制器器件手冊中都會詳細說明執行各種指令所需的機
器週期,瞭解以上概念後,那麼可以依據微控制器器件手冊中的指令執行週期和微控制器所用晶振頻率來完成
需要精確延時時間的延時程式。
二、延時指令
在微控制器程式設計裡面並沒有真正的延時指令,從上面的概念中我們知道微控制器每執行一條指令都需要一
定的時間,所以要達到延時的效果,只須讓微控制器不斷地執行沒有具體實際意義的指令,從而達到了延時
的效果。
1.資料傳送指令 MOV
資料傳送指令功能是將資料從一個地方複製、拷貝到另一個地方。
如:MOV R7,#80H ;將資料80H 送到暫存器R7,這時暫存器R7 裡面存放著80H,就單這條
指令而言並沒有任何實際意義,而執行該指令則需要一個機器週期。
2.空操作指令 NOP
空操作指令功能只是讓微控制器執行沒有意義的操作,消耗一個機器週期。
3.迴圈轉移指令 DJNZ
迴圈轉移指令功能是將第一個數進行減1 並判斷是否為0,不為0 則轉移到指定地點;為0 則往下執行。
如:DJNZ R7,KK ;將暫存器R7 的內容減1 並判斷暫存器R7 裡的內容減完1 後是否為0,如果
不為0 則轉移到地址標號為KK 的地方;如果為0 則執行下一條指令。這條指令需要2 個機器週期。
利用以上三條指令的組合就可以比較精確地編寫出所需要的延時程式。
三、1 秒延時子程式、流程圖及時間計算 (以微控制器晶振為12MHz 為例,1 個機器週期需要1μs)
瞭解了以上的內容,現在讓我們來看看
程式總共所需時間:1+10+2560+330240+660480+5120+20+2=998433 μs≈1S
在這裡執行這段程式共需998433 μs,還差1567μs 才達到1S 的,所以想要達到完美的1S 延時,需
要在返回指令RET 前再新增一些指令讓它把1567μs 的延時完成。有興趣的讀者可以自己試著新增完成。
最後補充一點,編寫程式時一般將延時程式編寫成獨立的子程式,而所謂子程式也就是一個實現某個功能
的小模組。這樣在主程式中就可以方便地反覆呼叫編寫好的延時子程式。
小提示:迴圈轉移指令(DJNZ )除了可以給定地址標號讓其跳轉外,還可以將地址標號改成$,這樣
程式就跳回本指令執行。例如:
DJNZ R7,$ ;R7 內容減1 不為0,則再次執行本指令;為0 則往下執行,當R7 的值改為10
時,則執行完該條程式所需的時間為2*10=20 μs。
51微控制器彙編延時程式演算法詳解
將以12MHZ晶振為例,詳細講解MCS-51微控制器中彙編程式延時的精確演算法。
指令週期、機器週期與時鐘週期
指令週期:CPU執行一條指令所需要的時間稱為指令週期,它是以機器週期為單位的,指令不同,所需的機器週期也不同。
時鐘週期:也稱為振盪週期,一個時鐘週期 =晶振的倒數。
MCS-51微控制器的一個機器週期=6個狀態週期=12個時鐘週期。
MCS-51微控制器的指令有單位元組、雙位元組和三位元組的,它們的指令週期不盡相同,一個單週期指令包含一個機器週期,即12個時鐘週期,所以一條單週期指令被執行所佔時間為12*(1/12000000)=1μs。
程式分析
例1 50ms 延時子程式:
DEL:MOV R7,#200 ①
DEL1:MOV R6,#125 ②
DEL2:DJNZ R6,DEL2 ③
DJNZ R7,DEL1 ④
RET ⑤
精確延時時間為:1+(1*200)+(2*125*200)+(2*200)+2
=(2*125+3)*200+3 ⑥
=50603μs
≈50ms
由⑥整理出公式(只限上述寫法)延時時間=(2*內迴圈+3)*外迴圈+3 ⑦
詳解:DEL這個子程式共有五條指令,現在分別就 每一條指令 被執行的次數和所耗時間進行分析。
第一句:MOV R7,#200 在整個子程式中只被執行一次,且為單週期指令,所以耗時1μs
第二句:MOV R6,#125 從②看到④只要R7-1不為0,就會返回到這句,共執行了R7次,共耗時200μs
第三句:DJNZ R6,DEL2 只要R6-1不為0,就反覆執行此句(內迴圈R6次),又受外迴圈R7控制,所以共執行R6*R7次,因是雙週期指令,所以耗時2*R6*R7μs。
例2 1秒延時子程式:
DEL:MOV R7,#10 ①
DEL1:MOV R6,#200 ②
DEL2:MOV R5,#248 ③
DJNZ R5,$ ④
DJNZ R6,DEL2 ⑤
DJNZ R7,DEL1 ⑥
RET ⑦
對每條指令進行計算得出精確延時時間為:
1+(1*10)+(1*200*10)+(2*248*200*10)+(2*200*10)+(2*10)+2
=[(2*248+3)*200+3]*10+3 ⑧
=998033μs≈1s
由⑧整理得:延時時間=[(2*第一層迴圈+3)*第二層迴圈+3]*第三層迴圈+3 ⑨
此式適用三層迴圈以內的程式,也驗證了例1中式⑦(第三層迴圈相當於1)的成立。
注意,要實現較長時間的延時,一般採用多重迴圈,有時會在程式序里加入NOP指令,這時公式⑨不再適用,下面舉例分析。
例3仍以1秒延時為例
DEL:MOV R7,#10 1指令週期1
DEL1:MOV R6,#0FFH 1指令週期10
DEL2:MOV R5,#80H 1指令週期255*10=2550
KONG:NOP 1指令週期128*255*10=326400
DJNZ R5,$ 2指令週期2*128*255*10=652800
DJNZ R6,DEL2 2指令週期2*255*10=5110
DJNZ R7,DEL1 2指令週期2*10=20
RET 2
延時時間=1+10+2550+326400+652800+5110+20+2 =986893μs約為1s
整理得:延時時間=[(3*第一層迴圈+3)*第二層迴圈+3]*第三層迴圈+3 ⑩
結論:針對初學者的困惑,對彙編程式的延時演算法進行了分步講解,並就幾種不同寫法分別總結出相應的計算公式,只要仔細閱讀例1中的詳解,並用例2、例3來加深理解,一定會掌握各種型別程式的演算法並加以運用。
微控制器延時子程式
1)延時為:20ms 晶振12M
1+(1+2*248+2)*4+1+1+1=20000US=20MS
用匯編..優點就是精確...
缺點就是算有點複雜.
DELAY20MS:
MOV R7,#4
D1:
MOV R6,#248
DJNZ R6,$
DJNZ R7,D1
NOP
NOP
RET
2)一些通過計算51彙編指令得出的軟延時子程式
;*****************************************************************
;延時10uS
;*****************************************************************
time10us: mov r5,#05h ;11us
djnz r5,$
ret
;*****************************************************************
;延時50uS
;*****************************************************************
time50us: mov r5,#19h ;51us
djnz r5,$
ret
;*****************************************************************
;延時100uS
;*****************************************************************
time100us: mov r5,#31h ;99.6us
djnz r5,$
ret
;*****************************************************************
;延時200uS
;*****************************************************************
time200us: mov r5,#64h ;201us
djnz r5,$
ret
;*****************************************************************
;延時250uS
;*****************************************************************
time250us: mov r5,#7ch ;249.6us
djnz r5,$
ret
;*****************************************************************
;延時350uS
;*****************************************************************
time350us: mov r5,#0afh ;351us
time350us_1: djnz r5,time350us_1
ret
;*****************************************************************
;延時500uS
;*****************************************************************
time500us: mov r5,#0fah ;501us
time500us_1: djnz r5,time500us_1
ret
;*****************************************************************
;延時1mS
;*****************************************************************
time1ms: mov r5,#0fah ;1001us
time1ms_1: nop
nop
djnz r5,time1ms_1
ret
;*****************************************************************
;延時2.5mS
;*****************************************************************
time2_5ms: mov r5,#05h ;2.496ms
time2_5ms_1: mov r6,#0f8h ;497us
djnz r6,$
djnz r5,time2_5ms_1
ret
;*****************************************************************
;延時10mS
;*****************************************************************
time10ms: mov r5,#14h ;10.262ms
time10ms_1: mov r6,#0ffh ;511us
djnz r6,$
djnz r5,time10ms_1
ret
;*****************************************************************
;延時50mS
;*****************************************************************
time50ms: mov r5,#63h ;49.996ms
time50ms_1: mov r6,#0fbh ;503us
djnz r6,$
djnz r5,time50ms_1
ret
;*****************************************************************
;延時100mS
;*****************************************************************
time100ms: mov r5,#0c3h ;100.036ms
time100ms_1: mov r6,#0ffh ;511us
djnz r6,$
djnz r5,time100ms_1
ret
;*****************************************************************
;延時200mS
;*****************************************************************
time200ms: mov r5,#02h ;250.351ms
time200ms_1: mov r6,#0f4h ;125.173ms
time200ms_2: mov r7,#0ffh ;511us
djnz r7,$
djnz r6,time200ms_2
djnz r5,time200ms_1
ret
;*****************************************************************
;延時500mS
;*****************************************************************
time500ms: mov r5,#04h ;500.701ms
time500ms_1: mov r6,#0f4h ;125.173ms
time500ms_2: mov r7,#0ffh ;511us
djnz r7,$
djnz r6,time500ms_2
djnz r5,time500ms_1
ret
;*****************************************************************
;延時1S
;*****************************************************************
time1s: mov r5,#08h ;1001.401ms
time1s_1: mov r6,#0f4h ;125.173ms
time1s_2: mov r7,#0ffh ;511us
djnz r7,$
djnz r6,time1s_2
djnz r5,time1s_1
ret
12M晶振 機器週期為1US NOP為單週期指令 DJNZ為雙週期指令.
3)
;;晶振12MHZ,延時1秒
DELAY:MOV 72H,#100
LOOP3:MOV 71H,#100
LOOP1:MOV 70H,#47
LOOP0:DJNZ 70H,LOOP0
NOP
DJNZ 71H,LOOP1
MOV 70H,#46
LOOP2:DJNZ 70H,LOOP2
NOP
DJNZ 72H,LOOP3
MOV 70H,#48
LOOP4:DJNZ 70H,LOOP4
4);延時1分鐘子程式,F=6MHz
;程式已測過,延時時間60,000,000.0uS
delay60s:mov r3,#228
mov r2,#253
mov r1,#219
loop1: djnz r1,$
djnz r2,loop1
djnz r3,loop1
nop
ret
5)計算機反覆執行一段程式以達到延時的目的稱為軟體延時,微控制器程式中經常需要短時間的延時,但是相當一部分人對延時程式很模糊,對延時程式的演算法不夠了解,在這裡我以12MHz晶振和兩個經典延時子程式為例,詳細分析微控制器彙編延時程式。
何為時鐘週期、機器週期、和指令週期?
時鐘週期:也就是振盪週期,以12MHz的時鐘脈衝為例,那時鐘週期就為(1/12000000)s=(1/12)us;
機器週期:1個機器週期=6個狀態週期=12個時鐘週期=1us;
指令週期:CPU執行一條指令所需要的時間稱為指令週期,指令週期是以機器週期為單位的,不同的指令所需的機器週期不一定相同,可參考51微控制器指令速查表。
由上可得:CPU執行一條單週期指令,需要1us;執行一條雙週期指令需要2us。
下面是具體的延時子程式分析:
0.1s延時子程式(12MHz晶振):
MOV R7,#200 ;單週期指令(1us)
D1: MOV R6,#250 ;單週期指令(1us)
DJNZ R6,$ ;雙週期指令(2us)//該指令自身執行R6次
DJNZ R7,D1 ;雙週期指令(2us)//D1執行R7次
RET ;雙週期指令(2us)
T=1+(1+2*R6+2)*R7+2
=100603us
≈0.1s
0.5s延時子程式(12MHz晶振):
MOV R7,#5 ;單週期指令(1us)
D1: MOV R6,#200 ;單週期指令(1us)
D2: MOV R5,#250 ;單週期指令(1us
DJNZ R5,$ ;雙週期指令(2us)//該指令自身執行R5次
DJNZ R6,D2 ;雙週期指令(2us)//D2執行R6次
DJNZ R7,D1 ;雙週期指令(2us)//D1執行R7次
RET ;雙週期指令(2us)
T=1+[1+(1+2*R5+2)*R6+2]*R7+2
=503018us
≈0.5s
6) 51微控制器經典流水燈程式,在51微控制器的P2口接上8個發光二極體,產生流水燈的移動效果。
ORG 0 ;程式從0地址開始
START: MOV A,#0FEH ;讓ACC的內容為11111110
LOOP: MOV P2,A ;讓P2口輸出ACC的內容
RR A ;讓ACC的內容左移
CALL DELAY ;呼叫延時子程式
LJMP LOOP ;跳到LOOP處執行
;0.1秒延時子程式(12MHz晶振)===================
DELAY: MOV R7,#200 ;R7暫存器載入200次數
D1: MOV R6,#250 ;R6暫存器載入250次數
DJNZ R6,$ ;本行執行R6次
DJNZ R7,D1 ;D1迴圈執行R7次
RET ;返回主程式
END ;結束程式