lixin91985 发表于 2014-11-1 17:05:29

实在搞不定了,求助高手 指出CC530读取24C02中的BUG

本帖最后由 lixin91985 于 2014-11-1 17:06 编辑

本来是认为是一个很简单的事情。

IO模拟IIC,使用了不知道多少次。花了整整两天时间,参考了不知道多少个以前成功的程序。。。。。还是没有成功

硬件 外部上拉,有试过1k,4,7k 10k。

IC没有问题,因为焊接到STM32上面测试过。。
写入之间的延时有调整过。
测试过多个PCB。排除焊接问题。
用示波器观察,IO有电平输出。逻辑眼观是正确的。

现象:能读出来,,先这么认为吧。


10个数据,第一个能正常写入,每隔两个能正常一个。

#define SCL_H         (P1_3=1)
#define SCL_L          (P1_3=0)
   
#define SDA_H         (P1_2=1)
#define SDA_L          (P1_2=0)

//#define SCL_read      (P1_3)
#define SDA_Out   (P1DIR|=(1<<2))
#define SDA_In   (P1DIR&=~(1<<2))
#define SDA_read      (P1_2)

、、----------------------------------------------------下面是程序--------------------------------------------------------------
void EEPROM_HAL_Init(void)
{
// P0DIR|=((1<<6)|(1<<7));
//P1_0=0;P0_6=0;P0_7=0;
//-------------------------------------
SDA_H;SCL_H;
P1DIR|=((1<<3)|(1<<2));// CLK pin is output
// P1INP&=~((1<<3)|(1<<2));
P1SEL&=~((1<<3)|(1<<2));

EE_Delay_ms(100);
I2C_Test();
}


void I2C_delay(void)
{       
   uint8 i=20; //这里可以优化速度        ,经测试最低到5还能写入
   while(i)
   {
   i--;
   }
}

void delayus(uint8 time)
{       
   while(time)
   {
   time--;//nop();
   }
}
bool I2C_Start(void)
{
   
    SDA_Out;
   
    SDA_H;
    SCL_H;
    delayus(5);
    SDA_L;
    delayus(5);
    SCL_L;    //拉低
    delayus(5);   return TRUE;
}

void I2C_Stop(void)
{
    SDA_Out;
   
    SDA_L;
    SCL_H;
    delayus(5);
    SDA_H;
    delayus(5);   
    SCL_L;
    delayus(250);delayus(50);
}

void I2C_Ack(void)
{       
   SCL_L;I2C_delay();
   SDA_Out;SDA_L;
   I2C_delay();
   SCL_H;
   I2C_delay();
   SCL_L;
   I2C_delay();
}

void I2C_NoAck(void)
{       
    SDA_Out;
   
    SCL_H;
    SDA_H;
    delayus(5);
    SCL_L;
    SDA_L;
    delayus(5);
}

bool I2C_WaitAck(void)        //返回为:=1有ACK,=0无ACK
{uint8 cnt=255;
//SCL_L;
//I2C_delay();
SDA_Out;
SDA_H;       
SCL_H;
   I2C_delay();
SDA_In;
//I2C_delay();
while(SDA_read&&cnt) cnt--;
if(cnt==0)
   { SCL_L;//I2C_delay();
         return FALSE;
   }
SCL_L;//SDA_Out;
return TRUE;
}

void I2C_SendByte(uint8 SendByte) //数据从高位到低位//
{
    uint8 i,temp;
       
    SDA_Out;
    for(i = 0;i < 8;i ++)
    {
      temp = SendByte & 0x80;
      if(temp)
            SDA_H;
      else
            SDA_L;
      SCL_H;
      delayus(5);
      SCL_L;
      delayus(5);
      SendByte <<= 1;
    }
}

uint8 I2C_ReceiveByte(void)//数据从高位到低位//
{
    uint8 i,temp;
       
    SDA_In;
    for(i = 0;i < 8;i ++)
    {
      temp <<= 1;
      SCL_H;
      delayus(5);
      if(SDA_read)
      {
            temp |= 1;
      }
      SCL_L;
      delayus(5);
    }
    return temp;
}

void EE_Delay_ms(uint16 Count)
{uint16 i;
   uint8 J;
for(;Count>0;Count--)
        {for(i=0;i<0x4fff;i++) J++;
   }
}


