简简单单的一个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条回答
olive2003
1楼-- · 2019-07-16 12:16
本帖最后由 olive2003 于 2014-6-24 22:05 编辑
ying-teng 发表于 2014-6-24 06:29
你是不是在程序里,用到CY位了

CY位么,确实用到了ACC和左移了
        ACC=ACC<<1;
        ACC0=SDA;

这个对delay有什么影响么?
————————————————————————————————————
刚才试了下放弃使用ACC的方法读取数据,发现delay函数怎么改都没问题了。膜拜大神,请教原因。

olive2003
2楼-- · 2019-07-16 14:16
阿信509 发表于 2014-6-24 09:22
你的语句肯定没问题,
看看延时对不,I2C对时序要求挺严的。

嗯,很严格这点我知道,像我试验的24C02就需要5us的处理时间,而结束和起始之间估计没1ms反应不过来。
正是因为delay稍有改变,进入delay函数后马上就跳出来了

jylfyzyz
3楼-- · 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--)的习惯。




olive2003
4楼-- · 2019-07-16 23:08
jylfyzyz 发表于 2014-6-25 17:25
最好不要随便用ACC,看过一些说for(i=0;i0;i--)因为使用了ACC导致结果不同,最好新建一个变量。这是那位博 ...

嗯,了解了。之前我也曾经出现过用for(i=0;i<8;i++)出现错误的情况。然后后面两三天天尝试用for(i=8;i>0;i--),不过因为习惯问题,偶尔还是写错,就放弃了。看来今天要重新试着改这个习惯了。
问题解决,这帖子就让他沉了吧。
最后感谢提供解答,谢谢。

olive2003
5楼-- · 2019-07-17 00:46
 精彩回答 2  元偷偷看……
ntmusic
6楼-- · 2019-07-17 04:23
先不要沉,我想说一下我个人看法。我观察过过很多人写程序,对于从引脚获取串行数据的写法中,不知道从哪里来的习惯,会用ACC寄存器去获取。先不说这么用会给程序带来隐患,就从编程的角度出发,既然使用了C语言,能脱离硬件底层的写法就尽量避免不要用底层寄存器,一方面程序方便移植,另一方面也不会与编译器编译产生冲突。有人还说使用ACC提高处理器效率,我只想说,你应该先去试试,不要人云亦云。

一周热门 更多>