C及匯編延時(shí)程序_第1頁(yè)
C及匯編延時(shí)程序_第2頁(yè)
C及匯編延時(shí)程序_第3頁(yè)
C及匯編延時(shí)程序_第4頁(yè)
C及匯編延時(shí)程序_第5頁(yè)
已閱讀5頁(yè),還剩11頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

有個(gè)好帖,從精度考慮,它得研究結(jié)果是:

void

delay2(unsigned

char

i)

{

while(--i);

}

為最佳方法。

分析:假設(shè)外掛12M(之后都是在這基礎(chǔ)上討論)

我編譯了下,傳了些參數(shù),并看了匯編代碼,觀察記錄了下面的數(shù)據(jù):

delay2(0):延時(shí)518us

518-2*256=6

delay2(1):延時(shí)7us(原帖寫“5us”是錯(cuò)的,^_^)

delay2(10):延時(shí)25us

25-20=5

delay2(20):延時(shí)45us

45-40=5

delay2(100):延時(shí)205us

205-200=5

delay2(200):延時(shí)405us

405-400=5

見(jiàn)上可得可調(diào)度為2us,而最大誤差為6us。

精度是很高了!

但這個(gè)程序的最大延時(shí)是為518us

顯然不

能滿足實(shí)際需要,因?yàn)楹芏鄷r(shí)候需要延遲比較長(zhǎng)的時(shí)間。

那么,接下來(lái)討論將t分配為兩個(gè)字節(jié),即uint型的時(shí)候,會(huì)出現(xiàn)什么情況。

void

delay8(uint

t)

{

while(--t);

}

我編譯了下,傳了些參數(shù),并看了匯編代碼,觀察記錄了下面的數(shù)據(jù):

delay8(0):延時(shí)524551us

524551-8*65536=263

delay8(1):延時(shí)15us

delay8(10):延時(shí)85us

85-80=5

delay8(100):延時(shí)806us

806-800=6

delay8(1000):延時(shí)8009us

8009-8000=9

delay8(10000):延時(shí)80045us

80045-8000=45

delay8(65535):延時(shí)524542us

524542-524280=262

如果把這個(gè)程序的可調(diào)度看為8us,那么最大誤差為263us,但這個(gè)延時(shí)程序還是不能滿足要求的,因?yàn)檠訒r(shí)最大為524.551ms。

那么用ulong

t呢?

一定很恐怖,不用看編譯后的匯編代碼了。。。

那么如何得到比較小的可調(diào)度,可調(diào)范圍大,并占用比較少得RAM呢?請(qǐng)看下面的程序:

/*--------------------------------------------------------------------

程序名稱:50us

延時(shí)

注意事項(xiàng):基于1MIPS,AT89系列對(duì)應(yīng)12M晶振,W77、W78系列對(duì)應(yīng)3M晶振

例子提示:調(diào)用delay_50us(20),得到1ms延時(shí)

全局變量:無(wú)

返回:

無(wú)

--------------------------------------------------------------------*/

void

delay_50us(uint

t)

{

uchar

j;

for(;t>0;t--)

for(j=19;j>0;j--)

;

}

我編譯了下,傳了些參數(shù),并看了匯編代碼,觀察記錄了下面的數(shù)據(jù):

delay_50us(1):延時(shí)63us

63-50=13

delay_50us(10):延時(shí)513us

503-500=13

delay_50us(100):延時(shí)5013us

5013-5000=13

delay_50us(1000):延時(shí)50022us

50022-50000=22

赫赫,延時(shí)50ms,誤差僅僅22us,作為C語(yǔ)言已經(jīng)是可以接受了。再說(shuō)要求再精確的話,就算是用匯編也得改用定時(shí)器了。

/*--------------------------------------------------------------------

程序名稱:50ms

延時(shí)

注意事項(xiàng):基于1MIPS,AT89系列對(duì)應(yīng)12M晶振,W77、W78系列對(duì)應(yīng)3M晶振

例子提示:調(diào)用delay_50ms(20),得到1s延時(shí)

全局變量:無(wú)

返回:

無(wú)

--------------------------------------------------------------------*/

void

delay_50ms(uint

t)

{

uint

j;

/****

可以在此加少許延時(shí)補(bǔ)償,以禰補(bǔ)大數(shù)值傳遞時(shí)(如delay_50ms(1000))造成的誤差,

但付出的代價(jià)是造成傳遞小數(shù)值(delay_50ms(1))造成更大的誤差。

因?yàn)閷?shí)際應(yīng)用更多時(shí)候是傳遞小數(shù)值,所以補(bǔ)建議加補(bǔ)償!

****/

for(;t>0;t--)

for(j=6245;j>0;j--)

;

}

