简简单单的一个delay函数,也出现了意想不到的问题,求助

2019-07-15 19:20发布

RT,在写一个关于I2C的函数,出现问题了,而问题不在别的上,而在delay上,让我百思不得其解。
void delay() //延时
{
char x;
for(x=0;x<10;x++);
}
用以上的程序,运行出现问题,但当我改成for函数改成

for(x=1;x<11;x++);
问题就没了,这是怎么回事啊

另外之前也遇到过在别的程序中
for(i=0;i<8;i++);
不行,改成
for(i=1;i<9;i++);
或者倒过来都可以


如果是函数初始化的话我试过全部不初始化,也试过全部初始化都不行
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
13条回答
jylfyzyz
2019-07-16 20:12
本帖最后由 jylfyzyz 于 2014-6-25 17:42 编辑

最好不要随便用ACC,看过一些说for(i=0;i<10;i++)和for(i=10;i>0;i--)因为使用了ACC导致结果不同,最好新建一个变量。这是那位博主写的ACC对for循环的影响


认真对比这两个代码,可能会觉得没区别,而且这两个代码都可以通过编译(加上reg52.h和一些宏定义)。我也是一直认为for()这里边没有错误,结果。。。试着修改时钟信号,增加延时之类的,调了好久还是错,严重打击我的自信心。这两个代码的区别就只有for(i=0;i<8;i++)和for(i=8;i>0;i--)了。学过c语言的人都知道,这两个句子都是实现一个8次的循环,功能一模一样。怎么会因为这个句子的区别就导致单片机控制的错误呢?神奇!

    接着我试着把错误程序中的ACC改为51芯片的寄存器B,烧录进单片机,程序运行成功,跟“for(i=8;i>0;i--),ACC版”一样,lcd在很嚣张地显示着正确的时间( for(i=0;i<8;i++),ACC版lcd的时间显示为0)。

这样就知道原因了,使用for(i=0;i<8;i++)的运算中可能有累加器ACC参与了,导致修改了ACC的值,使写入的命令出现错误。但为什么for(i=8;i>0;i--)就没有ACC的参与呢?一个大大的问号。基于我调试了一个星期的程序,皆因为这一个神奇的错误,我实在不甘心,决定研究到底。于是,分别查看了这三个程序代码用 keil4 编译后得到的 汇编代码。

对比后,可以发现,出错的原因是for(i=0;i<8;i++)ACC版中,用ACC接收了实参(存储的为要写入的指令),然后在 for 循环前要给变量  “ i  "   赋值时,要用到ACC清零,再把ACC中的零赋给 R7 ("i"的值存储在R7)。这样的话,原来存储在ACC中的写入指令就被清零,自然会导致控制出现错误,最终没法读取ds1302芯片的时间,故显示为零。

    而在for(i=8;i>0;i--)ACC版中,也用ACC接收了实参的值,但在 for 循环前,给变量“ i ” 赋值时,赋值为8,不需要用到ACC,所以ACC一直是存储着实参中的指令,没有被清零,所以能够顺利地向ds1302发送指令,从而能够读取到时间。

   总结:

     因为用for(i=0;i<n;i++)类的指令会重复使用ACC而可能导致出错,而且,即使其它程序可能不会有这种用ACC来接收实参值的情况,但前者比for(i=n;i>0;i--)类的指令多了 CLR A  和 INC R7 两条指令,CJNE 指令又比较DJNZ指令多了一个字节的程序代码存储空间,在频率为12M的51单片机上体现为执行同样功能的程序,要多用2us,代码空间花多一字节。所以前者是毫无优势的,以后应养成用

for(i=n;i>0;i--)的习惯。




一周热门 更多>