Introduction to EEPROM Libraries#
Code-docs: xid: 20230530-175600
接口抽象#
不同层级的抽象,提供不同的使用接口。最典型的接口有:
Arduino 的数组型
基本的 Byte_read, Byte_write, page_read, page_write 功能
用于提交性能的 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。并指出了优化性能的两个方向:
使用 Page Write。采用 Page 写时,可以连续将8/16 个字节的数据通过I2C连续发往 EEPROM
使用“确认查询”技术。不管是 Byte Write,或是 Page Write,在写完之后,都要等待一定的时间,才能继续往 EEPROM 写入新数据。CPU 在这段时间完全停下来,什么都不干,是不高效的。此时应该使用类似于 Blink without Delay 的技术进行程序设计。
讨论#
没有Arduino EEPROM 的下标访问方法,即不能像数组一样使用,这需要进一步抽象,在此基础上进一步实现下标访问功能,是一个很好的练习题。
实现 Page Write 和确认查询技术
为什么没有体会到页边界?
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#
易于理解但并不最为推荐的方法:
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