我通常使用的技术是为数据添加一个4字节的滚动序列号,其中最大的数字代表最新的/当前的值。在存储2个字节的实际数据的情况下,总共6个字节,然后形成一个循环队列排列,因此对于128个字节的EEPROM,它将包含21个条目,并增加了21倍的耐力。
然后,启动时可以使用最大序列号来确定要使用的下一个序列号和队列的当前尾部。以下C伪代码演示,这是假定在初始编程时EEPROM区域已被擦除为0xFF的值,因此我忽略了0xFFFF的序列号:
struct
{
uint32_t sequence_no;
uint16_t my_data;
} QUEUE_ENTRY;
#define EEPROM_SIZE 128
#define QUEUE_ENTRIES (EEPROM_SIZE / sizeof(QUEUE_ENTRY))
uint32_t last_sequence_no;
uint8_t queue_tail;
uint16_t current_value;
// Called at startup
void load_queue()
{
int i;
last_sequence_no = 0;
queue_tail = 0;
current_value = 0;
for (i=0; i < QUEUE_ENTRIES; i++)
{
// Following assumes you've written a function where the parameters
// are address, pointer to data, bytes to read
read_EEPROM(i * sizeof(QUEUE_ENTRY), &QUEUE_ENTRY, sizeof(QUEUE_ENTRY));
if ((QUEUE_ENTRY.sequence_no > last_sequence_no) && (QUEUE_ENTRY.sequence_no != 0xFFFF))
{
queue_tail = i;
last_sequence_no = QUEUE_ENTRY.sequence_no;
current_value = QUEUE_ENTRY.my_data;
}
}
}
void write_value(uint16_t v)
{
queue_tail++;
if (queue_tail >= QUEUE_ENTRIES)
queue_tail = 0;
last_sequence_no++;
QUEUE_ENTRY.sequence_no = last_sequence_no;
QUEUE_ENTRY.my_data = v;
// Following assumes you've written a function where the parameters
// are address, pointer to data, bytes to write
write_EEPROM(queue_tail * sizeof(QUEUE_ENTRY), &QUEUE_ENTRY, sizeof(QUEUE_ENTRY));
current_value = v;
}
对于较小的EEPROM,3字节序列将更有效,尽管需要一点位切片而不是使用标准数据类型。