ImageVerifierCode 换一换
格式:DOCX , 页数:13 ,大小:19.73KB ,
资源ID:2922549      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-2922549.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(精确延时.docx)为本站会员(b****1)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

精确延时.docx

1、精确延时KEIL单片机C语言精确延时值的计算 2011-11-20 20:54| 发布者: pcb_dz| 查看: 111| 评论: 0|来自: 关于单片机C语言的精确延时,网上很多都是大约给出延时值没有准确那值是多少,也就没有达到精确高的要求,而51hei给出的本函数克服了以上缺点,能够精确计数出要延时值且精确达到1us,本举例所用CPU为STC12C5412系列12倍速的单片机,只要修改一下参数值其它系例单片机也通用,适用范围宽。共有三条延时函数说明如下:函数调用分两级:一级是小于10US的延时,二级是大于10US的延时/=小于10US的【用1US级延时】=/-微秒级延时-for(i=X;

2、iX;i-) 延时时间=(3+5*X)/12 提示(单位us, X不能大于255)/=大于10US0;Ms-) for(i=26;i0;i-);i=(延时值-1.75)*12/Ms-15/4如想延时60US则 i=(60-1.75)*12/6-15/4=25.37526; 修改i的值=26,再调用上面的【10US级延时函数】Delay10us(6); 则就精确延时60US;如果想延时64US可以用这二种函数组合来用: Delay10us(6); for(i=9;iX;i-) 共延时64US/=对于大于20Ms的可用中断来实现程序运行比较好=中断用定时器0, 1Ms中断:void timer0(

3、void) interrupt 1 TL0=(0xffff-1000+2)%0x100;TH0=(0xffff-1000+2)/0x100; /每毫秒执行一次 if(DelayMs_10)DelayMs_1-;/大于20Ms延时程序 函数调用void DelayMs(uint a)/延时 a1(ms)的时间。 DelayMs_1=a; while(DelayMs_1);如果延时50Ms则 函数值为 DelayMs(50)/+公式推算来由+二级延时C语言反汇编见上传图1: /=STC单片机延时指令时间=指今 时间(1us) 指今 时间(1us)MOV A Rn 1 SETB C 1MOV Rn

4、#data 2 SUBB A #data 2 DJNZ Rn rel 4 Dec Rn 3 SJMP rel 3 JC rel 3 MOV Rn direct 4 Lcall addr16 6 RET 4 /-JNZ 3 XRL 2SUBB 3使用Delay10us(uchar Ms) 最多能延时21995.5us;其中循环外函数调用与返回用的时间=(6+4)进入+退出(1+1+2+3+,4)=10+11=21/12=1.75us;循环内函数时间 MS= Ms*(1+1+2+3,+2+4*I+3+3)/12=Ms*(15+4*I)/12 ; 所以如果延时60us时用【10US级延时函数】I的值

5、为:60=循环外时间+循环内时间=1.75us+ Ms*(15+4*I)/12;则i=(60-1.75)*12/6-15/4=25.37526即如果Ms=6, i=26;本算法中的12是STC12单片机与普通标准速率比。C语言写程序时,初学者遇到的一个难题时精确延时程序的设计。我刚开始用C语言写程序时同样遇到了这个问题,后来参考了一些文章和实际设计后才知道了精确延时程序的设计。 我现在就用两种方法来实现,一种是while()语句,另一种是for()语句,这两种语句均可产生汇编语句中的DJNZ语句,以12MHZ晶振为例(说明:在编写C程序时,变量尽量使用unsigned char,如满足不了才使

6、用unsigned int): 1.delay99;while(-delay);产生的汇编代码为:000FH MOV 08H,#63H0012H DJNZ 08H,0012H这样产生的延时时间为:(99+1)2us。最小延时时间为2us,若加上对delay赋值语句,则最小为4us。 2.for(i=delay;i0;i-);产生的汇编代码同while()语句。 下面来举例几个延时函数: 一. 500ms延时子程序void delay500ms(void) unsigned char i,j,k;for(i=15;i0;i-)for(j=202;j0;j-)for(k=81;k0;k-);产生的

