I2C写入E2,我用的24C02,读取数据不对。

我通过GPIO口模拟I2C对E2进行读/写操作。先对地址0x20写入数据0x01,再去读地址0x20,但是读到的数据是0xff。一下是逻辑分析仪抓取到的图。

img

写完数据后,延时10ms之后再去读取数据!感觉这个时序有点问题!

  • 你可以参考下这篇文章:模拟I2C怎么用--教你使用GPIO口模拟I2C总线协议
  • 除此之外, 这篇博客: 使用GPIO模拟I2C的驱动程序分析中的 一、I2C协议结构 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 在这里插入图片描述
    一般SCL和SDA上都会借一个上拉电阻。
    如果要去使用GPIO模拟I2C,必须对GPIO的时序了解比较清楚

  • 以下回答由chatgpt基于相关博客总结生成:

    根据问题描述和逻辑分析仪抓取的图,可能存在以下几种问题:

    1. SDA在写入E2数据时没有按照协议进行驱动,导致数据传输失败
    2. 读取数据时没有正确驱动SDA线,导致读取到的数据为0xff

    针对这些问题,可以按照以下步骤进行排查和解决:

    1. 确认GPIO口设置为输出,并开启开漏/开极模式
    SDA_GPIO->MODER |= GPIO_MODER_MODE1_0; //使能pin1第一种输出模式
    SDA_GPIO->OTYPER |= GPIO_OTYPER_OT1;   //设置为开漏/开极
    
    1. 按照I2C协议进行SDA驱动和读取数据的逻辑编写,具体如下:
    2. 写入E2数据时,先发送起始信号,然后发送器件地址,接着发送E2数据的地址,最后发送E2数据内容,并发送停止信号。 C void I2C_Write_E2(unsigned char device_addr, unsigned char data_addr, unsigned char data) { IIC_Start();//起始信号 IIC_Send_Byte(device_addr << 1);//发送器件地址 + 写命令 if(!IIC_Wait_Ack())//等待ACK { IIC_Stop(); return; } IIC_Send_Byte(data_addr);//发送E2数据的地址 IIC_Wait_Ack();//等待ACK IIC_Send_Byte(data);//发送E2数据内容 IIC_Wait_Ack();//等待ACK IIC_Stop();//停止信号 }
    3. 读取E2数据时,先发送起始信号,然后发送器件地址,接着发送E2数据的地址,接着发送起始信号,再发送器件地址,并加上读命令,然后读取E2数据内容,并发送不应答位,最后发送停止信号。 C unsigned char I2C_Read_E2(unsigned char device_addr, unsigned char data_addr) { unsigned char temp = 0; IIC_Start();//起始信号 IIC_Send_Byte(device_addr << 1);//发送器件地址 + 写命令 if(!IIC_Wait_Ack())//等待ACK { IIC_Stop(); return 0xff;//失败返回0xff } IIC_Send_Byte(data_addr);//发送E2数据的地址 IIC_Wait_Ack();//等待ACK IIC_Start();//起始信号 IIC_Send_Byte((device_addr << 1) | 0x01);//发送器件地址 + 读命令 IIC_Wait_Ack();//等待ACK temp = IIC_Read_Byte(0);//读取E2数据内容,不发送应答位 IIC_Stop();//停止信号 return temp; }
    4. 验证其他器件的I2C操作是否正常,以排除硬件问题的可能性。

    如果以上操作仍不能解决问题,可能原因为程序逻辑有误或芯片规格不同导致,需要进一步排查。