C及汇编延时程序_第1页
C及汇编延时程序_第2页
C及汇编延时程序_第3页
C及汇编延时程序_第4页
C及汇编延时程序_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

有个好帖,从精度考虑,它得研究结果是:

voiddelay2(unsignedchari)

(

while(—i);

)

为最佳方法。

分析:假设外挂12M(之后都是在这基础上讨论)

我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:

delay2(0)延:时518us518-2*256=6

dday2(l)延时7us(原帖写,5us是嘴的,A_A)

delay2(10)延:时25us25-20=5

delay2(20)延:时45us45-40=5

delay2(100)延:时205us205-200=5

delay2(200)延:时4()5us405-400=5

见上可得可调度为2us,而最大误差为6us。

精度是很高了!

但这个程序的最大延时是为518us显然不

能满足实际需要,因为不少时候需要延迟比较长的时间。

那末,接下来讨论将t分配为两个字节,即uint型的时候,会浮现什么情况。

voiddelay8(uintt)

while(-t);

}

我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:

delay&O)延:时524551us524551-8*65536=263

delayS(l)延:时15us

delay&10)延时85us85-80=5

delay&100)延:时806us806-800=6

delay&lOOO)延时8009us8009-8000=9

80()45-8000=45

dclay8(10000)延:时80045us

524542-524280=262

delay8(65535)延:时524542us

8us,那末最大误差为263us,但这个延时程序还

如果把这个程序的可调度看为

是不能满足要求的,因为延时最大为524.551ms。

那末用ulongt呢?

一定很恐怖,不用看编译后的汇编代码了。。。

那末如何得到比较小的可调度,可调范围大,并占用比较少得RAM呢?请看下

面的程序:

/*-----------------------------------------------程序名称:50us延时

注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶

例子提示:调用delay_50us(20),得到1ms延时

全局变量:无

返回:无--------------------------------

-----------------------*/voiddelay_5()us(uintt)

(

ucharj;

for(;t>0;t-)

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

}

我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:

delay_50us⑴延时63us63-50=13

delay_50us(l0)延时513us503-500=13

delay_50us(l00)延:时5013us5013-5000=13

delay_50us(1000)延:时50022us50022-50000=22

赫赫,延时50ms,误差仅仅22us,作为C语言已是可以接受了。再说要求再精

确的话,就算是用汇编也得改用定时器了。

/*----------------------------------------------程序名称:5()ms延时

注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶

例子提示:调用dclay_50ms(20),得到Is延时

全局变量:无

返回:无--------------------------------

-----------------------♦/voiddelay_5()ms(uintt)

uintj;

/****

可以在此加少许延时补偿,以祢补大数值传递时(如delay_50ms(1000))造成的

误差,

但付出的代价是造成传递小数值(delay_50ms(1))造成更大的误差。

因为实际应用更多时候是传递小数值,所以补建议加补偿!

****/

for(;t>0;t-)

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

}

我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:

delay_50ms⑴延:时5()()1()]0us

delay_50ms(10)延:时49998317us

dclay_50ms(100)延:时4999713287us

delay_50ms(l000)延:时49970222.978ms

赫赫,延时50s,误差仅仅2.978ms,可以接受!

上面程序没有才用long,也没采用3层以上的循环,而是将延时分拆为两个程序

以提高精度。应该是比较好的做法了

问题内容:怎样用c语言写延时程序

混霜校展接单用朋嚷以甯修嘉,娜儆呼蟒l.asp?id=4760346

提问者:zhanisl解决者:hiflower

感谢:iccsnowsshimd0604sclarkca81061yiowcrcitiyccsnowstony1976

tony1976eastrcdinp2003hu_an_xiong517517hiflowertyj_3

关键字:函数语句硬件/嵌入开辟单片机指令汇编void循环定时周期

单片机/工控

答案:

要求是秒级的,同时说明下原理

空循环就行了

如据i的不同决定了延时长短

无非C的延时不是非常准确,你得根据反汇编,看汇编语句的数

量和指令周期来计算时间

楼上的说得很对,用C语言编写单片机程序时,普通开辟界面(如科

尔KE1LE)都提供了C-汇编的代码转换,参照转换后的汇编语言就

可以精确延时了

你可以数指令,然后按着MCU的MIPS算时间,结果应该比较精

确:)

voidmDelay(unsignedintDelay)//Delay时二间10/ODS