我編譯了下,傳了些參數(shù),并看了匯編代碼,觀察記錄了下面的數(shù)據(jù):

delay_50ms(1):延時(shí)50

010

10us

delay_50ms(10):延時(shí)499

983

17us

delay_50ms(100):延時(shí)4

999

713

287us

delay_50ms(1000):延時(shí)4

997

022

2.978ms

赫赫,延時(shí)50s,誤差僅僅2.978ms,可以接受!

上面程序沒(méi)有才用long,也沒(méi)采用3層以上的循環(huán),而是將延時(shí)分拆為兩個(gè)程序以提高精度。應(yīng)該是比較好的做法了問(wèn)題內(nèi)容:怎樣用c語(yǔ)言寫延時(shí)程序原討論鏈接:/expert/topicview1.asp?id=4760346所屬論壇:?jiǎn)纹瑱C(jī)/工控

審核組:硬件/嵌入開發(fā)提問(wèn)者:\o"zharrisl個(gè)人空間"zharrisl

解決者:\o"hiflower個(gè)人空間"hiflower感謝:\o"icesnows個(gè)人空間"icesnows\o"shimd0604個(gè)人空間"shimd0604\o"sclarkca810619個(gè)人空間"sclarkca810619\o"flowercity個(gè)人空間"flowercity\o"icesnows個(gè)人空間"icesnows\o"tony1976個(gè)人空間"tony1976\o"tony1976個(gè)人空間"tony1976\o"eastred個(gè)人空間"eastred\o"winp2003個(gè)人空間"winp2003\o"hu_an_xiong個(gè)人空間"hu_an_xiong\o"517517個(gè)人空間"517517\o"hiflower個(gè)人空間"hiflower\o"tyj_3個(gè)人空間"tyj_3關(guān)鍵字:函數(shù)語(yǔ)句硬件/嵌入開發(fā)單片機(jī)指令匯編void循環(huán)定時(shí)周期單片機(jī)/工控答案:要求是秒級(jí)的,同時(shí)說(shuō)明下原理

---------------------------------------------------------------

空循環(huán)就行了

如while(i--);根據(jù)i的不同決定了延時(shí)長(zhǎng)短

不過(guò)C的延時(shí)不是非常準(zhǔn)確,你得根據(jù)反匯編,看匯編語(yǔ)句的數(shù)量和指令周期來(lái)計(jì)算時(shí)間

---------------------------------------------------------------

樓上的說(shuō)得很對(duì),用C語(yǔ)言編寫單片機(jī)程序時(shí),一般開發(fā)界面(如科爾KEILE)都提供了C

-

匯編的代碼轉(zhuǎn)換,參照轉(zhuǎn)換后的匯編語(yǔ)言就可以精確延時(shí)了

---------------------------------------------------------------

你可以數(shù)指令,然后按著MCU的MIPS算時(shí)間,結(jié)果應(yīng)該比較精確:)

---------------------------------------------------------------

void

mDelay(unsigned

int

Delay)

//Delay

=

1000

時(shí)間為1S

{

unsigned

int

i;

for(;Delay>0;Delay--)

{

for(i=0;i<124;i++)

{;}

}

}

---------------------------------------------------------------

數(shù)

一次循環(huán)的匯編指令,再乘以指令周期就知道一次循環(huán)的時(shí)間了啊,然后用1秒一除,不就知道循環(huán)次數(shù)了么

---------------------------------------------------------------

秒級(jí)的本身精度要求就不高嘛

很容易控制啊

多套用幾個(gè)for語(yǔ)句

或者在for語(yǔ)句里引用n個(gè)更低量級(jí)的(如100ms級(jí))的延時(shí)函數(shù)即可

要精確就計(jì)算匯編代碼執(zhí)行長(zhǎng)度

---------------------------------------------------------------

to

flowercity(Love

Program,Love

Living):

你的函數(shù)沒(méi)有什么參考價(jià)值

延時(shí)時(shí)間和指令周期以及編譯出來(lái)的代碼類型有關(guān)系的

不是所謂

//Delay

=

1000

時(shí)間為1S

就是一定的.

那只是針對(duì)你現(xiàn)在的系統(tǒng).

用的晶振不同,執(zhí)行CPU指令周期和時(shí)鐘周期比率不同

結(jié)果都不同

---------------------------------------------------------------

秒級(jí)的,用定時(shí)器比較好吧。

---------------------------------------------------------------

void

waitms(int

i)

{

char

m;

for(

;

i

;i--)

{

for(m

=

203;

m

;

m--)

{

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

}

}

}

延時(shí)1ms的函數(shù)

時(shí)鐘頻率12MHz

