51單片機(jī)的延時(shí)子程序
延時(shí)程序在單片機(jī)編程中使用非常廣泛,但一些讀者在學(xué)習(xí)中不知道延時(shí)程序怎么編程,不知道機(jī)器周期和指令周期的區(qū)別,不知道延時(shí)程序指令的用法, ,本文就此問題從延時(shí)程序的基本概念、機(jī)器周期和指令周期的區(qū)別和聯(lián)系、相關(guān)指令的用法等用圖解法的形式詳盡的回答讀者
我們知道程序設(shè)計(jì)是單片機(jī)開發(fā)最重要的工作,而程序在執(zhí)行過程中常常需要完成延時(shí)的功能。例如
在交通燈的控制程序中,需要控制紅燈亮的時(shí)間持續(xù)30秒,就可以通過延時(shí)程序來完成。延時(shí)程序是如何實(shí)現(xiàn)的呢?下面讓我們先來了解一些相關(guān)的概念。
一、機(jī)器周期和指令周期
1.機(jī)器周期是指單片機(jī)完成一個(gè)基本操作所花費(fèi)的時(shí)間,一般使用微秒來計(jì)量單片機(jī)的運(yùn)行速度,51 單片機(jī)的一個(gè)機(jī)器周期包括12 個(gè)時(shí)鐘振蕩周期,也就是說如果51 單片機(jī)采用12MHz 晶振,那么執(zhí)行一個(gè)機(jī)器周期就只需要1μs;如果采用的是6MHz 的晶振,那么執(zhí)行一個(gè)機(jī)器周期就需要2 μs。
2 .指令周期是指單片機(jī)執(zhí)行一條指令所需要的時(shí)間,一般利用單片機(jī)的機(jī)器周期來計(jì)量指令周期。在51 單片機(jī)里有單周期指令(執(zhí)行這條指令只需一個(gè)機(jī)器周期),雙周期指令(執(zhí)行這條指令只需要兩個(gè)機(jī)器周期),四周期指令(執(zhí)行這條指令需要四個(gè)機(jī)器周期)。除了乘、除兩條指令是四周期指令,其余均為單周期或雙周期指令。也就是說,如果51 單片機(jī)采用的是12MHz 晶振,那么它執(zhí)行一條指令一般只需1~2 微秒的時(shí)間;如果采用的是6MH 晶振,執(zhí)行一條指令一般就需2~4 微秒的時(shí)間。
現(xiàn)在的單片機(jī)有很多種型號(hào),但在每個(gè)型號(hào)的單片機(jī)器件手冊(cè)中都會(huì)詳細(xì)說明執(zhí)行各種指令所需的機(jī)器周期,了解以上概念后,那么可以依據(jù)單片機(jī)器件手冊(cè)中的指令執(zhí)行周期和單片機(jī)所用晶振頻率來完成需要精確延時(shí)時(shí)間的延時(shí)程序。
二、延時(shí)指令
在單片機(jī)編程里面并沒有真正的延時(shí)指令,從上面的概念中我們知道單片機(jī)每執(zhí)行一條指令都需要一定的時(shí)間,所以要達(dá)到延時(shí)的效果,只須讓單片機(jī)不斷地執(zhí)行沒有具體實(shí)際意義的指令,從而達(dá)到了延時(shí)的效果。
1.數(shù)據(jù)傳送指令 MOV
數(shù)據(jù)傳送指令功能是將數(shù)據(jù)從一個(gè)地方復(fù)制、拷貝到另一個(gè)地方。
如:MOV R7,#80H ;將數(shù)據(jù)80H 送到寄存器R7,這時(shí)寄存器R7 里面存放著80H,就單這條
指令而言并沒有任何實(shí)際意義,而執(zhí)行該指令則需要一個(gè)機(jī)器周期。
2.空操作指令 NOP
空操作指令功能只是讓單片機(jī)執(zhí)行沒有意義的操作,消耗一個(gè)機(jī)器周期。
3.循環(huán)轉(zhuǎn)移指令 DJNZ
循環(huán)轉(zhuǎn)移指令功能是將第一個(gè)數(shù)進(jìn)行減1 并判斷是否為0,不為0 則轉(zhuǎn)移到指定地點(diǎn);為0 則往下執(zhí)行。
如:DJNZ R7,KK ;將寄存器R7 的內(nèi)容減1 并判斷寄存器R7 里的內(nèi)容減完1 后是否為0,如果
不為0 則轉(zhuǎn)移到地址標(biāo)號(hào)為KK 的地方;如果為0 則執(zhí)行下一條指令。這條指令需要2 個(gè)機(jī)器周期。
利用以上三條指令的組合就可以比較精確地編寫出所需要的延時(shí)程序。
三、1 秒延時(shí)子程序、流程圖及時(shí)間計(jì)算 (以單片機(jī)晶振為12MHz 為例,1 個(gè)機(jī)器周期需要1μs)
了解了以上的內(nèi)容,現(xiàn)在讓我們來看看
程序總共所需時(shí)間:1+10+2560+330240+660480+5120+20+2=998433 μs≈1S
在這里運(yùn)行這段程序共需998433 μs,還差1567μs 才達(dá)到1S 的,所以想要達(dá)到完美的1S 延時(shí),需要在返回指令RET 前再添加一些指令讓它把1567μs 的延時(shí)完成。有興趣的讀者可以自己試著添加完成。
最后補(bǔ)充一點(diǎn),編寫程序時(shí)一般將延時(shí)程序編寫成獨(dú)立的子程序,而所謂子程序也就是一個(gè)實(shí)現(xiàn)某個(gè)功能的小模塊。這樣在主程序中就可以方便地反復(fù)調(diào)用編寫好的延時(shí)子程序。
小提示:循環(huán)轉(zhuǎn)移指令(DJNZ )除了可以給定地址標(biāo)號(hào)讓其跳轉(zhuǎn)外,還可以將地址標(biāo)號(hào)改成$,這樣程序就跳回本指令執(zhí)行。例如:
DJNZ R7,$ ;R7 內(nèi)容減1 不為0,則再次執(zhí)行本指令;為0 則往下執(zhí)行,當(dāng)R7 的值改為10時(shí),則執(zhí)行完該條程序所需的時(shí)間為2*10=20 μs。
51單片機(jī)匯編延時(shí)程序算法詳解
將以12MHZ晶振為例,詳細(xì)講解MCS-51單片機(jī)中匯編程序延時(shí)的精確算法。
指令周期、機(jī)器周期與時(shí)鐘周期
指令周期:CPU執(zhí)行一條指令所需要的時(shí)間稱為指令周期,它是以機(jī)器周期為單位的,指令不同,所需的機(jī)器周期也不同。
時(shí)鐘周期:也稱為振蕩周期,一個(gè)時(shí)鐘周期 =晶振的倒數(shù)。
MCS-51單片機(jī)的一個(gè)機(jī)器周期=6個(gè)狀態(tài)周期=12個(gè)時(shí)鐘周期。
MCS-51單片機(jī)的指令有單字節(jié)、雙字節(jié)和三字節(jié)的,它們的指令周期不盡相同,一個(gè)單周期指令包含一個(gè)機(jī)器周期,即12個(gè)時(shí)鐘周期,所以一條單周期指令被執(zhí)行所占時(shí)間為12*(1/12000000)=1μs。
程序分析
例1 50ms 延時(shí)子程序:
DEL:MOV R7,#200 ①
DEL1:MOV R6,#125 ②
DEL2:DJNZ R6,DEL2 ③
DJNZ R7,DEL1 ④
RET ⑤
精確延時(shí)時(shí)間為:1+(1*200)+(2*125*200)+(2*200)+2
=(2*125+3)*200+3 ⑥
=50603μs
≈50ms
由⑥整理出公式(只限上述寫法)延時(shí)時(shí)間=(2*內(nèi)循環(huán)+3)*外循環(huán)+3 ⑦
詳解:DEL這個(gè)子程序共有五條指令,現(xiàn)在分別就 每一條指令 被執(zhí)行的次數(shù)和所耗時(shí)間進(jìn)行分析。
第一句:MOV R7,#200 在整個(gè)子程序中只被執(zhí)行一次,且為單周期指令,所以耗時(shí)1μs
第二句:MOV R6,#125 從②看到④只要R7-1不為0,就會(huì)返回到這句,共執(zhí)行了R7次,共耗時(shí)200μs
第三句:DJNZ R6,DEL2 只要R6-1不為0,就反復(fù)執(zhí)行此句(內(nèi)循環(huán)R6次),又受外循環(huán)R7控制,所以共執(zhí)行R6*R7次,因是雙周期指令,所以耗時(shí)2*R6*R7μs。
例2 1秒延時(shí)子程序:
DEL:MOV R7,#10 ①
DEL1:MOV R6,#200 ②
DEL2:MOV R5,#248 ③
DJNZ R5,$ ④
DJNZ R6,DEL2 ⑤
DJNZ R7,DEL1 ⑥
RET ⑦
對(duì)每條指令進(jìn)行計(jì)算得出精確延時(shí)時(shí)間為:
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
由⑧整理得:延時(shí)時(shí)間=[(2*第一層循環(huán)+3)*第二層循環(huán)+3]*第三層循環(huán)+3 ⑨
此式適用三層循環(huán)以內(nèi)的程序,也驗(yàn)證了例1中式⑦(第三層循環(huán)相當(dāng)于1)的成立。
注意,要實(shí)現(xiàn)較長時(shí)間的延時(shí),一般采用多重循環(huán),有時(shí)會(huì)在程式序里加入NOP指令,這時(shí)公式⑨不再適用,下面舉例分析。
例3仍以1秒延時(shí)為例
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
延時(shí)時(shí)間=1+10+2550+326400+652800+5110+20+2 =986893μs約為1s
整理得:延時(shí)時(shí)間=[(3*第一層循環(huán)+3)*第二層循環(huán)+3]*第三層循環(huán)+3 ⑩
結(jié)論:針對(duì)初學(xué)者的困惑,對(duì)匯編程序的延時(shí)算法進(jìn)行了分步講解,并就幾種不同寫法分別總結(jié)出相應(yīng)的計(jì)算公式,只要仔細(xì)閱讀例1中的詳解,并用例2、例3來加深理解,一定會(huì)掌握各種類型程序的算法并加以運(yùn)用。
單片機(jī)延時(shí)子程序
1)延時(shí)為:20ms 晶振12M
1+(1+2*248+2)*4+1+1+1=20000US=20MS
用匯編..優(yōu)點(diǎn)就是精確...
缺點(diǎn)就是算有點(diǎn)復(fù)雜.
DELAY20MS:
MOV R7,#4
D1:
MOV R6,#248
DJNZ R6,$
DJNZ R7,D1
NOP
NOP
RET
2)一些通過計(jì)算51匯編指令得出的軟延時(shí)子程序
;*****************************************************************
;延時(shí)10uS
;*****************************************************************
time10us: mov r5,#05h ;11us
djnz r5,$
ret
;*****************************************************************
;延時(shí)50uS
;*****************************************************************
time50us: mov r5,#19h ;51us
djnz r5,$
ret
;*****************************************************************
;延時(shí)100uS
;*****************************************************************
time100us: mov r5,#31h ;99.6us
djnz r5,$
ret
;*****************************************************************
;延時(shí)200uS
;*****************************************************************
time200us: mov r5,#64h ;201us
djnz r5,$
ret
;*****************************************************************
;延時(shí)250uS
;*****************************************************************
time250us: mov r5,#7ch ;249.6us
djnz r5,$
ret
;*****************************************************************
;延時(shí)350uS
;*****************************************************************
time350us: mov r5,#0afh ;351us
time350us_1: djnz r5,time350us_1
ret
;*****************************************************************
;延時(shí)500uS
;*****************************************************************
time500us: mov r5,#0fah ;501us
time500us_1: djnz r5,time500us_1
ret
;*****************************************************************
;延時(shí)1mS
;*****************************************************************
time1ms: mov r5,#0fah ;1001us
time1ms_1: nop
nop
djnz r5,time1ms_1
ret
;*****************************************************************
;延時(shí)2.5mS
;*****************************************************************
time2_5ms: mov r5,#05h ;2.496ms
time2_5ms_1: mov r6,#0f8h ;497us
djnz r6,$
djnz r5,time2_5ms_1
ret
;*****************************************************************
;延時(shí)10mS
;*****************************************************************
time10ms: mov r5,#14h ;10.262ms
time10ms_1: mov r6,#0ffh ;511us
djnz r6,$
djnz r5,time10ms_1
ret
;*****************************************************************
;延時(shí)50mS
;*****************************************************************
time50ms: mov r5,#63h ;49.996ms
time50ms_1: mov r6,#0fbh ;503us
djnz r6,$
djnz r5,time50ms_1
ret
;*****************************************************************
;延時(shí)100mS
;*****************************************************************
time100ms: mov r5,#0c3h ;100.036ms
time100ms_1: mov r6,#0ffh ;511us
djnz r6,$
djnz r5,time100ms_1
ret
;*****************************************************************
;延時(shí)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
;*****************************************************************
;延時(shí)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
;*****************************************************************
;延時(shí)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晶振 機(jī)器周期為1US NOP為單周期指令 DJNZ為雙周期指令.
3)
;;晶振12MHZ,延時(shí)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);延時(shí)1分鐘子程序,F(xiàn)=6MHz
;程序已測過,延時(shí)時(shí)間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)計(jì)算機(jī)反復(fù)執(zhí)行一段程序以達(dá)到延時(shí)的目的稱為軟件延時(shí),單片機(jī)程序中經(jīng)常需要短時(shí)間的延時(shí),但是相當(dāng)一部分人對(duì)延時(shí)程序很模糊,對(duì)延時(shí)程序的算法不夠了解,在這里我以12MHz晶振和兩個(gè)經(jīng)典延時(shí)子程序?yàn)槔,詳?xì)分析單片機(jī)匯編延時(shí)程序。
何為時(shí)鐘周期、機(jī)器周期、和指令周期?
時(shí)鐘周期:也就是振蕩周期,以12MHz的時(shí)鐘脈沖為例,那時(shí)鐘周期就為(1/12000000)s=(1/12)us;
機(jī)器周期:1個(gè)機(jī)器周期=6個(gè)狀態(tài)周期=12個(gè)時(shí)鐘周期=1us;
指令周期:CPU執(zhí)行一條指令所需要的時(shí)間稱為指令周期,指令周期是以機(jī)器周期為單位的,不同的指令所需的機(jī)器周期不一定相同,可參考51單片機(jī)指令速查表。
由上可得:CPU執(zhí)行一條單周期指令,需要1us;執(zhí)行一條雙周期指令需要2us。
下面是具體的延時(shí)子程序分析:
0.1s延時(shí)子程序(12MHz晶振):
MOV R7,#200 ;單周期指令(1us)
D1: MOV R6,#250 ;單周期指令(1us)
DJNZ R6,$ ;雙周期指令(2us)//該指令自身執(zhí)行R6次
DJNZ R7,D1 ;雙周期指令(2us)//D1執(zhí)行R7次
RET ;雙周期指令(2us)
T=1+(1+2*R6+2)*R7+2
=100603us
≈0.1s
0.5s延時(shí)子程序(12MHz晶振):
MOV R7,#5 ;單周期指令(1us)
D1: MOV R6,#200 ;單周期指令(1us)
D2: MOV R5,#250 ;單周期指令(1us
DJNZ R5,$ ;雙周期指令(2us)//該指令自身執(zhí)行R5次
DJNZ R6,D2 ;雙周期指令(2us)//D2執(zhí)行R6次
DJNZ R7,D1 ;雙周期指令(2us)//D1執(zhí)行R7次
RET ;雙周期指令(2us)
T=1+[1+(1+2*R5+2)*R6+2]*R7+2
=503018us
≈0.5s
6) 51單片機(jī)經(jīng)典流水燈程序,在51單片機(jī)的P2口接上8個(gè)發(fā)光二極管,產(chǎn)生流水燈的移動(dòng)效果。
ORG 0 ;程序從0地址開始
START: MOV A,#0FEH ;讓ACC的內(nèi)容為11111110
LOOP: MOV P2,A ;讓P2口輸出ACC的內(nèi)容
RR A ;讓ACC的內(nèi)容左移
CALL DELAY ;調(diào)用延時(shí)子程序
LJMP LOOP ;跳到LOOP處執(zhí)行
;0.1秒延時(shí)子程序(12MHz晶振)===================
DELAY: MOV R7,#200 ;R7寄存器加載200次數(shù)
D1: MOV R6,#250 ;R6寄存器加載250次數(shù)
DJNZ R6,$ ;本行執(zhí)行R6次
DJNZ R7,D1 ;D1循環(huán)執(zhí)行R7次
RET ;返回主程序
END ;結(jié)束程序
編輯:admin 最后修改時(shí)間:2018-05-18