找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1957|回复: 11
收起左侧

请教各位关于单片机内部存储的平衡写入

[复制链接]
ID:510170 发表于 2021-7-20 18:03 | 显示全部楼层 |阅读模式
我们在做项目的时候,难免会遇到掉电的问题,一掉电,ram里面的内容全部都清空了。一般来说都会附加一个eeprom,好的eeprom可以写入千万次的数据,但是外带一个是要成本的,且占用接口io,一般的单片机都带有eeprom,但很多都是flash改成eeprom的。虽然对外宣传是eeprom,实际按特性来看就是flash,flash的写入次数要远低于eeprom,一般是10w左右,我们能否利用flash量大且足的特性,将其充分利用起来,进行平衡写法。将其写入次数最大化。以stc8a8k60s4a12单片机为列,里面有4keeprom,分成8个扇区,每个扇区有512个字节,我们再将扇区分成32份,每份有16个字节的数据,用来存储一般的变量应该是足够的,如果不够,再将其扩大就好了。划成16份,32个字节每份。这里只是做比方,其中首字节用来做数据引索,填入aa,查找是也只需要按份来读取aa就可以得出写入指针在哪里了。下一次写入的情况下将这次的首位写为00即可。原理知道了。但是程序应该怎么写呢?由于不是科班出生,都是自学的。只知道简单的判断写法,有大神能出个方便点的算法吗?最好能给个程序实列。我目前的写法是这样的。
                if(IapRead(0x0000)=0xaa){xrzz=0;}
                if(IapRead(0x0010)=0xaa){xrzz=1;}
                if(IapRead(0x0020)=0xaa){xrzz=2;}
                if(IapRead(0x0030)=0xaa){xrzz=3;}
                ......



回复

使用道具 举报

ID:123289 发表于 2021-7-22 09:39 | 显示全部楼层
能力有限,不能理解你所说的【平衡写入】。
要结合考虑。写入次数被你平衡了。也未必科学。
1、为了读写A,先要索引,如果A放在最末,索引时间就会加长。
2、整个区内,有一个单元不良时(假设其它很好,这个很差写200次就不行了),你的【平衡写入】,反而达不成目的。
3、为了【平衡写入】,而使用程序复杂化,且大量占用CPU的时间,未必合算。
回复

使用道具 举报

ID:401564 发表于 2021-7-22 19:27 | 显示全部楼层
平衡写入是个什么东东?没有听说过
十万次的擦写我都觉得足够用了
如果一个数据是经常记录保存,而且量还很大,那就不是一个单片机能保存的了,一般都是用外部的EEPROM,容量大的有64M的
而所谓的写入,目前为止还不知道内部是怎么操作的,在没有验证之前,不要想当然的觉得:每个地址都有十万次的写入寿命,这个地址我用得差不多了,在它没坏之前,换一个地址,它又有十万次的擦写寿命了,感觉是这样而已,目前我还没有听说有人验证过
与其想着这个,还不如考虑一下算法,看一下能不能少用写入操作
回复

使用道具 举报

ID:155507 发表于 2021-7-22 20:43 | 显示全部楼层
如果一个数据是经常记录保存,而且量还很大, 你可以用
NVRAM( Non-Volatile Random Access Memory) 是非易失性随机访问存储器,即断电之后,所存储的数据不丢失的随机访问存储器。

NVRAM 指断电后仍能保持数据的一种RAM。一般都是用电池,可以持续10年。

NVRAM 能够保护数据(即便在掉电情况下),支持高速RAM写操作,擦写次数不受限制。
回复

使用道具 举报

ID:161164 发表于 2021-7-23 00:07 | 显示全部楼层
  1. 先建立一个EEPROM地址数列
  2. u16 code EEP_Addr[]={
  3. 0x0000, 0x0010, 0x0020, ...};
  4. 如你所说,每次写入时都在索引字节填入aa
  5. 因为EEPROM原始数值为0xFF
  6. 那么经过几次写入后可得出以下列表
  7. (首地址)(字节0)(字节1)(字节2)...
  8. 0x0000   0xaa    0xXX    0xXX
  9. 0x0010   0xaa    0xXX    0xXX
  10. 0x0020   0xff     0xff      0xff
  11. ...