---------------------------------------------------------------

空操作,不過(guò)不好做到很準(zhǔn)確

---------------------------------------------------------------

秒級(jí)延時(shí),用指令的話,你要求延時(shí)的精確度是多少,高的話最好用定時(shí)器,而且你延時(shí)這么長(zhǎng),你的CPU不是就一直占用了,浪費(fèi)呀。。。

---------------------------------------------------------------

與定時(shí)器中斷服務(wù)程序配合實(shí)現(xiàn)延時(shí)。

unsigned

int

sleepTime;

unsinged

char

inSleep

=

0;

void

sleepService(void)

{

if

(inSleep)

sleepTime--;

if

(sleepTime

==

0)

inSleep

=

0;

}

void

isr_timer(void)

//假定定時(shí)器中斷1ms

中斷一次。

{

...

sleepService();

...

}

void

sleep(unsigned

int

ms)

//延時(shí)子程序

{

sleepTime

=

ms;

inSleep

=

1;

while(inSleep);

}

void

main(void)

{

....

sleep(1000);

//延時(shí)

1秒

...

}

---------------------------------------------------------------

>>要求是秒級(jí)的

這么長(zhǎng)的延時(shí),單片機(jī)中一般采取不占CPU時(shí)間的延時(shí),利用定時(shí)器來(lái)實(shí)現(xiàn)延時(shí),

如果非得用循環(huán)延時(shí),在C中也通常嵌入?yún)R編實(shí)現(xiàn),這樣誤差比較小在論壇上看到不少不錯(cuò)的延時(shí)程序,整理如下共同分享:精確延時(shí)計(jì)算公式:延時(shí)時(shí)間=[(2*第一層循環(huán)+3)*第二層循環(huán)+3]*第三層循環(huán)+5;延時(shí)5秒左右

DELAY5S:PUSH

04H

PUSH

05H

PUSH

06H

MOV

R4,#50

DELAY5S_0:MOV

R5,#200

DELAY5S_1:MOV

R6,#245

DJNZ

R6,$

DJNZ

R5,DELAY5S_1

DJNZ

R4,DELAY5S_0

POP

06H

POP

05H

POP

04H

RET

;513微秒延時(shí)程序

DELAY:

MOV

R2,#0FEH

DELAY1:DJNZ

R2,DELAY1

RET;10毫秒延時(shí)程序

DL10MS:MOV

R3,#14H

DL10MS1:LCALL

DELAY

DJNZ

R3,DL10MS1

RET;0.1s延時(shí)程序12mhz

DELAY:MOVR6,#250

DL1:MOVR7,#200

DL2:DJNZR6,DL2

DJNZR7,DL1

RET;延時(shí)1046549微秒(12mhz)

;具體的計(jì)算公式是:

;((((r7*2+1)+2)*r6+1)+2)*r5+1+4=((r7*2+3)*r6+3)*r5+5

DEL:MOV

R5,#08H

DEL1:MOV

R6,#0FFH

DEL2:MOV

R7,#0FFH

DJNZ

R7,$

DJNZ

R6,DEL2

DJNZ

R5,DEL1

RET;1秒延時(shí)子程序是以12MHz晶振

Delay1S:mov

r1,#50

del0:

movr2,#91

del1:

movr3,#100

djnzr3,$

djnzr2,del1

djnzr1,del0

Ret;1秒延時(shí)子程序是以12MHz晶振為例算指令周期耗時(shí)

KK:MOV

R5,#10

;1指令周期1

K1:MOV

R6,#0FFH

;1指令周期10

K2:MOV

R7,#80H

;1指令周期256*10=2560

K3:NOP

;1指令周期128*256*10=327680

DJNZ

R7,K3

;2指令周期2*128*256*10=655360

DJNZ

R6,K2

;2指令周期2*256*10=5120

DJNZ

R5,K1

;2指令周期2*10=20

RET

;2指令周期21+10+2560+327680+655360+5120+20+2=990753

;約等于1秒1秒=1000000微秒

;這個(gè)算下來(lái)也只有0.998抄

T_0:

MOV

R7,#10;

D1:

MOV

R6,#200;

D2:

MOV

R5,#248;

DJNZ

R5,$

DJNZ

R6,D2;

DJNZ

R7,D1;

RET;這樣算下來(lái)應(yīng)該是1.000011秒

T_0:

MOV

R7,#10;

D1:

MOV

R6,#200;

D2:

NOP

MOV

R5,#248;

DJNZ

R5,$

DJNZ

R6,D2;

DJNZ

R7,D1;

RETDELAY_2S:

;10MS(11.0592mhz)

MOVR3,#200

JMPDELAY10MS

DELAY_100MS:

