Introduction to EEPROM Libraries#

Code-docs: xid: 20230530-175600

接口抽象#

不同层级的抽象,提供不同的使用接口。最典型的接口有:

  1. Arduino 的数组型

  2. 基本的 Byte_read, Byte_write, page_read, page_write 功能

  3. 用于提交性能的 put, update

问题#

EEPROM 写一个字会造成写一页吗?

I2C EEPROM with page write/read - Software / Interfacing - Arduino Forum

Arduino EEPROM Library#

Arduino EEPROM library [1] 将UNO自带的 EEPROM 抽象成了 Array,完全隐藏了 EEPROM 的访问时的通信与读写细节,也不需要手写 I2C 的通信过程,只需要当成一个可按字节地址访问的数组,使用非常方便。

EEPROM.write(addr, val);
value = EEPROM.read(address);
EEPROM.update(address, val);

Iteration#

int index = 0;
while (index < EEPROM.length()) {
  //Add one to each cell in the EEPROM
  EEPROM[ index ] += 1;
  index++;
}

问题#

能不能将外接的 EEPROM 按 Arduino EEPROM library 的方法使用?

EEPROM Byte Access Library#

来自于 Arduino Cookbook 第十三章的 EEPROM 方法,只提供两个函数:

  • I2CEEPROM_Read(address)

  • I2CEEPROM_Write(address, byte data)

这两个函数很好用,配合 for 循环,可以方便顺序读写每个字节,完全可以用于简单(数据量不大,性能要求不高)的 EEPROM 读写场合。

其中 write 每写一个字节等待 5ms。并指出了优化性能的两个方向:

  1. 使用 Page Write。采用 Page 写时,可以连续将8/16 个字节的数据通过I2C连续发往 EEPROM

  2. 使用“确认查询”技术。不管是 Byte Write,或是 Page Write,在写完之后,都要等待一定的时间,才能继续往 EEPROM 写入新数据。CPU 在这段时间完全停下来,什么都不干,是不高效的。此时应该使用类似于 Blink without Delay 的技术进行程序设计。

讨论#

  1. 没有Arduino EEPROM 的下标访问方法,即不能像数组一样使用,这需要进一步抽象,在此基础上进一步实现下标访问功能,是一个很好的练习题。

  2. 实现 Page Write 和确认查询技术

  3. 为什么没有体会到页边界?

EEPROM Page Access#

用I2C访问和控制具有 I2C 接口的外部 EEPROM 是典型的使用方法。这是写一个 I2C EEPROM 库之前的雏形。

使用 Wire 提供的 I2C 协议功能,但是,需要手写 EEPROM 的读写逻辑。这个例子适合适合(避开 I2C 的细节)学习后,进一步研究 EEPROM 底层控制方法,即读写当前地址、连续读、连续写、页写与回卷、负载均衡等。

英文原文:Arduino I2C + AC24C32 EEPROM - Programmer All

注意:在用 Wire 完成连续写或者连续读时,会受到 Wire 的读写缓存只有 32 字节 (实际可用少于32字节)的限制。

如何写简单的 EEPROM Library#

Arduino Playground - I2CEEPROM

简单好用,可以学习只用 Wire 库,是怎么做EEPROM访问接口抽象的:

  • byte_read()

  • byte_write()

  • page_write()

  • read_buffer()

问题:

  • 为什么没有观察到 page roll over?

External EEPROM Arduino Library#

Sparkfun/External_EEPROM_Arduino_Library: An Arduino library for the easy control of external I2C EEPROMs.

易于理解但并不最为推荐的方法:

void read(uint32_t eepromLocation, uint8_t *buff, uint16_t bufferSize);
void write(uint32_t eepromLocation, uint8_t dataToWrite);
void write(uint32_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize);

更好的方法:

int myValue2 = -366;
myMem.put(10, myValue2); //(location, data)
int myRead2;
myMem.get(10, myRead2); //location to read, thing to put data into
float myValue3 = -7.35;
myMem.put(20, myValue3); //(location, data)
float myRead3;
myMem.get(20, myRead3); //location to read, thing to put data into

还定义了很多设置与辅助用途的方法。

I2C EEPROM#

同样也是用 Wire 库作为通信协议来控制 EEPROM,但特别完整和详尽。独特的地方还包括跨页写大量的数据,并读回检查。

https://learn.sparkfun.com/tutorials/reading-and-writing-serial-eeproms

注意: Wire 连续读写的数据长度限制。

讨论: EEPROM跨页写与负载均衡#

serial - about how to write data in the whole EEprom? - Arduino Stack Exchange

EEPROM PageSize#

EEPROM endurance and page size - Arduino Stack Exchange