slzm40 发表于 2012-7-29 21:07:56

IIC写单字节成功,用单字节命令分别写入三个字节就失败...

本帖最后由 slzm40 于 2012-7-30 20:50 编辑

    做了个IIC的程序,向固定地址写入一个byte写入正确,用页写入三个byte也是正确的。但用固定地址写入一个byte的方法,一个个写入就不行了。问题在哪里。。?
void IICdely(int del)//
{
        while(del--)
        {;}
}

void IICinit()//IIC Init
{
        SDA_SET;
        IICdely(10);
        SCL_SET;
        IICdely(10);
}

void IICstart()//IIC启动信号
{
        SDA_SET;
        IICdely(10);
        SCL_SET;
        IICdely(10);;
        SDA_CLR;
        IICdely(10);
        SCL_CLR;
}
void IICstop()//IIC停止信号
{
        SDA_CLR;
        IICdely(10);
        SCL_SET;
        IICdely(10);;
        SDA_SET;
        IICdely(10);
}
void IICACK() //应答信号,从控件应答信号
{
        IICdely(10);
        SCL_SET;
        IICdely(10);
        while(SDA_GEDATA==1);//时钟线低电平时,数据线被拉成低电平,从器件应答收到
        IICdely(10);
        SCL_CLR;
        IICdely(10);       
}
//主机接收多byte数据时应答信号
void Ack_IIC(bit a)//主器件应答信号   0非应答,1 应答
{
        if(a==0) SDA_CLR;            /*在此发出应答或非应答信号 */
        else SDA_SET;
        IICdely(10);      
        SCL_SET;
        IICdely(10);                  /*时钟低电平周期大于4μs*/
        SCL_CLR;                     /*清时钟线,钳住I2C总线以便继续接收*/
        IICdely(10);          
}

void IICbyteWrite(uchar eprom_data)//发数据到从器件
{
        uchar i,temp;
        temp=eprom_data;
        for(i=0;i<8;i++)//数据从高位开始传
        {
                if((temp&0x80)==0x80) SDA_SET; //判断发送位,送数据到数据线上
                else SDA_CLR;
                IICdely(10);
                SCL_SET;
                IICdely(10);
                SCL_CLR;
                temp=temp<<1;
        }
        IICdely(10);

}
uchar IICbyteRead()//从从器件读数据
{
uchar i,byt;
SDA_SET;//释放总线
for(i=0;i<8;i++)//数据从高位开始接收
        {
        byt=byt<<1;
        SCL_SET;
        IICdely(10);
        if(SDA_GEDATA==1) byt|=0x01;
        else byt|=0x00;
        IICdely(10);
        SCL_CLR;
        IICdely(10);
        }
return(byt);
}

//向固定地址写入一个 byte。
void IICWriteToOnebyte(uchar address,uchar bytedata)//向一个地址写入一个数据
{
        IICstart();
        IICbyteWrite(ADD_24C02&0xfe);//写操作
        IICACK();
        IICbyteWrite(address);//送写入的地址
        IICACK();
        IICbyteWrite(bytedata);//写数据
        IICACK();
        IICstop();
}       
///***************************************************************************
//向24c02中写多个字节
//data:指向要写入数据数组的指针
//StartAddress:24c02中要写入数据的首地址
// bytes:写入的字节数,须小于16
//***************************************************************************/
void Write_Date(uchar StartAddress,uchar *pdatebuf,uchar bytes)
{
        uchar i;
        IICstart();
        IICbyteWrite(ADD_24C02&0xfe);//写操作
        IICACK();
        IICbyteWrite(StartAddress);//送写入起始地址
        IICACK();
       
        for(i=0;i<bytes;i++)
                {
                IICbyteWrite(*pdatebuf);//写数据
                IICACK();
                pdatebuf++;
                }
        IICstop();
}


如我定义个数组
   uchar VAL;
然后 用
      IICWriteToOnebyte(0x00,VAL);
这种单写一个byte是成功的。

然后再试用
         Write_Date(0x00,VAL,3);
这个连续写入三个byte也是成功的
最后这个用
   IICWriteToOnebyte(0x00,VAL);
       IICWriteToOnebyte(0x01,VAL);
最后一个程序就死在上面了。。。不知道什么原因。。


   
解决办法,实测 在两个BYT连续写入加上足够的延时。 我用的是2MS就可以跳过写延时。实际运用还得看情况。

slzm40 发表于 2012-7-29 23:37:28

{:sleepy:}有没人知道。。

dlmaowf 发表于 2012-7-30 09:08:19

EEPROM是有写延迟的,每写一个字节后加上至少5ms以上的延时试试呢

cb1470 发表于 2012-7-30 16:12:05

楼上正解!

slzm40 发表于 2012-7-30 16:49:39

那我回去试试。 我试过延时1ms。不成功。我程序里没有延时超过1ms的。

sf49ers 发表于 2012-7-30 17:05:11

slzm40 发表于 2012-7-30 16:49 static/image/common/back.gif
那我回去试试。 我试过延时1ms。不成功。我程序里没有延时超过1ms的。

1ms肯定不够,至少5-10ms
还有一种方法,在写之前先读,判断是否有ACK
如果正在写延时期间,eeprom不会返回ACK

slzm40 发表于 2012-7-30 20:49:19

dlmaowf 发表于 2012-7-30 09:08 static/image/common/back.gif
EEPROM是有写延迟的,每写一个字节后加上至少5ms以上的延时试试呢

算是搞定了。。我加了5MS延时可以再次写入。 实际在测。用1MS失败。2MS就可以了。。

感谢LS几位的帮助
页: [1]
查看完整版本: IIC写单字节成功,用单字节命令分别写入三个字节就失败...