求指点---有关延时函数形参的问题
本帖最后由 12tangyang12 于 2012-7-28 11:03 编辑今天在调试的时候偶然间发现一个问题,延时函数 形参类型不一样 对延时的时间竟然也有影响的,下面先把程序打包上传36903。
下载附件慢的朋友 可以直接看, 我把源码 贴出来吧
#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
}
} 程序中 我定义了 四个延时函数,四个函数唯一的区别就是 形参 的类型 不一样 , 分别是 charunchar int 和 uint。 接着 在主函数中调用它们。 为了使 循环的次数一样 , 我们输入的形参 是100 , 这样都能满足 charuncharint uint 数据类型。 在调试前 设置 晶振 11.0592Mhz 通过设置断点 调试后 发现当 延时函数 的 形参类型是 char 和 uchar 时竟然和inuint延时的时间不一样。 怎么会这样呢? 不得其解, 希望 各路大大指点指点 那是因为C转为汇编后,代码都不一样了,建议楼主看看编译后的汇编代码。
函数传递参数时,一个字节的参数和两个字节的参数肯定是不一样的。
做加法时,8位的加法和16位的加法是不一样的。
lcw_swust 发表于 2012-7-27 22:34 static/image/common/back.gif
那是因为C转为汇编后,代码都不一样了,建议楼主看看编译后的汇编代码。
函数传递参数时,一个字节的参数和 ...
thankyou
今天仔细调试了一下,又发现了个新的问题。 先把源程序 贴出来。
#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 这样对时序要求严格的元器件 这样的误差足以导致不能产生正确的时序了。。。。
哪位 大大 能够 指点 指点?鄙人真想不明白了 从 汇编 过度到 C 就不会这样的疑问。
通过keil编译后看汇编代码,对照51指令表,将下面这个延时函数的延时时间公式推导出来就明白:虽然形参del越大 延时时间就越长,但两者并不是正比关系
void Delay_uchar(uchar del)
{
while(del--);
}
觉得麻烦的话,建议直接用“单片机小精灵”(论坛有,自己搜搜),输入参数 直接生产 精确的延时函数
第一个问题显然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 /****************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);。
/**************************************/
页:
[1]