//写入1字节数据       待写入数据    待写入地址       器件类型(24c16或SD2403)
bool I2C_WriteByte(uint8 SendByte, uint16 WriteAddress, uint8 DeviceAddress)
{               
    I2C_Start();
    I2C_SendByte(0xa0);//((WriteAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE);//设置高起始地址+器件地址
    I2C_WaitAck();
    I2C_SendByte(WriteAddress);//& 0x00FF));   //设置低起始地址      
    I2C_WaitAck();       
    I2C_SendByte(SendByte);
    I2C_WaitAck();   
    I2C_Stop();
        //注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
    EE_Delay_ms(10);///EE_Delay_ms(1000);
    return TRUE;
}

//读出1串数据         存放读出数据待读出长度      待读出地址       器件类型(24c16或SD2403)       
bool I2C_ReadByte(uint8* pBuffer,   uint8 length,   uint16 ReadAddress)
{
while(length--)
{
   *pBuffer=I2C_ReadChar(ReadAddress);
   pBuffer++;ReadAddress++;
   EE_Delay_ms(5);
}
return TRUE;

}


uint8 I2C_ReadChar(uint8 addr)
{
uint8 temp;

I2C_Start();
I2C_SendByte(0xa0);
I2C_WaitAck();
I2C_SendByte(addr);
I2C_WaitAck();
I2C_Start();
I2C_SendByte(0xa0 +0x01);
I2C_WaitAck();
temp=I2C_ReceiveByte();
I2C_NoAck();
I2C_Stop();
return temp;

}


void I2C_ReadS_24C(uint16 addr ,uint8* pBuffer,uint16 no)
{I2C_ReadByte(pBuffer,(uint8)no,addr);
}

void I2C_WriteS_24C(uint16 addr,uint8* pBuffer,uint16 no)
{
while(no)
{I2C_WriteByte(*pBuffer,addr,EEPROM_ADDR);// I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress)
   pBuffer++;addr++;
   no--;
   //Delay_ns(20);
}
/*
HAL_ENTER_ISR();
I2C_Start();
I2C_SendByte(0xa0);//((addr & 0x0700) >>7) | EEPROM_ADDR& 0xFFFE);//设置高起始地址+器件地址
I2C_WaitAck();
I2C_SendByte((uint8)(addr& 0x00FF));   //设置低起始地址      
I2C_WaitAck();
while(no--)
        {I2C_SendByte(*pBuffer);pBuffer++;
         I2C_WaitAck();
        }
I2C_Stop();
HAL_EXIT_ISR();*/
}




void I2C_ByteWrite_24C(uint16 addr,uint8 dat)
{I2C_WriteByte(dat,addr,EEPROM_ADDR);
}


//测试用
void I2C_Test(void)
{
        uint8 i;
        uint8 I2c_Buf;
        //I2C_Standby_24C();
        //填充缓冲
        for(i=0;i<20;i++)
                I2c_Buf=i+0x70;
        //写
        I2C_WriteS_24C(10,I2c_Buf,20);EE_Delay_ms(100);
        I2C_WriteByte(0x41,31,EEPROM_ADDR);
        I2C_WriteByte(0x42,32,EEPROM_ADDR);
        I2C_WriteByte(0x43,33,EEPROM_ADDR);
        //清缓冲
        for(i=0;i<20;i++)
                I2c_Buf=0;
        //读
        EE_Delay_ms(100);
        I2C_ReadS_24C(10,I2c_Buf,30);
        EE_Delay_ms(100);
}


、、--------------------------
混论坛这么久,一直都不敢让坛友看这么长的程序。

dzymushi 发表于 2014-11-1 17:47:05

void IIC_WriteByte(unsigned int Addr,unsigned char Data)
{
    uint16 i;
        IIC_Start();
        IIC_Send(0xa0|((Addr/256)<<1));
        IIC_Send(Addr%256);
        IIC_Send(Data);
        IIC_Stop();
    for(i=0;i<5000;i++);        //这个时间很重要               
}
这个是我一直用的写字节的代码,是不是延时不足?
24C02硬件地址三根线需要接,是不是地址不对?

lixin91985 发表于 2014-11-2 08:33:26

dzymushi 发表于 2014-11-1 17:47
void IIC_WriteByte(unsigned int Addr,unsigned char Data)
{
    uint16 i;


延时肯定是足够的 。

地址也肯定是正确的。

都已经能够写入和读出了。
页: [1]
查看完整版本: 实在搞不定了,求助高手 指出CC530读取24C02中的BUG