使用I2C协议读取EEPROM芯片时出现问题

我正在尝试读取支持 I2C 协议的EEPROM芯片(不能告诉IC型号,因为它没有打印)。当然它支持I2C协议,因为我编写了一个代码来使用I2C库检测它,我得到的设备地址是 0x51 。现在我正在尝试编写一个从该IC芯片读取数据的代码。代码如下:

#include 

int addr = 0;

void setup() {
    Wire.begin();//initialise the connection
    Serial.begin(9600);
    while (!Serial) {}
    delay(100);
}

void loop() {
  byte deviceAddress = 0x51;
  byte data = readData(addr, deviceAddress);
  Serial.print(data, HEX);
  Serial.print(" ");
  addr++;
  if(addr%16 == 0) {
     Serial.print('\n');
  }
 //check for 1Kbits first
  if (addr%128 == 0) {
     Serial.println("round complete");
     Serial.println();
     addr = 0;
  }
  delay(100);
}

byte readData(int address, int deviceAddress) {
 //sending device address
  Wire.beginTransmission(deviceAddress);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom((short int)deviceAddress, 1);
  if(Wire.available()) {
    byte data = Wire.read();
    return data;  
  }
  return 0xAA;//random data
}

我面临的问题是,我将地址(我想从中读取数据)作为数据本身返回(例如,read(0)返回0,read(1)返回1,依此类推)。我甚至尝试使用逻辑分析仪(在这种情况下为Saleae逻辑)调试I2C通信。屏幕截图如下所示。

enter image description here

屏幕截图显示了来自单个地址(0x78)的读取操作的逻辑,但故事适用于每个地址,即我返回地址而不是地址中的数据。

上面代码的输出如下:

0 1 2 3 4 5 6 7 8 9 A B C D E F
  10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
  20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
  30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
  40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
  50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
  60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
  70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
  完整的

你能帮我辨别出我在这里做错了什么吗?

谢谢。

1
@MikaelPatel:我将尝试使用16位地址,让您知道结果是什么。
额外 作者 mcrumley,
@NickGammon:只是为了确保内容不是0x00,0x01等。我试图对芯片执行写操作。但是写完后读取的结果仍然是一样的。也许我必须尝试使用​​你建议的16位地址。
额外 作者 mcrumley,
@NickGammon:我尝试使用16位地址,但没有成功。我得到的数据全是零。也许是因为现在我回到了我写的前8位,即0x00。我还在看你在博客中建议的I2c库。 dsscircuits.com/articles/arduino-i2c-master-library 。你能帮我理解一下,registerAddress究竟是什么?它用于该库的许多功能,例如,地址,寄存器地址,*数据,数字字符串。谢谢!
额外 作者 mcrumley,
好的我正在做一个逆向工程项目,芯片实际上是一个COB。然后,我必须以某种方式将它打开并看到下面。不管怎么说,多谢拉。
额外 作者 mcrumley,
芯片有多少条腿(引脚)?
额外 作者 Nick Gammon,
我也同意Mikael,你可以尝试发送一个16位的地址。例如,首先发送一个零,然后发送一个地址。在任何情况下,你能否确定芯片内存中没有0x00,0x01等?
额外 作者 Nick Gammon,
它取决于器件,但有些有一个寄存器,向其写入内容会导致内部位置位。老实说,尝试帮助写入/读取未知设备几乎是不可能的。只需5美元,你就可以购买一个你知道零件编号的芯片,并且可以获得数据表。
额外 作者 Nick Gammon,
如何使用16位地址?这是我为Cosa写的驱动程序的链接; github.com/mikaelpatel/Cosa/blob/master/libraries/ AT24CXX /…
额外 作者 Mikael Patel,

3 答案

您需要将地址作为两个字节逐个传递。

不要做:

Wire.write(address);

相反,做:

Wire.write((uint8_t)(address >> 8));//MSB
Wire.write((uint8_t)(address & 0xFF));//LSB
2
额外

总之,你应该拆分

Wire.write(address);

Wire.write((int)(eeaddress >> 8));//MSB
Wire.write((int)(eeaddress & 0xFF));//LSB

I am working on a similar project right now. I have searched through many different codes and libraries and found the following to work the best: https://playground.arduino.cc/Code/I2CEEPROM

I am using the 24LC1025 who's datasheet can be found here: http://www.microchip.com/datasheet/24LC1025

我使用1Mb版本,它使用0x51和0x50,因为它有两个页面。我怀疑你会发现你的芯片至少是相似的,因为你列出的I2C地址。您可能拥有仅使用一个地址的同一芯片的较小版本。

1
额外

没有特定的芯片信息,这将是困难的。

但是,我对EEPROM和I2C的经验是,第一个操作是编写命令,然后写入该命令的参数,然后读取响应。

通常,EEPROM中需要读取状态寄存器(通过写入命令,然后读取响应)以确定EEPROM是否准备好接收不同的命令,例如写入以设置读取的地址。/write,然后是实际的read命令。

0
额外