首 页文档资料下载资料维修视频包年699元
请登录  |  免费注册
当前位置:精通维修下载 > 文档资料 > 家电技术 > 单元电路介绍 > 其它电路
C语言精确延时计算实例!
来源:本站整理  作者:佚名  2011-12-16 06:35:02



设晶振频率为12M,单片机AT89C51。则知一个机器周期为1us。现有延时函数如下:
     3: void delay(void)
     4: {
     5:         unsigned char i,j,k;
     6:         for(i=15;i>0;i--)
     7:         for(j=202;j>0;j--)
     8:         for(k=81;k>0;k--);
     9: }
         以上就是利用C51语言编写的一个延时函数,下面这段代码则是利用keil软件翻译的一段汇编语言程序段,大家可以对照着看。  
                                                                         机器周期数
C:0x0800     7F0F       MOV       R7,#0x0F                 1
C:0x0802     7ECA     MOV       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
         通过上面的汇编语言程序段(0x0F=15,0xCA=202,0x51=81 ),我们可以计算出该延时子程序的具体延时时间:
Td=[(2×81+1)×202+202×2+1]×15+15×2+1+2
     =(163×202+405)×15+35
     =33331×15+33
     =499978us=499.978ms
         通过与C语言相比较,我们可以得出一个公式(对于C51,这个公式中的格式就跟上面的一样,数据类型必须是unsigned char,而且是三重循环,延时函数不带任何形参):
     Td=[2×j×k+3×j+3]×i+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     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(;i>0;i--)
     7:         for(j=202;j>0;j--)
     8:         for(k=81;k>0;k--);
     9: }
                                                                           机器周期数
C:0x800       EF           MOV       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。通过上面这段汇编程序段,我们用同样的方法来计算一下它的延时时间为(机器周期数请自己查阅书籍):
Td=[2×202×81+3×202+8]×15+3
     =[32724+614]×15+3
     =33338×15+3
     =500073us=500.073ms
由此,我们可以得出一个公式为:
     Td=[2×j×k+3×j+8]×i+3.....................②
下面是调用了void delay(unsigned char i)延时函数的main()函数机器汇编代码。
     11: void main(void)
     12: {
     13:         p10=1;
     14:         while(1)
     15:         {
     16:                 p10=~p10;
     17:                 delay(15);
     18:         }

C:0x081E     D290     SETB     p10(0x90.0)
C:0x0820     B290     CPL       p10(0x90.0)
C:0x0822     7F0F     MOV       R7,#0x0F
C:0x0824     120800   LCALL     delay(C:0800)
C:0x0827     80F7     SJMP     C:0820

         两种不同的写法,公式①、②造成的时间误差有1个毫秒多,在许多要求精确延时的地方,我们就不得不注意这1个毫秒会造成什么样的后果。大家有兴趣,可以用同样的方式去验证和计算unsigned int型以及使用while语句和for语句组合起来的精确延时时间的计算。注意,其中for语句里面的循环控制语句,i>0,j>0,k>0,如果你把他们改写成i>=0,j>=0,k>=0,效果就不一样了,延时时间变的更长。

关键词:

文章评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分)
Copyright © 2007-2017 down.gzweix.Com. All Rights Reserved .
页面执行时间:126,238.30000 毫秒