7、汇编代码:C:0x0800 7F0F MOV R7,#0x0FC:0x0802 7ECA MOV R6,#0xCAC:0x0804 7D51 MOV R5,#0x51C:0x0806 DDFE DJNZ R5,C:0806C:0x0808 DEFA DJNZ R6,C:0804C:0x080A DFF6 DJNZ R7,C:0802C:0x080C 22 RET 计算分析:程序共有三层循环一层循环n:R5*2 = 81*2 = 162us DJNZ 2us二层循环m:R6*(n+3) = 202*165 = 33330us DJNZ 2us + R5赋值 1us = 3us三层循环: R7*(

8、m+3) = 15*33333 = 499995us DJNZ 2us + R6赋值 1us = 3us循环外: 5us 子程序调用 2us + 子程序返回 2us + R7赋值 1us = 5us延时总时间 = 三层循环 + 循环外 = 499995+5 = 500000us =500ms计算公式:延时时间=(2*R5+3)*R6+3*R7+5 二. 200ms延时子程序void delay200ms(void) unsigned char i,j,k; for(i=5;i0;i-) for(j=132;j0;j-) for(k=150;k0;k-); 三. 10ms延时子程序void de

9、lay10ms(void) unsigned char i,j,k; for(i=5;i0;i-) for(j=4;j0;j-) for(k=248;k0;k-); 四. 1s延时子程序void delay1s(void) unsigned char h,i,j,k; for(h=5;h0;h-) for(i=4;i0;i-) for(j=116;j0;j-) for(k=214;k0;k-);以上的这先希望对大家有帮组,如有不足之处请指出,如有更好的方法也可以告诉我,大家一起分享C语言最大的缺点就是实时性差,我在网上到看了一些关于延时的讨论,其中有篇文章51单片机 Keil C 延时程序的简

10、单研究,作者:InfiniteSpace Studio/isjfk 写得不错,他是用while(-i);产生DJNZ 来实现精确延时,后来有人说如果while里面不能放其它语句,否则也不行,用do-while就可以,具体怎样我没有去试.所有这些都没有给出具体的实例程序来.还看到一些延时的例子多多少少总有点延时差.为此我用for循环写了几个延时的子程序贴上来,希望能对初学者有所帮助.(晶振12MHz,一个机器周期1us.)void Delay(uchar i)while(-i); 21: void Delay(uchar i) 22: 23: while(-i); C:0x001F DFFE D

11、JNZ R7,Delay(C:001F) 24: 一. 500ms延时子程序程序: void delay500ms(void) unsigned char i,j,k;for(i=15;i0;i-)for(j=202;j0;j-)for(k=81;k0;k-); 产生的汇编:C:0x08007F0F MOVR7,#0x0FC:0x08027ECA MOVR6,#0xCAC:0x08047D51 MOVR5,#0x51C:0x0806DDFE DJNZ R5,C:0806C:0x0808DEFA DJNZ R6,C:0804C:0x080ADFF6 DJNZ R7,C:0802C:0x080C2

12、2 RET计算分析:程序共有三层循环一层循环n:R5*2 = 81*2 = 162usDJNZ2us二层循环m:R6*(n+3) = 202*165 = 33330usDJNZ2us + R5赋值 1us = 3us三层循环: R7*(m+3) = 15*33333 = 499995usDJNZ2us + R6赋值 1us = 3us循环外: 5us子程序调用 2us + 子程序返回 2us + R7赋值 1us= 5us延时总时间 = 三层循环 + 循环外 = 499995+5 = 500000us =500ms计算公式:延时时间=(2*R5+3)*R6+3*R7+5二. 200ms延时子程

13、序程序:void delay200ms(void) unsigned char i,j,k;for(i=5;i0;i-)for(j=132;j0;j-)for(k=150;k0;k-);产生的汇编C:0x08007F05 MOVR7,#0x05C:0x08027E84 MOVR6,#0x84C:0x08047D96 MOVR5,#0x96C:0x0806DDFE DJNZ R5,C:0806C:0x0808DEFA DJNZ R6,C:0804C:0x080ADFF6 DJNZ R7,C:0802C:0x080C22 RET三. 10ms延时子程序程序:void delay10ms(void)

14、 unsigned char i,j,k;for(i=5;i0;i-)for(j=4;j0;j-)for(k=248;k0;k-);产生的汇编C:0x08007F05 MOVR7,#0x05C:0x08027E04 MOVR6,#0x04C:0x08047DF8 MOVR5,#0xF8C:0x0806DDFE DJNZ R5,C:0806C:0x0808DEFA DJNZ R6,C:0804C:0x080ADFF6 DJNZ R7,C:0802C:0x080C22 RET四. 1s延时子程序程序:void delay1s(void) unsigned char h,i,j,k;for(h=5;