;100MS(11.0592mhz)

MOVR3,#10

JMPDELAY10MS

DELAY_10MS:

MOVR3,#1

DELAY10MS:

;去抖動(dòng)10MS(11.0592mhz)

MOVR4,#20

DELAY10MSA:

MOVR5,#247

DJNZR5,$

DJNZR4,DELAY10MSA

DJNZR3,DELAY10MS

RET

DELAY_500MS:

;500500MS

MOVR2,#208

JMPDELAY_MS

DELAY_175MS:

;175MS

MOVR2,#73

JMPDELAY_MS

delaY_120MS:

;120MS

MOVR2,#50

JMPDELAY_MS

delay_60ms:

;60ms

MOVR2,#25

JMPDELAY_MS

delay_30ms:

;30ms

MOVR2,#12

JMPDELAY_MS

DELAY_5MS:

;5MS

MOVR2,#2

;===================================

DELAY_MS:

CALLDELAY2400

DJNZR2,DELAY_MS

RET

;===================================

DELAY2400:

;10x244+4=2447/1.024=2390

MOV

R0,#244

;1

DELAY24001:

MULAB

;4

MULAB

;4

DJNZR0,DELAY24001;2

RETDELAY:;延時(shí)子程序(1秒)

MOVR0,#0AH

DELAY1:MOVR1,#00H

DELAY2:MOVR2,#0B2H

DJNZR2,$

DJNZR1,DELAY2

DJNZR0,DELAY1

RET

MOVR2,#10;延時(shí)1秒

LCALLDELAY

MOVR2,#50;延時(shí)5秒

LCALLDELAY

DELAY:;延時(shí)子程序

PUSHR2

PUSHR1

PUSHR0

DELAY1:MOVR1,#00H

DELAY2:MOVR0,#0B2H

DJNZR0,$

DJNZR1,DELAY2;延時(shí)100mS

DJNZR2,DELAY1

POPR0

POPR1

POPR2

RET

1:DEL:

MOV

R7,

#200

DEL1:

MOV

R6,

#123

NOP

DEL2:

DJNZ

R6,

DEL2

DJNZ

R7,

DEL1

RET是50.001ms算法是:

0.001ms+200*0.001ms+200*0.001ms+200*123*0.002ms+200*0.002ms;(123*2+4)*200+12:DEL:MOVR7,#200

DEL1:MOVR6,#123

DEL2:NOP

DJNZR6,DEL2

DJNZR7,DEL1RETD500MS:

PUSHPSW

SETBRS0

MOVR7,#200

D51:MOVR6,#250

D52:NOP

NOP

NOP

NOP

DJNZR6,D52

DJNZR7,D51

POPPSW

RET

DELAY:;延時(shí)1毫秒

PUSHPSW

SETBRS0

MOVR7,#50

D1:MOVR6,#10

D2:DJNZR6,$

DJNZR7,D1

POPPSW

RET

ORG

0

LJMP

MAIN

ORG

000BH

LJMP

CTC0

MAIN:

MOV

SP,#50H

CLR

EA

MOV

TMOD,#01H

MOV

TH0,#3CH

MOV

TL0,#0B0H

MOV

R4,

#10

SETB

ET0

SETB

EA

SETB

TR0

SJMP

$

;

CTC0:

MOV

TH0,#3CH

MOV

TL0,#0B0H

DJNZ

R4,LP

CPL

P1.0

MOV

R4,

#10

LP:

RETI

END匯編延時(shí)程序算法詳解來(lái)源:嵌入式技術(shù)網(wǎng)作者:姜會(huì)敏時(shí)間:2008-01-01發(fā)布人:林逸摘要計(jì)算機(jī)反復(fù)執(zhí)行一段程序以達(dá)到延時(shí)的目的稱為軟件延時(shí),單片機(jī)應(yīng)用程序中經(jīng)常需要短時(shí)間延時(shí),有時(shí)要求很高的精度,網(wǎng)上或書中雖然有現(xiàn)成的公式可以套用,但在部分算法講解中發(fā)現(xiàn)有錯(cuò)誤之處,而且延時(shí)的具體算法講得并不清楚,相當(dāng)一部分人對(duì)此仍很模糊,授人魚,不如授之以漁,本文將以12MHZ晶振為例,詳細(xì)講解MCS-51單片機(jī)中匯編程序延時(shí)的精確算法。

關(guān)鍵詞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。

程序分析

例150ms延時(shí)子程序:

DEL:MOVR7,#200①

DEL1:MOVR6,#125②

DEL2:DJNZR6,DEL2③

DJNZR7,DEL1④

RET⑤

精確延時(shí)時(shí)間為:1+(1*200)+(2*125*2

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論