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就可以跳过写延时。实际运用还得看情况。
{:sleepy:}有没人知道。。 EEPROM是有写延迟的,每写一个字节后加上至少5ms以上的延时试试呢 楼上正解! 那我回去试试。 我试过延时1ms。不成功。我程序里没有延时超过1ms的。 slzm40 发表于 2012-7-30 16:49 static/image/common/back.gif
那我回去试试。 我试过延时1ms。不成功。我程序里没有延时超过1ms的。
1ms肯定不够,至少5-10ms
还有一种方法,在写之前先读,判断是否有ACK
如果正在写延时期间,eeprom不会返回ACK dlmaowf 发表于 2012-7-30 09:08 static/image/common/back.gif
EEPROM是有写延迟的,每写一个字节后加上至少5ms以上的延时试试呢
算是搞定了。。我加了5MS延时可以再次写入。 实际在测。用1MS失败。2MS就可以了。。
感谢LS几位的帮助
页:
[1]