版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
有个好帖,从精度考虑,它得研究结果是:
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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 生物标志物在药物临床试验中的生物标志物策略
- 生物制品稳定性试验文档规范与完整性
- 生物制剂失应答后IBD的联合治疗策略-1
- 生物3D打印器官供应链管理策略
- 内控主管笔试题及解析
- 深度解析(2026)《GBT 19569-2004洁净手术室用空气调节机组》
- 生活方式干预习惯优化方案
- 体育产业资料员招聘面试问题集
- 日化产品销售数据分析技巧面试题
- 深度解析(2026)《GBT 19320-2003小艇 汽油发动机逆火火焰控制》
- 地质灾害危险性评估方案报告
- 感术行动培训课件
- DB44∕T 2552-2024 药物临床试验伦理审查规范
- 跨区域文化协作-洞察及研究
- 2025 易凯资本中国健康产业白皮书 -生物制造篇(与茅台基金联合发布)
- 产业经济学(苏东坡版)课后习题及答案
- T/CECS 10227-2022绿色建材评价屋面绿化材料
- 区域医学检验中心项目建设方案
- 小学四年级安全教育上册教学计划小学四年级安全教育教案
- 个人优势与劣势分析
- VCR接头锁紧工作程序
评论
0/150
提交评论