版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024游艇銷售及倉(cāng)儲(chǔ)物流服務(wù)合同范本3篇
- 二零二五年度廚房設(shè)備進(jìn)出口貿(mào)易合同2篇
- 專業(yè)2024委托獵頭服務(wù)協(xié)議范本版
- 二零二五年股東股權(quán)解除及退股條件明確協(xié)議書3篇
- 個(gè)人租車合同2024年度版:租賃工程車具體條款3篇
- 2024版承包經(jīng)營(yíng)權(quán)抵押合同
- 二零二五版?zhèn)€人房產(chǎn)抵押典當(dāng)經(jīng)營(yíng)合同3篇
- 臺(tái)州科技職業(yè)學(xué)院《內(nèi)科學(xué)B》2023-2024學(xué)年第一學(xué)期期末試卷
- 二零二五年股權(quán)投資合同具體條款2篇
- 二零二五年度汽車環(huán)保技術(shù)改造投資合同3篇
- 醫(yī)療組長(zhǎng)競(jìng)聘
- 2024年業(yè)績(jī)換取股權(quán)的協(xié)議書模板
- 顳下頜關(guān)節(jié)疾?。谇活M面外科學(xué)課件)
- 工業(yè)自動(dòng)化設(shè)備維護(hù)保養(yǎng)指南
- 2024人教新版七年級(jí)上冊(cè)英語(yǔ)單詞英譯漢默寫表
- 《向心力》參考課件4
- 2024至2030年中國(guó)膨潤(rùn)土行業(yè)投資戰(zhàn)略分析及發(fā)展前景研究報(bào)告
- 2024年深圳中考數(shù)學(xué)真題及答案
- 土方轉(zhuǎn)運(yùn)合同協(xié)議書
- Module 3 Unit 1 Point to the door(教學(xué)設(shè)計(jì))-2024-2025學(xué)年外研版(三起)英語(yǔ)三年級(jí)上冊(cè)
- 智能交通信號(hào)燈安裝合同樣本
評(píng)論
0/150
提交評(píng)論