分享

关于单片机EEPROM数据保存的若干经验总结

 guitarhua 2014-12-06
因为要保存的数据可能是千变万化的,字长可能从8位到32位,其中包括char(8)、short int(16)、 int(32)、float(32),而不同数据类型在不同体系架构上字长各不相同,复杂点的甚至包括结构体Struct,
因为结构体包含数据大小未知,完成由用户定义,如果保存数据时要考虑到这么多的变化,那能把人都搞晕,因此设计一个以不变应万变的数据保存机制就很好了,好比是复杂平台中的数据串行化保存。
在单片机里面不可能实现这么高级的技术,但是也可以通过一个小小的技巧实现类似功能,方式就是通过联合体来保存,比如下面所示

struct e2prom_data
{
char TEM_compensate;
unsigned int sterilization_temperature[10];//0.1
unsigned char sterilization_time_min[10];
unsigned char exhaust_times;
unsigned char prebalance_time_min;
};

union sector
{
struct e2prom_data sterlization_data;
unsigned char storage[ sizeof(struct e2prom_data) ];
} e2prom;

联合sector代表实际的扇区,大小不能超过扇区大小,而上面的结构体就用来保存真正要用到的变量,然后通过联合体sector里面的unsigned char storage,统一转换成1个字节来保存实际数据,极其方便。
而要读取数据的时候可以通过下面的  void read_sector(char secn)函数来统一操作,把数据统一读取到内存中,确认保存后再通过void write_sector(char secn)统一保存。
效率很高,用内存来缓存数据,可以减小EEPROM擦写次数,提高寿命。

  void read_sector(char secn)
{
  int i;
int E2prom_sector_start_addr=(secn-1)*512;
for(i=0;i< sizeof(struct e2prom_data);i++)
{
e2prom.storage[i]=Byte_Read( i+ E2prom_sector_start_addr);
}
 IAP_Disable();
}

void write_sector(char secn)
{
int i;
int E2prom_sector_start_addr=(secn-1)*512;

Sector_Erase(E2prom_sector_start_addr);
for(i=0;i< sizeof( struct e2prom_data );i++)
{
Byte_Program(i + E2prom_sector_start_addr, e2prom.storage[i]);
}
   IAP_Disable();
}

唯一不足的地方是实际数据地址是固定的,如果常年累月读写次数多了的话,EEPROM还是有可能出问题的,下一步改进的地方就是通过实际一个虚拟存储空间来延长EEPROM寿命,
实际方案是比如一个扇区是1K字节,那么把1k分成256个单元,每个单元4个字节,扇区首单元保存扇区状态,剩余255个单元作为实际存储单元,而每个存储单元又分成2+2布局,前两字节保存实际数据,后两字节保存虚拟地址,
1.写入时写入数据紧跟后面写入虚地址VirtAddVarTab[i](0<=i<NumbOfVar)
2.每个Page第一个地址写入该页状态(Earse,Reveice,Vild)
相同地址再次写入时不会把上次写的擦掉,而是在模拟EEPROM区尾部未写过的地方再次写入数据、虚地址, 
3、 读的时候是从尾部开始匹配地址,也就是读取最后一次写的内容。 
4、模拟EEPROM区分为2页,如果一页满了把这一页内陆址不重复的数据复制到另一页后擦除,2页交替使用。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多