复制代码


回复

使用道具 举报

ID:451718 发表于 2021-7-23 09:43 | 显示全部楼层
这个想法很有建设性,而且很有可行性。最后特别提醒,可不能因为这个原因,就把ROM当RAM用。   
回复

使用道具 举报

ID:213173 发表于 2021-7-23 10:37 | 显示全部楼层
楼主这个想法没有实际意义。还以stc8a8k60s4a12单片机为列,读flash中数据没有寿命限制,擦写flash次数有寿命限制。擦除是以扇区为单位,所以将扇区划分若干份使用不会延长使用寿命。如果需要保存的数据不太多,可以通过软件轮流使用8个扇区以延长使用寿命。其实这些方法基本都是多余的。只要增加简单硬件就可以实现掉电和关机保存eeprom。你这设备总不至于每天掉电无数次吧?
回复

使用道具 举报

ID:161164 发表于 2021-7-23 14:57 来自手机 | 显示全部楼层
wulin 发表于 2021-7-23 10:37
楼主这个想法没有实际意义。还以stc8a8k60s4a12单片机为列,读flash中数据没有寿命限制,擦写flash次数有寿 ...

软件做到的事,为什要另加硬件?
回复

使用道具 举报

ID:382454 发表于 2021-7-23 16:28 | 显示全部楼层
楼主所想说的平衡写入,我理解应该是这样的吧,将扇区分成32份,每份有16个字节的数据,写入和擦除是从1到16轮流写的,也就是排队写入数据,第一次写1区,第二次写2区,第三次写3区,以此类推从头到尾循环。如果停电了就以最后写入的那个参数把她读出来。
我认为这样利用也是很有创意的,就单单EEPROM使用寿命来说是16倍。其它这个写数据也很简单了,按上面的逻辑来,写一个流水写循环就可以了,读的话,可以读一个最后的标志位即可。
回复

使用道具 举报

ID:161164 发表于 2021-7-23 17:46 | 显示全部楼层

太可怕了,竟然吞了半个贴子
续上
每当要再写入数据时可用For循环找出未被写入的地址
  1. for(i=0;i<32;i++){
  2. HeadAddr = EEP_Addr[i];
  3. if(IapRead(HeadAddr) == 0xFF){
  4. break;
  5. }
  6. }
  7. if(i<32){
  8. iapProgram(HeadAddr,0xaa);
  9. iapProgram(HeadAddr + 1,Data1);
  10. iapProgram(HeadAddr + 2,Data2);
  11. iapProgram(HeadAddr + 3,Data3);
  12. 下略
  13. }else{
  14. //i >= 32代表所有地址已被写满,需先擦除一次再写入
  15. }
  16. 开机的时候先读
  17. for(i=0;i<32;i++){
  18. HeadAddr = EEP_Addr[i];
  19. if(IapRead(HeadAddr) != 0xaa){
  20. break;
  21. }
  22. }
  23. if(i>0){
  24. Data1 = IapRead(HeadAddr + 1);
  25. Data2 = IapRead(HeadAddr + 2);
  26. Data3 = IapRead(HeadAddr + 3);
  27. 下略
  28. }else{
  29. //i = 0 代表没有写入过
  30. }
复制代码




回复

使用道具 举报

ID:283954 发表于 2021-7-23 20:13 | 显示全部楼层
克服断电问题还是软硬兼施来得好,现在的单片机耗电很小了,用个小的锂电池,边用边充电,断电后还可以运作一两天,真的没电了才写进EEPROM,正如 wulin君所言,是整个扇区删除重写,所以扇区分部使用不会延长使用寿命的,依次使用每个扇区是能延长整体寿命。
回复

使用道具 举报

ID:57657 发表于 2021-7-24 09:18 | 显示全部楼层
平衡写入 就是所谓的 磨损均匀算法,EEPROM的写扇区都是有寿命损耗的,写入、擦除 都需要做效验。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表