搜索
bottom↓
回复: 7

求指点---有关延时函数形参的问题

[复制链接]

出0入8汤圆

发表于 2012-7-27 21:20:55 | 显示全部楼层 |阅读模式
本帖最后由 12tangyang12 于 2012-7-28 11:03 编辑

今天在调试的时候偶然间发现一个问题,延时函数 形参类型不一样 对延时的时间竟然也有影响的,下面先把程序打包上传[attach://]36903[/attach]。
下载附件慢的朋友 可以直接看, 我把源码 贴出来吧


#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char

void Delay_char(char del)
{
        while(del--);
}

void Delay_uchar(uchar del)
{
        while(del--);
}

void Delay_int(int del)
{
        while(del--);
}
void Delay_uint(uint del)
{
        while(del--);
}

void main(void)
{
        while(1)
        {
                Delay_char(100);        //需要0。66298ms
                Delay_uchar(100);        //需要0。66298ms
                Delay_int(100);                //需要0。993ms
                Delay_uint(100);        //需要0。993ms

        }
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入8汤圆

 楼主| 发表于 2012-7-27 21:31:32 | 显示全部楼层
程序中 我定义了 四个延时函数  ,四个函数唯一的区别就是 形参 的类型 不一样 , 分别是 char  unchar int 和 uint。 接着 在主函数中调用它们。 为了使 循环的次数一样 , 我们输入的形参 是100 , 这样都能满足 char  unchar  int uint 数据类型。 在调试前 设置 晶振 11.0592Mhz    通过设置断点 调试后 发现  当 延时函数 的 形参类型是 char 和 uchar 时  竟然和  in  uint  延时的时间不一样。 怎么会这样呢? 不得其解  , 希望 各路大大  指点指点

出0入0汤圆

发表于 2012-7-27 22:34:02 | 显示全部楼层
那是因为C转为汇编后,代码都不一样了,建议楼主看看编译后的汇编代码。
函数传递参数时,一个字节的参数和两个字节的参数肯定是不一样的。
做加法时,8位的加法和16位的加法是不一样的。

出0入8汤圆

 楼主| 发表于 2012-7-28 08:14:10 | 显示全部楼层
lcw_swust 发表于 2012-7-27 22:34
那是因为C转为汇编后,代码都不一样了,建议楼主看看编译后的汇编代码。
函数传递参数时,一个字节的参数和 ...

thank  you

出0入8汤圆

 楼主| 发表于 2012-7-28 13:07:45 | 显示全部楼层
今天仔细调试了一下,又发现了个新的问题。 先把源程序 贴出来。
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char

void Delay_char(char del)
{
        while(del--);
}

void Delay_uchar(uchar del)
{
        while(del--);
}

void Delay_int(int del)
{
        while(del--);
}
void Delay_uint(uint del)
{
        while(del--);
}

void main(void)
{
        while(1)
        {

                Delay_char(10);                        //75.954 us
                Delay_char(50);                        //336.37us
                Delay_char(100);                //661.89us

                Delay_uchar(10);                //75.964us
                Delay_uchar(50);                //336.37us
                Delay_uchar(100);                //661.89us

                Delay_int(10);                        //112.85us
                Delay_int(50);                        //503.47us
                Delay_int(100);                        //991.75us

                Delay_uint(10);                        //112.85us
                Delay_uint(50);                        //503.47us               
                Delay_uint(100);                //991.75us

                P0=0x00;
        }
}
在程序中,就拿 Delay_uchar(uchar del);  这个函数举例吧,
当形参是 10的时候 整个函数执行的时间是 75.964us  
当形参是 50 的时候  按照倍数关系 执行的时间 应该是 75.964 X 5 = 379.82us  可是通过调试 测出执行的时间是 336.37us -   将近比预计的时间快了 43.45 us   这个误差 在精确延时中不容忽视了已经。
我们再看看 当 100的时候 , 100的时候执行整个函数 需要 661.89us  而 我们通过倍数关系应该是 75.964us的10倍 =759.64 , 和实际延时 相差了 97.75us  这次 误差更大了。
这个是什么原因造成的呢? 这个难道延时的时间不能通过 执行一次需要的时间乘以执行的次数 算吗??
程序 我也打包上传了。虽然是 us 级别的误差。但是在 DS18B20 这样对时序要求严格的元器件 这样的误差足以导致不能产生正确的时序了。。。。
  哪位 大大 能够 指点 指点?鄙人真想不明白了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-7-28 13:35:10 | 显示全部楼层
从 汇编 过度到 C 就不会这样的疑问。
通过keil编译后看汇编代码,对照51指令表,将下面这个延时函数的延时时间公式推导出来就明白:虽然形参del越大 延时时间就越长,但两者并不是正比关系
void Delay_uchar(uchar del)
{
        while(del--);
}

觉得麻烦的话,建议直接用“单片机小精灵”(论坛有,自己搜搜),输入参数 直接生产 精确的延时函数

出0入0汤圆

发表于 2012-7-28 20:16:06 | 显示全部楼层
第一个问题显然8位加法和16位加法运算速度不一样,
第二个问题你可以看看这个
****************C语*******************/
void delay(uint delaytime)
{
       while(delaytime--);
}

/****************汇编******************/

C:0x0840        EF          MOV             A,R7                                        //1个机器周期
C:0x0841        1F          DEC              R7                                           //1个机器周期
C:0x0842        AC06      MOV             R4,0x06                                   //1个机器周期
C:0x0844        7001      JNZ               C:0847                                    //2个机器周期
C:0x0846        1E          DEC              R6                                          //1个机器周期
C:0x0847        4C          ORL              A,R4                                       //1个机器周期
C:0x0848        70F6       JNZ              delay(C:0x0840)                       //2个机器周期
C:0x084A        22          RET                                                           //2个机器周期
/**************************************/
运行时间(周期):
8*[(R7+1)+256*R6]+1*R6+2
平均时间约为8个机器周期
占用资源:ACC,R4,R6,R7

出0入0汤圆

发表于 2012-7-28 20:18:31 | 显示全部楼层
/****************C语*******************/
void delay(uint delaytime)
{
       while(delaytime--);
}

/****************汇编******************/

C:0x0840        EF          MOV             A,R7                                        //1个机器周期
C:0x0841        1F          DEC              R7                                           //1个机器周期
C:0x0842        AC06      MOV             R4,0x06                                   //1个机器周期
C:0x0844        7001      JNZ               C:0847                                    //2个机器周期
C:0x0846        1E          DEC              R6                                          //1个机器周期
C:0x0847        4C          ORL              A,R4                                       //1个机器周期
C:0x0848        70F6       JNZ              delay(C:0x0840)                       //2个机器周期
C:0x084A        22          RET                                                           //2个机器周期
/**************************************/
运行时间(周期):
8*[(R7+1)+256*R6]+1*R6+2
平均时间约为8个机器周期
占用资源:ACC,R4,R6,R7


/**************************************/



/****************C语*******************/
void delay(uint delaytime)
{
       while(--delaytime);
}

/****************汇编******************/

C:0x0840        EF          MOV             A,R7                                       //1个机器周期
C:0x0841        1F          DEC              R7                                          //1个机器周期
C:0x0842        7001      JNZ               C:0845                                   //2个机器周期
C:0x0844        1E          DEC              R6                                         //1个机器周期
C:0x0845        14          DEC              A                                          //1个机器周期
C:0x0846        4E          ORL              A,R6                                      //1个机器周期
C:0x0847        70F7       JNZ              delay(C:0x0840)                      //2个机器周期
C:0x084A        22          RET                                                          //2个机器周期
/**************************************/
运行时间(周期):
6*(R7+256*R6)+1*R6+2
平均时间约为6个机器周期
占用资源:ACC,R6,R7


/**************************************/




/****************C语*******************/
void delay(uint delaytime)
{
       for(;delaytime==0;--delaytime);
}

/****************汇编******************/

C:0x0840        EF          MOV             A,R7                                        //1个机器周期
C:0x0841        4E          ORL              A,R7                                        //1个机器周期
C:0x0842        7007      JNZ               C:084B                                    //2个机器周期
C:0x0844        EF          MOV             A,R7                                       //1个机器周期
C:0x0845        1F          DEC              R7                                          //1个机器周期
C:0x0846        70F8      JNZ               delay(C:0x0840)                       //2个机器周期
C:0x0848        1E          DEC              R6                                          //1个机器周期
C:0x0849        80F5      SJMP             delay(C:0x0840)                       //2个机器周期
C:0x084B        22          RET                                                           //2个机器周期
/**************************************/
运行时间(周期):
4+8*(R7+256*R6)+3*R6+2
平均时间约为8个机器周期
占用资源:ACC,R6,R7


/**************************************/
void delay(uint delaytime)
{
       for(;delaytime==0;delaytime--);
}
同上一样 for(;delaytime==0;--delaytime);。
/**************************************/
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 16:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表