打印

延时是怎样计算

[复制链接]
3363|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dingy|  楼主 | 2011-8-2 19:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
汇编的延时很理解,以晶振为时间基准算出机器周期然后让机器在那里空转,但是C呢?
沙发
dingy|  楼主 | 2011-8-2 20:00 | 只看该作者
//=================
void delay(uint k)
{
uint i,j;
for (i=0;i<k;i++)
  {
    for (j=0;j<121;j++)
     {;}
  }
}
//上面这个延时书中说是延时1ms

那么如果硬件不变的话下面这个是延时多少呢???

//-------------------------------------------------------------------
void delay_1ms(void)
{
uint k;
for(k=0;k<121;k++);   //很奇怪??为什么这里for语句后面没有了循环体了呢??
}
//难道这个也是1ms

使用特权

评论回复
板凳
renyaq| | 2011-8-2 20:05 | 只看该作者
拆看C编译后的汇编代码,算一下就OK了

使用特权

评论回复
地板
zwll| | 2011-8-2 20:07 | 只看该作者
最好直接用硬件定时器,现在的单片机,定时器资源都很多

使用特权

评论回复
5
llljh| | 2011-8-2 20:09 | 只看该作者
俺有个简单的办法,用Keil的软仿。

一般这样用:
void delay( uint16_t ms ){ // 注意这个参数是ms,也就是毫秒
  uint8_t i;
  while( ms-- ){
    // 注意这个i =100,后面说明这个值怎么确定
    for( i=100; i!=0; --i ){;} // 这行要不要{}都行,但分号不能少
  }
}

用的时候这样用:
  delay(200); // 这就是延时200ms
  delay(20); // 这个延时是20ms
这样定义是不是可读性好一点?!


软件仿真前配置好晶振的数值!!!
主程序这样写
void main( void ){
  low_level_init(); // 低层初始化,最好打开需要的中断,如按键扫描,LED显示刷新等
  delay(1000);   // 在这行前定义一个断点,运行到这清一下软件仿真的计时器,在Keil窗口右下角
  。。。
  while(1);
}

Keil窗口右下角有个软件计时器,再次强调用前一定要设置好晶振的数值
运行delay(1000)前,Reset Watch1, 然后单步运行delay(1000),再看一下Watch1的数值,算一下结果差多少,
修改一下delay程序中的i=100一句,再重新编译一下,重新来过

这个办法的好处是可以把中断的时间影响一起加进去,比单纯的手工算周期更准一些,也不容易出错,但是:

一定要注意CPU的型号,一般只对12分频的标准8051核的好用,比如W79E4051是4分频的,这个办法就不能用了

使用特权

评论回复
6
supernan| | 2011-8-2 20:12 | 只看该作者
keil软件仿真的吧,不过精度值得商榷

使用特权

评论回复
7
juventus9554| | 2011-8-2 20:14 | 只看该作者
void delay(uint z)
{
    uint x,y;
    for(x=z;x>0;x--)
        for(y=110;y>0;y--);

使用特权

评论回复
8
pengf| | 2011-8-3 09:42 | 只看该作者
C的延时,用汇编来算的,写一段C延时,在看看翻译成汇编计算时间

使用特权

评论回复
9
supernan| | 2011-8-3 09:46 | 只看该作者
一般情况下,我是编译后看汇编代码计算时间。

使用特权

评论回复
10
zwll| | 2011-8-3 09:49 | 只看该作者
外接个引脚,示波器测下波形就知道了!

使用特权

评论回复
11
司徒老鹰| | 2011-8-3 10:02 | 只看该作者
嗯,我也是拿示波器

使用特权

评论回复
12
pengf| | 2011-8-3 10:12 | 只看该作者
这两段显然不一样嘛,第一段是嵌套循环,延时更长点。后面那个没有循环体也没什么,执行判断和自加不就行了~!

使用特权

评论回复
13
chuxh| | 2011-8-3 10:17 | 只看该作者
实际上,用while(--i)比较好一些,具体原因看反汇编。

使用特权

评论回复
14
llljh| | 2011-8-3 10:28 | 只看该作者
时序严格的时候建议用for循环进行延时,精确,可控。
for(i=x;i>0;i--);
延时时间为(2*i+1 ) us
ms级的延时建议采用一个带形参的延时函数,然后用keil的软仿真进行调试即可。
当然嵌入汇编语言进行延时是最好的一种形式

使用特权

评论回复
15
栩栩如生| | 2011-8-3 10:51 | 只看该作者
//=================
void delay(uint k)
{
       uint i,j;
       for (i=0;i<k;i++)
      {
             for (j=0;j<121;j++)
             {;}
      }
}
//上面这个延时书中说是延时1ms

可以简写成这样:
void delay(uint k)                    //这里不是延时1ms,而是毫秒级延时,至于延时多少毫秒,要看K。
{                                             //这个延时可能是根据Keil的软仿真得来的。
       uint i,j;                             //毫秒级别是怎么算来的呢?我猜想这里晶振可能是11.0592MHZ
       for (i=0;i<k;i++)               //根据51的12分频,指令周期大约为0.92us。
             for (j=0;j<121;j++);   //如果k=1,j=1。那么,两个for之间转换成汇编
}                                             //就会有两个INC,两个DNJZ等。所以,两个for可能有9个指令周期。
                               //如果K=1,那么:循环的时间=121*9*0.92=1000us=1ms

void delay_1ms(void)
{
       uint k;
       for(k=0;k<121;k++); //很奇怪??为什么这里for语句后面没有了循环体了呢??
}                                    //不用奇怪,你可以理解成:作者想怎么写就怎么写,你管不了。
                                    //程序是作者思路、思想 的体现。各有各的风格,以后你爱怎么写人家也不管你
              //一个for,大约有4个指令周期。所以循环的时间=121*4*0.92=450us(不是1ms)

使用特权

评论回复
16
supernan| | 2011-8-3 10:56 | 只看该作者
晶振12M:void delay()
                {
                   unsigned char a,b;
                   for(a=10;a>0;a--)
                     for(b=100;b>0;b--) ;      
                  }

使用特权

评论回复
17
jack_shine| | 2011-8-3 11:01 | 只看该作者
可以空转,也可以在这段时间干些别的事情

使用特权

评论回复
18
dingy|  楼主 | 2011-8-3 11:01 | 只看该作者
呵呵,真热闹,先结贴了,多谢大家

使用特权

评论回复
19
rulu| | 2011-8-5 13:59 | 只看该作者
都拿示波器呀

使用特权

评论回复
20
rulu| | 2011-8-5 13:59 | 只看该作者
:lol

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

745

主题

10920

帖子

6

粉丝