发新帖我要提问
12
返回列表
打印

IIC口线操作变慢之后读数统一被乘2,是为什么?

[复制链接]
楼主: alphal
手机看帖
扫描二维码
随时随地手机跟帖
21
qjy_dali| | 2007-10-9 11:36 | 只看该作者 回帖奖励 |倒序浏览

有一点向楼主请教:

你说是写没问题,而读被乘2。那你是如何知道,写没有问题!我为什么不可以理解为,也许是你的写问题,写进去的数据被乘2,而读没问题。你是否把写入后的EEPROM放到通用的编程器上验证过???

使用特权

评论回复
22
alphal|  楼主 | 2007-10-9 12:51 | 只看该作者

用正常的程序(直接操作io口方式就正常了)读出没有问题

使用特权

评论回复
23
alphal|  楼主 | 2007-10-10 22:44 | 只看该作者

贴了程序就没人应了啊。。。

使用特权

评论回复
24
computer00| | 2007-10-10 23:03 | 只看该作者

那就可能是你定义clr和set的问题了

你是什么型号的单片机? 可能在| & 等操作时出了问题...

使用特权

评论回复
25
alphal|  楼主 | 2007-10-10 23:07 | 只看该作者

mcu是sst89e564,

同样的操作代码、方式操作其它外设就没有问题,只是在iic驱动这里出问题了。

使用特权

评论回复
26
computer00| | 2007-10-10 23:10 | 只看该作者

你要知道,I2C总线有点特殊,外设是可以拉低总线的,

因此你使用这样的操作,可能会改变另一根线的状态. 

使用特权

评论回复
27
alphal|  楼主 | 2007-10-10 23:17 | 只看该作者

可能会改变另一根线的状态?

可能会改变另一根线的状态?我这样操作P2的某脚,转化成汇编,也只是读出P2口值,计算,赋值,一次操作只赋值一次,哪个地方会改变另一根线状态?外设自己拉的?就算有那也是程序的正常流程内的事吧。

另外,我用的P2口,是否有点特殊?

使用特权

评论回复
28
computer00| | 2007-10-10 23:27 | 只看该作者

你是通过读引脚回来再操作的

本来另一个脚(你没有操作的那个脚)输出高电平的,但是这时被外设拉低了,你再读回来,然后又写出去,不就错了?

所以还是直接写引脚比较好,不要读回来再写出去. 51可以按引脚访问,有这么好
的功能,干啥不用呢...

使用特权

评论回复
29
alphal|  楼主 | 2007-10-10 23:32 | 只看该作者

。。。。

本来另一个脚(你没有操作的那个脚)输出高电平的,但是这时被外设拉低了,你再读回来,然后又写出去,不就错了?

本来输出高电平,这时被外设拉低,读回来的不也是低吗?

这样做是为了统一io操作的程序出口,也是便于将来向arm上移植。

使用特权

评论回复
30
computer00| | 2007-10-10 23:47 | 只看该作者

读回来是低,但是原本输出是高的,你现在却输出低了...

宏定义改成P20=0什么的并不影响将来向ARM移植. 将来那个宏肯定是要修改的了,
到时再改成那样的操作,并且很多ARM有SET和CLR寄存器,可以不用读回。

常用的ARM不像51那样,它是有方向控制的,所以你的程序中还是要修改,读和写时要
修改方向位.

使用特权

评论回复
31
alphal|  楼主 | 2007-10-10 23:56 | 只看该作者

。。。。。

读回来是低,但是原本输出是高的,你现在却输出低了...

好像有点启发。。。

但是,我测试结果是每次都会出现“左移”的情况,很稳定的“左移”了,如果是你说这种情况,位置和时机不会出现的这么“稳定”吧,而且也只移一次的。



很晚了,准备睡,谢谢圈圈同志的指点,晚安。。。。

使用特权

评论回复
32
computer00| | 2007-10-11 00:12 | 只看该作者

也许刚好是巧合,让你的结果乘了2...

你换成一些特殊的数试试? 例如全0,AA,55什么的.

总之是存在着隐患,而且让人想起来也觉得头晕...

使用特权

评论回复
33
古道热肠| | 2007-10-11 11:59 | 只看该作者

你这数据接收的函数有问题,多移了一次

   我以前用软件模拟SPI读数据时,也遇到类似现象,移位得放在数据接收后,快试试,我回头看你的结果,我要吃饭去了。

使用特权

评论回复
34
alphal|  楼主 | 2007-10-11 13:14 | 只看该作者

你这数据接收的函数有问题,多移了一次??

移位操作是在for循环体内的,在“数据接收”前或后都不会多一次出来,而且关键是我将io口操作方式改成直接赋值方式就没有问题了。

或者,你可以也用这种方式修改你的iic读写程序看看,会不会也多移一次?

使用特权

评论回复
35
ayb_ice| | 2007-10-11 13:44 | 只看该作者

肯定是宏有问题...

调试跟踪一下就知道了...

使用特权

评论回复
36
古道热肠| | 2007-10-11 16:17 | 只看该作者

看来得回家给你试试,才能找出根本原因了。

   这种故障属于隐性故障,比较难找,我想最好的办法是架仿真器单步跟踪,同步总线是可以低速运行的。

使用特权

评论回复
37
alphal|  楼主 | 2007-10-12 09:15 | 只看该作者

古大侠。。。

你用这种方式测试情况如何?

使用特权

评论回复
38
古道热肠| | 2007-10-12 09:23 | 只看该作者

找到你的驱动的一个BUG

   用我的硬件平台测试了一下,读取到的数据全部是0xFF,并没出现你说的乘2现象。
   用软仿真领导真调试了一下,驱动SCL和SDA线的高低变换都没问题,问题还是在接收数据字节的功能函数中。

看如下:
    for (__i = 0; __i < BITSOFBYTE; __i++)
    {
        __temp <<= 1;

        SET_SCLEPR_HIGH;
        I2CEPR_DELAY ;

        __temp1 = GET_SDAEPR_VALUE;
        __temp |= __temp1;

        SET_SCLEPR_LOW;
        I2CEPR_DELAY ;
    }

中的       __temp1 = GET_SDAEPR_VALUE;
假设SDA接P2.4,则如果SDA为1,返回值为0x10,如果SDA为0,返回值为0x00
再看下一句       __temp |= __temp1;

此时将返回结果不是放在最低位,而是放置到与SDA引脚对应的位置了。
我测试和结果,低4位永远是0,得到的结果是0xF0


候改后的代码如下,请比对:
        __temp1 = GET_SDAEPR_VALUE;
//        __temp |= __temp1;
        if(_temp1 != 0)
        {
            _temp |= 0x01;
        }

        SET_SCLEPR_LOW;

使用特权

评论回复
39
alphal|  楼主 | 2007-10-12 10:31 | 只看该作者

是啊,这里确实有个bug,谢谢古版主!!

确实是这个读数据的宏定义的问题,我用的sda是P2.1,所以就是乘2了,我一直还以为是时序的问题,呵呵,太感谢古版主了!!

使用特权

评论回复
40
古道热肠| | 2007-10-12 11:23 | 只看该作者

解决问题的方法很重要!

  凡事当透过现象看本质,用正确的方法去整,总归能解决问题的,所以我说“办法总比困难多”

使用特权

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

本版积分规则