(

unsignedinti;

for(;Dclay>0:Dclay—)

{

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

(;)

数一次循环的汇编指令,再乘以指令周期就知道一次循环的时间

了啊,然后用1秒一除,不就知道循环次数了么

秒级的本身精度要求就不高嘛

很容易控制啊

多套用几个for语句

或者在for语句里引用n个更低量级的(如100ms级)的延时函数即可

要精确就计算汇编代码执行长度

toflowcrcity(LovcPiog,niLmovcLiving):

你的函数没有什么参考价值

延时时间和指令周期以及编译出来的代码类型有关系的

不是所谓

//Delay=100时0间为1S

就是一定的.

那只是针对你现在的系统.

用的晶振不同,执行CPU指令周期和时钟周期比率不同

结果都不同

秒级的,用定时器比较好吧。

voidwaitms(inti)

(

charm;

for(;i;i-)

(

for(m=203;m;m-)

(

_nop_();

_nop_0;

_nop_0;

_nop_();

_nop_0;

_nop_Q;

_nop_();

)

I

1

延时1ms的函数

时钟频率12MHz

空操作,无非不好做到很准确

秒级延时,用指令的话,你要求延时的精确度是多少,高的话最

好用定时器,而且你延时这么长,你的CPU不是就向来占用了

浪费呀…

与定时器中断服务程序配合实现延时。

unsignedintsleepTiine;

unsingedcharinSleep=0;

voidsleepService(void)

if(inSleep)sleepTime";

if(sleepTime==0)inSIcep=0;

)

voidisr_timer(voi取淀/定时器中断1ms中断一次。

sleepService();

1-

voidsleep(unsignedint延s)时万7程序

(

sleepTime=ms;

inSleep=1;

while(inSleep);

)

voidmain(void)

sleep(1000)涎时秒

}

>>要求是秒级的

这么长的延时,单片机中普通采取不占CPU时间的延时,利用定

时器来实现延时,

如果非得用循环延时,在C中也通常嵌入汇编实现,这样误差比

较小

在论坛上看到不少不错的延时程序,整理如下共同分享:

精确延时计算公式:

延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+5

;延时5秒摆布

DELAY5S:PUSH04H

PUSH05H

PUSH06H

MOVR4,#50

DELAY5SJ):MOVR5,#200

DELAY5S_1:MOVR6,#245

D进HSbQ,2

D进HSb?,DETV人?2」

D进HSb寸JDETV人?2_0

bObOQH

bOb0?H

bOb0寸H

bEL

:?J3谢新兵阱程各

DETVA:NOAbS,#OEEH

DETVAJ:D进HSbS,DETV人J

bEL

:JO膏新兵阱程各

DTJ0N2:NOAb3,#J、JH

DTJ0N2J:TCVTTDETVA

D进HSb3,DTJON2J

bEL

:0J2兵阱程各JSinps-

DETVA:NOAbQ,#S?O

DTJ:NOAb\,#SOO

DTS:D进HSbQ,DTS

D进HSb\,DTJ

bEL

:兵阱JO寸Q?'Joi^tWr(JSirps)

:首悼的斗算安点房:

:((((r\*S+J)+S)*rQ+J)+S)*r?+Jh^((r\*S+3)*rQ+3)

*r?+?

DET:NOAb?,#O8H

DETJ:NOAbQ,#0EEH

DETS:NOAb\,#()EEH

D进HSb12

DfflHSbQ,DETS

D进HSb?,DETJ

bEL

1秒延时子程序是以12MHz晶振

DelaylS:movrl,#50

delO:movr2,#91

dell:movr3,#l()()

djnzr3,$

djnzr2,del1

djnzrl.delO

Ret

;i秒延时子程序是以12MHz晶振为例算指令周期耗时

KK:MOVR5,#10;1指令周期1

KI:MOVR6,#0FFH;1指令周期10

K2:MOVR7,#80H;1指令周期256*10=2560

K3:NOP;1指令周期

128*256*10=327680

DJNZR7,K3;2指令周期

2*128*256*10=655360

DJNZR6,K2;2指令周期

2*256*10=5120

DJNZR5,KI;2指令周期2*10=20

RET

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

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

;这个算下来也惟独0.998抄

T_0:MOVR7,#10;

DI:MOVR6,#200;

D2:MOVR5,#248;

DJNZR5,$

DJNZR6,D2;

DJNZR7,D1;

RET

;这样算下来应该是1.000011秒

TZO:MOVR7,#10;

DI:MOVR6,#200;

D2:NOP

MOVR5,#248;

DJNZR5,$

DJNZR6,D2;

DJNZR7,D1;

RET

DELAY_2S:;I0MS(II.0592mhz)

MOVR3,#200

JMPDELAY10MS

DELAY_1OOMS:;100MS(l1.0592mhz)

MOVR3,#l()

JMPDELAY10MS

DELAY_10MS:

MOVR3,#I

DELAY10MS:;去颤动10MS

(1LO592mhz)

MOVR4,#20

DELAY10MSA:

MOVR5,#247

DJNR5,$

ZR4,DELAY10MSA

2JNR3,DELAY10MS

DJN

Z

RET

DELAY_500MS:;5(X)5OOMS

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

DELAY24(X):;10x244+4=2447

71.024=2390

MOVR0,#244;1

DELAY24001:

MULAB;4

MULAB;4

DJNZR0,DELAY24001;2

RET

DELAY:;延时子程序(1秒)

MWR0,#0AH

DELAY1:MOVRl,#()0H

DELAY2:MOVR2J0B2H

DJNZR2,$

DJNZR1,DELAY2

DJNZRO,DELAY1

RET

MOVR2,#10;延时1秒

LCALLDELAY

MOVR2,#50;延时5秒,

LCALLDELAY

DELAY:;延时子程序

PUSHR2

PUSHRI

PUSHRO

DELAY1:MOVRl,#00H

DELAY2:MOVR0J0B2H

DJNZR0,$

DJNZR1,DELAY2;延时100mS

DJNZR2,DELAY1

POPRO

POPRI

POPR2

RET

一ADELMtW—际#2加----------------------------------------

DELI:MOVR6,#123

NOP

DEL2:DJNZR6,DEL2

DJNZR7,DELI

RET

是50.001ms算法是:

0.001ms-t-200*0.001ms+200*0.001ms+200*123*0.002ms+200*0.002ms

;(123*2+4)*200+1

2:DEL:MOVR7,#200

DELI:MOVR6,#123

DEL2:NOP

DJNZR6,DEL2

DJNZR7,DEL1

RET

D500MS:

EUSH-ESW------------------------------------------------------------------------

SETBRSO

MOVR7,#200

D51:MOVR6,#250

D52:NOP

NOP

NOP

NOP

DJNZR6,D52

DJNZR7,D51

POPPSW

RET

DELAY:;延时1毫秒

PUSHPSW

SETBRSO

MOVR7,#5()

DI:MOVR6,#10

D2:DJNZR6,$

DJNZR7,D1

POPPSW

RET

ORG0

LJMPMAIN

OR000BH

GCTCO

LJMP

MAIN:MOVSP,#50H

CLREA

MOVTMOD,#01H

MOVTHO,#3cH

MOVTL(),#()B()H

MOVR4,#10

SETETO

口人

BEA

SET

gTRO

SET$;

B

SJMP

CTCO:MOVTHO,#3CH

MOVTLO,#0B0H

DJNZR4,LP

CPLPI.0

MOVR4,#10

LP:RETI

END

汇编延时程序算法详解

来源:嵌入式技术网作者:姜会敏时间:2022-01-01发布人:林逸

摘要计算机反复执行一段程序以达到延时的目的称为软件延时,单片机应

用程序中时常需要短期延时,有时要求很高的精度,网上或者书中虽然有现成的

公式可以套用,但在部份算法讲解中发现有错误之处,而且延时的具体算法讲得

并不清晰,相当一-部份人对此仍很含糊,授人鱼,不如授之以渔,本文将以12MHz

晶振为例,详细讲解MCS-51单片机中汇编程序延时的精确算法。

关键词51单片机汇编延时算法

指令周期、机器周期与时钟周期

指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周

期为单位的,指令不同,所需的机器周期也不同,

时钟周期:也称为振荡周期,一个时钟周期=晶振的倒数。

MCS-51单片机的一个机器周期=6个状态周期=12个时钟周期。

MCS-51单片机的指令有单字节、双字节和三字节的,它们的指令周期不

尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周

期指令被执行所占时间为12*(1/12000000)=1So

程序分析

例150ms延时子程序:

DEL:MOVR7,#200①

DELI:MOVR6,#125@

DEL2:DJNZR6,DEL2③

DJNZR7,DELI④

RET⑤

精确延时时间为:1+(1*200)+(2*125*200)+(2*200)+2=(

2*125+3)*200+3⑥

=50603s

-50ms

由⑥整理出公式(只限上述写法)延时时间=(2*内循环+3)*外循环+3©

详解:DEL这个子程序共有五条指令,现在分别就每一条指令被执行的

次数和所耗时间进行分析。

第一句:MOVR7,#200在整个子程序中只被执行一次,且为单周期指令,

所以耗时1s

第二句:MOVR6,#125从②看到④只要R7-1不为0,就会返回到这句,

共执行了R7次,共耗时200s

第三句:DJNZR6,DEL2只要R&1不为0,就反复执行此句(内循环R6次),又

受外循环R7控制,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论