15、h0;h-)for(i=4;i0;i-)for(j=116;j0;j-)for(k=214;k0;k-);产生的汇编C:0x08007F05 MOVR7,#0x05C:0x08027E04 MOVR6,#0x04C:0x08047D74 MOVR5,#0x74C:0x08067CD6 MOVR4,#0xD6C:0x0808DCFE DJNZ R4,C:0808C:0x080ADDFA DJNZ R5,C:0806C:0x080CDEF6 DJNZ R6,C:0804C:0x080EDFF2 DJNZ R7,C:0802C:0x081022 RET在精确延时的计算当中,最容易让人忽略的是计算循环

16、外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响.设晶振频率为12M,单片机为AT89C51。则知一个机器周期为1us。现有延时函数如下: 3: void delay(void) 4: 5: unsigned char i,j,k; 6: for(i=15;i0;i-) 7: for(j=202;j0;j-) 8: for(k=81;k0;k-); 9: 以上就是利用C51语言编写的一个延时函数,下面这段代码则是利用keil软件翻译的一段汇编语言程序段,大家可以对照着看。 机器周期数 C:0x0800 7F0F MOV R7,#0x0F 1 C:0x0802 7ECA MOV

17、R6,#0xCA 1 C:0x0804 7D51 MOV R5,#0x51 1 C:0x0806 DDFE DJNZ R5,C:0806 2 C:0x0808 DEFA DJNZ R6,C:0804 2 C:0x080A DFF6 DJNZ R7,C:0802 2 C:0x080C 22 RET 2 通过上面的汇编语言程序段(0x0F15,0xCA202,0x5181 ),我们可以计算出该延时子程序的具体延时时间: Td(2811)202+2022+115+152+1+2 (163202+405)15+35 3333115+33 499978us499.978ms 通过与C语言相比较,我们可以

18、得出一个公式(对于C51,这个公式中的格式就跟上面的一样,数据类型必须是unsigned char,而且是三重循环,延时函数不带任何形参): Td2jk+3j+3i+3. 下面是调用了上面的延时函数的C51主函数,紧跟其后的汇编语言是利用keil软件翻译的一段汇编语言程序段。 11: void main(void) 12: 13: p10=1; 14: while(1) 15: 16: p10=p10; 17: delay(); 18: 机器周期数 C:0x0819 D290 SETB p10(0x90.0) 1 C:0x081B B290 CPL p10(0x90.0) 1 C:0x081D

19、 120800 LCALL delay(C:0800) 2 C:0x0820 80F9 SJMP C:081B 2 倘若我们需要一个带有形参的延时函数,方便在程序中根据不同的情形调用,延时时间不一致,我们的延时时间又如何计算呢?下面我们来看看这个延时函数,跟上面的一样,只是把延时函数加了个形参,我们用同样的方法来计算它的延时时间。 3: void delay(unsigned char i) 4: 5: unsigned char j,k; 6: for(;i0;i-) 7: for(j=202;j0;j-) 8: for(k=81;k0;k-); 9: 机器周期数 C:0x800 EF MO

20、V A,R7 C:0x0801 D3 SETB C C:0x0802 9400 SUBB A,#0x00 C:0x0804 400B JC C:0811 C:0x0806 7ECA MOV R6,#0xCA C:0x0808 7D51 MOV R5,#0x51 C:0x080A DDFE DJNZ R5,C:080A C:0x080C DEFA DJNZ R6,C:0808 C:0x080E 1F DEC R7 C:0x080F 80EF SJMP delay(C:0800) C:0x0811 22 RET 我们看看,R7的值是多少呢?在下面,主函数里面,赋值为0x0F,就是15。通过上面这段汇编程序段,我们用同样的方法来计算一下它的延时时间为(机器周期数请自己查阅书籍): Td220281+3202+815+3 32724+61415+3 3333815+3 500073us500.073ms 由此,我们可以得出一个公式为: Td2jk+3j+8i+3. 下面是调用了void delay(unsigned char i)延时函数的main()函数机器汇编代码。 11: void main(void) 12: 13: p10=1; 14: while(1) 15: 16:

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2