打印

C的延时是怎样计算的呀??

[复制链接]
7088|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gdqinci|  楼主 | 2010-4-24 13:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
汇编的延时很理解,以晶振为时间基准算出机器周期然后让机器在那里空转,但是C呢?
C语言中的延时是怎样计算出延时的时间的呢??

//=================
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

相关帖子

沙发
machunshui| | 2010-4-24 13:39 | 只看该作者
1.拆看C编译后的汇编代码,算一下就OK了

2.最好直接用硬件定时器,现在的单片机,定时器资源都很多

使用特权

评论回复
板凳
jacky82512| | 2010-4-24 13:52 | 只看该作者
dingge

使用特权

评论回复
地板
linjing| | 2010-4-24 15:06 | 只看该作者
俺有个简单的办法,用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分频的,这个办法就不能用了

使用特权

评论回复
5
linjing| | 2010-4-24 15:07 | 只看该作者
楼下的谁方便贴两张图片,一张要设置晶振的,一张要右下角的定时器的,俺机器没有装Keil呢

使用特权

评论回复
6
jsjdhuangwei| | 2010-4-24 16:07 | 只看该作者
我也遇到这个困惑过,推荐你看一篇**
网址是:
http://hi.baidu.com/txz01/blog/item/868ad8d4aeea8309a08bb79c.html
你可能遇到网页上的图片显示不出来,这时你需要登陆百度空间,申请个号码大概要花费1分钟。
**是长了点,希望楼主能耐心看下去...

**的大体意思是说
前提是Keil编译器

就单单是
delay()
{
}
里面是空函数的话,这个需要花费4个时钟周期
下面是该空语句的的汇编
NAME DELAY
?PR?delay?DELAY      SEGMENT CODE
PUBLIC delay
RSEG ?PR?delay?DELAY
delay:
RET
END

如果delay()里面加语句的话
例如
#define uchar unsigned char
    void delay(void)
     { uchar i;
       for(i=100,i>0,i--);
      }

其汇编如下
NAME DELAY
?PR?delay?DELAY      SEGMENT CODE
PUBLIC delay
RSEG ?PR?delay?DELAY
delay:
     mov r7,#100    //1个时钟周期
     djnz r7,$          //2*100
   RET                  
   END
时间计算如下 4+1+2*100+1 答案需要206个时钟周期
作者的启动TR0中断和关闭TR0中断,这个耗时1个周期,最后一个1就是这个意思

不要管那些名字前加?,这个就是标示,编译器怕重名,就整出这个东西...看的是挺别扭的...

使用特权

评论回复
7
yunqian09| | 2010-4-24 16:52 | 只看该作者
keil软件仿真的吧,不过精度值得商榷

使用特权

评论回复
8
wuyuwu| | 2010-4-24 17:36 | 只看该作者
void delay(uint z)
{
    uint x,y;
    for(x=z;x>0;x--)
        for(y=110;y>0;y--);

使用特权

评论回复
9
电子空对穴| | 2010-4-24 19:01 | 只看该作者
C的延时,用汇编来算的,写一段C延时,在看看翻译成汇编计算时间

使用特权

评论回复
10
berg| | 2010-4-24 20:26 | 只看该作者
一般情况下,我是编译后看汇编代码计算时间。

使用特权

评论回复
11
lirunze| | 2010-4-24 20:31 | 只看该作者
外接个引脚,示波器测下波形就知道了!

使用特权

评论回复
12
hulan1985| | 2010-4-24 21:40 | 只看该作者
嗯,我也是拿示波器

使用特权

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

使用特权

评论回复
14
cauhorse| | 2010-4-25 00:43 | 只看该作者
实际上,用while(--i)比较好一些,具体原因看反汇编。

使用特权

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

使用特权

评论回复
16
5429| | 2010-4-25 11:08 | 只看该作者
C也跟晶振有关吧。。。

使用特权

评论回复
17
chenyelong| | 2010-4-25 12:44 | 只看该作者
用keil软件慢慢调试啊

使用特权

评论回复
18
一棵小草| | 2010-4-25 13:36 | 只看该作者
//=================
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)

使用特权

评论回复
19
f2bosi| | 2010-4-25 14:38 | 只看该作者
要看晶振大小啊。

使用特权

评论回复
20
f2bosi| | 2010-4-25 14:43 | 只看该作者
晶振12M:void delay()
                {
                   unsigned char a,b;
                   for(a=10;a>0;a--)
                     for(b=100;b>0;b--) ;      
                  }

使用特权

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

本版积分规则

36

主题

341

帖子

2

粉丝