版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
有个好帖,从精度考虑,它得研究结果是:
void
delay2(unsigned
char
i)
{
while(--i);
}
为最佳方法。
分析:假设外挂12M(之后都是在这基础上讨论)
我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:
delay2(0):延时518us
518-2*256=6
delay2(1):延时7us(原帖写“5us”是错的,^_^)
delay2(10):延时25us
25-20=5
delay2(20):延时45us
45-40=5
delay2(100):延时205us
205-200=5
delay2(200):延时405us
405-400=5
见上可得可调度为2us,而最大误差为6us。
精度是很高了!
但这个程序的最大延时是为518us
显然不
能满足实际需要,因为很多时候需要延迟比较长的时间。
那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。
void
delay8(uint
t)
{
while(--t);
}
我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:
delay8(0):延时524551us
524551-8*65536=263
delay8(1):延时15us
delay8(10):延时85us
85-80=5
delay8(100):延时806us
806-800=6
delay8(1000):延时8009us
8009-8000=9
delay8(10000):延时80045us
80045-8000=45
delay8(65535):延时524542us
524542-524280=262
如果把这个程序的可调度看为8us,那么最大误差为263us,但这个延时程序还是不能满足要求的,因为延时最大为524.551ms。
那么用ulong
t呢?
一定很恐怖,不用看编译后的汇编代码了。。。
那么如何得到比较小的可调度,可调范围大,并占用比较少得RAM呢?请看下面的程序:
/*--------------------------------------------------------------------
程序名称:50us
延时
注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶振
例子提示:调用delay_50us(20),得到1ms延时
全局变量:无
返回:
无
--------------------------------------------------------------------*/
void
delay_50us(uint
t)
{
uchar
j;
for(;t>0;t--)
for(j=19;j>0;j--)
;
}
我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:
delay_50us(1):延时63us
63-50=13
delay_50us(10):延时513us
503-500=13
delay_50us(100):延时5013us
5013-5000=13
delay_50us(1000):延时50022us
50022-50000=22
赫赫,延时50ms,误差仅仅22us,作为C语言已经是可以接受了。再说要求再精确的话,就算是用汇编也得改用定时器了。
/*--------------------------------------------------------------------
程序名称:50ms
延时
注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶振
例子提示:调用delay_50ms(20),得到1s延时
全局变量:无
返回:
无
--------------------------------------------------------------------*/
void
delay_50ms(uint
t)
{
uint
j;
/****
可以在此加少许延时补偿,以祢补大数值传递时(如delay_50ms(1000))造成的误差,
但付出的代价是造成传递小数值(delay_50ms(1))造成更大的误差。
因为实际应用更多时候是传递小数值,所以补建议加补偿!
****/
for(;t>0;t--)
for(j=6245;j>0;j--)
;
}
我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:
delay_50ms(1):延时50
010
10us
delay_50ms(10):延时499
983
17us
delay_50ms(100):延时4
999
713
287us
delay_50ms(1000):延时4
997
022
2.978ms
赫赫,延时50s,误差仅仅2.978ms,可以接受!
上面程序没有才用long,也没采用3层以上的循环,而是将延时分拆为两个程序以提高精度。应该是比较好的做法了问题内容:怎样用c语言写延时程序原讨论链接:/expert/topicview1.asp?id=4760346所属论坛:单片机/工控
审核组:硬件/嵌入开发提问者:\o"zharrisl个人空间"zharrisl
解决者:\o"hiflower个人空间"hiflower感谢:\o"icesnows个人空间"icesnows\o"shimd0604个人空间"shimd0604\o"sclarkca810619个人空间"sclarkca810619\o"flowercity个人空间"flowercity\o"icesnows个人空间"icesnows\o"tony1976个人空间"tony1976\o"tony1976个人空间"tony1976\o"eastred个人空间"eastred\o"winp2003个人空间"winp2003\o"hu_an_xiong个人空间"hu_an_xiong\o"517517个人空间"517517\o"hiflower个人空间"hiflower\o"tyj_3个人空间"tyj_3关键字:函数语句硬件/嵌入开发单片机指令汇编void循环定时周期单片机/工控答案:要求是秒级的,同时说明下原理
---------------------------------------------------------------
空循环就行了
如while(i--);根据i的不同决定了延时长短
不过C的延时不是非常准确,你得根据反汇编,看汇编语句的数量和指令周期来计算时间
---------------------------------------------------------------
楼上的说得很对,用C语言编写单片机程序时,一般开发界面(如科尔KEILE)都提供了C
-
汇编的代码转换,参照转换后的汇编语言就可以精确延时了
---------------------------------------------------------------
你可以数指令,然后按着MCU的MIPS算时间,结果应该比较精确:)
---------------------------------------------------------------
void
mDelay(unsigned
int
Delay)
//Delay
=
1000
时间为1S
{
unsigned
int
i;
for(;Delay>0;Delay--)
{
for(i=0;i<124;i++)
{;}
}
}
---------------------------------------------------------------
数
一次循环的汇编指令,再乘以指令周期就知道一次循环的时间了啊,然后用1秒一除,不就知道循环次数了么
---------------------------------------------------------------
秒级的本身精度要求就不高嘛
很容易控制啊
多套用几个for语句
或者在for语句里引用n个更低量级的(如100ms级)的延时函数即可
要精确就计算汇编代码执行长度
---------------------------------------------------------------
to
flowercity(Love
Program,Love
Living):
你的函数没有什么参考价值
延时时间和指令周期以及编译出来的代码类型有关系的
不是所谓
//Delay
=
1000
时间为1S
就是一定的.
那只是针对你现在的系统.
用的晶振不同,执行CPU指令周期和时钟周期比率不同
结果都不同
---------------------------------------------------------------
秒级的,用定时器比较好吧。
---------------------------------------------------------------
void
waitms(int
i)
{
char
m;
for(
;
i
;i--)
{
for(m
=
203;
m
;
m--)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
延时1ms的函数
时钟频率12MHz
---------------------------------------------------------------
空操作,不过不好做到很准确
---------------------------------------------------------------
秒级延时,用指令的话,你要求延时的精确度是多少,高的话最好用定时器,而且你延时这么长,你的CPU不是就一直占用了,浪费呀。。。
---------------------------------------------------------------
与定时器中断服务程序配合实现延时。
unsigned
int
sleepTime;
unsinged
char
inSleep
=
0;
void
sleepService(void)
{
if
(inSleep)
sleepTime--;
if
(sleepTime
==
0)
inSleep
=
0;
}
void
isr_timer(void)
//假定定时器中断1ms
中断一次。
{
...
sleepService();
...
}
void
sleep(unsigned
int
ms)
//延时子程序
{
sleepTime
=
ms;
inSleep
=
1;
while(inSleep);
}
void
main(void)
{
....
sleep(1000);
//延时
1秒
...
}
---------------------------------------------------------------
>>要求是秒级的
这么长的延时,单片机中一般采取不占CPU时间的延时,利用定时器来实现延时,
如果非得用循环延时,在C中也通常嵌入汇编实现,这样误差比较小在论坛上看到不少不错的延时程序,整理如下共同分享:精确延时计算公式:延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+5;延时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微秒延时程序
DELAY:
MOV
R2,#0FEH
DELAY1:DJNZ
R2,DELAY1
RET;10毫秒延时程序
DL10MS:MOV
R3,#14H
DL10MS1:LCALL
DELAY
DJNZ
R3,DL10MS1
RET;0.1s延时程序12mhz
DELAY:MOVR6,#250
DL1:MOVR7,#200
DL2:DJNZR6,DL2
DJNZR7,DL1
RET;延时1046549微秒(12mhz)
;具体的计算公式是:
;((((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秒延时子程序是以12MHz晶振
Delay1S:mov
r1,#50
del0:
movr2,#91
del1:
movr3,#100
djnzr3,$
djnzr2,del1
djnzr1,del0
Ret;1秒延时子程序是以12MHz晶振为例算指令周期耗时
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微秒
;这个算下来也只有0.998抄
T_0:
MOV
R7,#10;
D1:
MOV
R6,#200;
D2:
MOV
R5,#248;
DJNZ
R5,$
DJNZ
R6,D2;
DJNZ
R7,D1;
RET;这样算下来应该是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:
;去抖动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:;延时子程序(1秒)
MOVR0,#0AH
DELAY1:MOVR1,#00H
DELAY2:MOVR2,#0B2H
DJNZR2,$
DJNZR1,DELAY2
DJNZR0,DELAY1
RET
MOVR2,#10;延时1秒
LCALLDELAY
MOVR2,#50;延时5秒
LCALLDELAY
DELAY:;延时子程序
PUSHR2
PUSHR1
PUSHR0
DELAY1:MOVR1,#00H
DELAY2:MOVR0,#0B2H
DJNZR0,$
DJNZR1,DELAY2;延时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:;延时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汇编延时程序算法详解来源:嵌入式技术网作者:姜会敏时间:2008-01-01发布人:林逸摘要计算机反复执行一段程序以达到延时的目的称为软件延时,单片机应用程序中经常需要短时间延时,有时要求很高的精度,网上或书中虽然有现成的公式可以套用,但在部分算法讲解中发现有错误之处,而且延时的具体算法讲得并不清楚,相当一部分人对此仍很模糊,授人鱼,不如授之以渔,本文将以12MHZ晶振为例,详细讲解MCS-51单片机中汇编程序延时的精确算法。
关键词51单片机汇编延时算法
指令周期、机器周期与时钟周期
指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。
时钟周期:也称为振荡周期,一个时钟周期=晶振的倒数。
MCS-51单片机的一个机器周期=6个状态周期=12个时钟周期。
MCS-51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/12000000)=1µs。
程序分析
例150ms延时子程序:
DEL:MOVR7,#200①
DEL1:MOVR6,#125②
DEL2:DJNZR6,DEL2③
DJNZR7,DEL1④
RET⑤
精确延时时间为:1+(1*200)+(2*125*2
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《第二单元 多彩的游记 2 设计版面》教学实录-2024-2025学年川教版信息技术(2019)四年级下册
- 设计制作校园植物名片(教学实录)2024-2025学年四年级上册信息技术苏科版
- 商品贸易采购合同范例
- 临安区房产买卖合同范例
- 承包土地写合同范例
- 2025年镇江道路客货运输从业资格证b2考试题库
- 员工激励股合同范例
- 人工智能风险治理报告(2024年)-构建面向产业的人工智能安全治理实践方案
- 版纳租车合同范例
- 个人租房合同范例版
- 钢结构竣工验收报告(范文)
- 数学文化欣赏
- 脊柱区1教学讲解课件
- KK5-冷切锯操作手册-20151124
- 人工智能对中学教学的影响与应对策略
- 闭合导线自动计算表
- 分管学校安全、德育、后勤等业务副校长述职报告
- 笔试考试:HSK笔试(三级)真题模拟汇编(共603题)
- 全国城市一览表-excel
- 国际金融课后习题答案(吴志明第五版)第1-9章
- 《WPS演示制作与设计》计算机应用基础高职专科一等奖(含课件制作试题及答案)
评论
0/150
提交评论