51单片机KeilC延时程序的研究doc 13页Word文档格式.docx

上传人:b****5 文档编号:21014753 上传时间:2023-01-26 格式:DOCX 页数:7 大小:48.10KB
下载 相关 举报
51单片机KeilC延时程序的研究doc 13页Word文档格式.docx_第1页
第1页 / 共7页
51单片机KeilC延时程序的研究doc 13页Word文档格式.docx_第2页
第2页 / 共7页
51单片机KeilC延时程序的研究doc 13页Word文档格式.docx_第3页
第3页 / 共7页
51单片机KeilC延时程序的研究doc 13页Word文档格式.docx_第4页
第4页 / 共7页
51单片机KeilC延时程序的研究doc 13页Word文档格式.docx_第5页
第5页 / 共7页
点击查看更多>>
下载资源
资源描述

51单片机KeilC延时程序的研究doc 13页Word文档格式.docx

《51单片机KeilC延时程序的研究doc 13页Word文档格式.docx》由会员分享,可在线阅读,更多相关《51单片机KeilC延时程序的研究doc 13页Word文档格式.docx(7页珍藏版)》请在冰豆网上搜索。

51单片机KeilC延时程序的研究doc 13页Word文档格式.docx

djnzr0,loop

51单片机的指令周期是晶振频率的1/12,也就是1us一个周期。

movr0,#09h需要2个极其周期,djnz也需要2个极其周期。

那么存在r0里的数就是(20-2)/2。

用这种方法,可以非常方便的实现256us以下时间的延时。

如果需要更长时间,可以使用两层嵌套。

而且精度可以达到2us,一般来说,这已经足够了。

;

SOURCELINE#19

SOURCELINE#20

0000?

C0007:

0000EFMOVA,R7

00016003JZ?

C0010

00031FDECR7

000480FASJMP?

C0007

SOURCELINE#21

0006?

C0010:

000622RET

FUNCTION_delay2(END)

真是不看不知道~~~一看才知道这个延时程序是多么的不准点~~~光看主要的那四条语句,就需要6个机器周期。

也就是说,它的精度顶多也就是6us而已,这还没算上一条lcall和一条ret。

如果我们把调用函数时赋的i值根延时长度列一个表的话,就是:

idelaytime/us

06

112

218

...

因为函数的调用需要2个时钟周期的lcall,所以delaytime比从函数代码的执行时间多2。

顺便提一下,有的朋友写的是这样的代码:

voiddelay2(unsignedchari)

{

unsignedchara;

for(a=i;

a!

=0;

a--);

}

可能有人认为这会生成更长的汇编代码来,但是事实证明:

FUNCTION_delay2(BEGIN)

SOURCELINE#18

----Variable'

i'

assignedtoRegister'

R7'

----

a'

SOURCELINE#22

其生成的代码是一样的。

不过这的确不是什么好的习惯。

因为这里实在没有必要再引入多余的变量。

我们继续讨论正题。

有的朋友为了得当更长的延时,甚至用了这样的代码:

voiddelay2(unsignedlongi)

for(;

i!

i--);

这段代码产生的汇编代码是什么样子的?

其实不用想也知道它是如何恐怖的$#^%&

%$......让我们看一看:

00008F00RMOVi+03H,R7

00028E00RMOVi+02H,R6

00048D00RMOVi+01H,R5

00068C00RMOVi,R4

0008?

0008E4CLRA

0009FFMOVR7,A

000AFEMOVR6,A

000BFDMOVR5,A

000CFCMOVR4,A

000DAB00RMOVR3,i+03H

000FAA00RMOVR2,i+02H

0011A900RMOVR1,i+01H

0013A800RMOVR0,i

0015C3CLRC

0016120000ELCALL?

C?

ULCMP

0019601AJZ?

001BE500RMOVA,i+03H

001D24FFADDA,#0FFH

001FF500RMOVi+03H,A

0021E500RMOVA,i+02H

002334FFADDCA,#0FFH

0025F500RMOVi+02H,A

0027E500RMOVA,i+01H

002934FFADDCA,#0FFH

002BF500RMOVi+01H,A

002DE500RMOVA,i

002F34FFADDCA,#0FFH

0031F500RMOVi,A

003380D3SJMP?

0035?

003522RET

呵呵,这倒是的确可以延迟很长时间~~~但是毫无精度可言了。

那么,用C到底能不能实现精确的延时呢?

我把代码稍微改了一下:

voiddelay1(unsignedchari)

while(i--);

因为根据经验,越简洁的C代码往往也能得出越简洁的机器代码。

那这样结果如何呢?

把它生成的汇编代码拿出来看一看就知道了。

满怀希望的我按下了“Buildtarget”键,结果打击是巨大的:

FUNCTION_delay1(BEGIN)

SOURCELINE#13

SOURCELINE#14

C0004:

SOURCELINE#15

0000AE07MOVR6,AR7

00021FDECR7

0003EEMOVA,R6

000470FAJNZ?

C0004

SOURCELINE#16

C0006:

FUNCTION_delay1(END)

虽说生成的代码跟用for语句是不大一样,不过我可以毫无疑问的说,这两种方法的效率是一样的。

似乎到此为止了,因为我实在想不出来源程序还有什么简化的余地。

看来我就要得出来这个结论了:

“如果需要us级的延时精度,需要时用汇编语言。

”但是真的是这样吗?

我还是不甘心。

因为我不相信大名鼎鼎的KeilC编译器居然连djnz都不会用?

因为实际上程序体里只需要一句loop:

djnzr7,loop。

近乎绝望之际(往往人在这种情况下确可以爆发出来,哦呵呵呵~~~),我随手改了一下:

while(--i);

心不在焉的编译,看源码:

0000DFFEDJNZR7,?

0002?

000222RET

天~~~奇迹出现了......我想这个程序应该已经可以满足一般情况下的需要了。

如果列个表格的话:

15

27

39

计算延时时间时,已经算上了调用函数的lcall语句所花的2个时钟周期的时间。

终于,结果已经明了了。

只要合理的运用,C还是可以达到意想不到的效果。

很多朋友抱怨C效率比汇编差了很多,其实如果对KeilC的编译原理有一个较深入的理解,是可以通过恰当的语法运用,让生成的C代码达到最优化。

即使这看起来不大可能,但还是有一些简单的原则可循的:

1.尽量使用unsigned型的数据结构。

2.尽量使用char型,实在不够用再用int,然后才是long。

3.如果有可能,不要用浮点型。

4.使用简洁的代码,因为按照经验,简洁的C代码往往可以生成简洁的目标代码(虽说不是在所有的情况下都成立)

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1