EEPROM协议误解

EEPROM protocol misconception

我目前正在使用通过 i2c 连接到 stm32f4 (11RET) 的微芯片的 eeprom ( 24cw160 )。配置和连接似乎工作正常,因为我的逻辑分析器打印了一些 i2c 消息(带有 ACK),我可以发送数据和接收数据。在阅读 reference manual(特别是第 13 和 18 页,其中包含我正在执行的两个操作的示意图)后,我希望下面的代码将数据 0,1,2... 依次发送到 x10 之后的地址然后接收相同的数据并打印它们:

while(true){

    HAL_Delay(1000);
    std::array<uint8_t,100> arr{};
    int counter=0;
    for(auto&i :arr){
      i=counter;
      counter++;
    }
    auto ret1 = HAL_I2C_Mem_Write_DMA(&hi2c1 , 0xa0 , 0x10 , 1 ,arr.data() , arr.size());
    HAL_Delay(1000);
    std::array<uint8_t,100> arr2{};
    arr2.fill(1);
    auto ret2 = HAL_I2C_Mem_Read( &hi2c1 , 0xa1 , 0x10 , 1 , arr2.data() , arr2.size(),100);
    printf("arr2:\n");
    for(auto i:arr2){
      printf("%d,",(int)i);
    }
    printf("\nWrite ret status: %d\nRead ret status: %d\n",ret1,ret2);
  }

相反,我在终端上得到的是:

arr2:
70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
Write ret status: 0
Read ret status: 0
arr2:
68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
Write ret status: 0
Read ret status: 0

注意,第一行打印与第二行有一些不同,第二行是重复出现的(所以第一次打印的 while true 与其他打印的有点不同)老实说我把自己弄糊涂了使用我给 HAL_I2C_Mem_Writeread 的常量参数,我也想对此做一些解释。 有关更多信息,请评论我,我将提供所有必要的 diagnostics/initializations 等

多亏了评论,我才设法将一个字节发送到我想要的任何地址。前面代码中注意到的一个错误是 MemAddress 参数(HAL_I2C_Write_Mem 的第三个参数),因为我的 eeprom 是 11 位可寻址的,我应该声明它是 16 而不是 8 作为额外的 5 位被忽略的位,但少于 11 可能会出现故障。

第二个问题是我试图写入超过 32 个字节,但我只读取前 32 个,因为协议不接受一次写入或读取超过 32 个字节的页面。所以这里是修改后的代码,并对更改进行了一些评论:

std::array<uint8_t,32> arr{0}; //32 bytes instead of something silly
unsigned counter=0;
for(auto&i :arr){
    i=counter;
    counter++;
}
// 0x20 is a start of a page so it can write all 32 bits
// I2C_MEMADD_SIZE_16BIT is the value 2 instead of 1 I had
// The extra 5 bits are ignored
// For the testing I call the blocking write
auto ret1 = HAL_I2C_Mem_Write(&hi2c1 , 0xa0 , 0x20 , I2C_MEMADD_SIZE_16BIT , arr.data() , arr.size(),4);
HAL_Delay(4);
std::array<uint8_t,32> arr2{0};
arr2.fill(1);
auto ret2 = HAL_I2C_Mem_Read( &hi2c1 , 0xa1 , 0x20 , I2C_MEMADD_SIZE_16BIT , arr2.data() ,arr2.size(),4);
HAL_Delay(4);
printf("arr2: ");
for(auto i:arr2)
   printf(" %d,",(int)i);
printf("\nWrite ret status: %d\nRead ret status: %d\n",ret1,ret2);