lzlym182 发表于 2011-6-24 12:00:53

STC单片机内部EEPROM读写操作避免使用大量ram指导思想及具体操作....

看到很多网友被EEPROM不能保存大量数据问题所困惑,特发此贴,希望他们能从这里获得一点启发。

STC单片机内部EEPROM写操作必须要求被写入地址的数据全为0xFF才能正确改写,因此如果恰巧这个被写入的地址里的值是0xFF,那么你可以正常写入,不必整个扇区擦除;但是不幸的是这个地址不是恰巧是那个值,那么你需要整个扇区(512字节)擦除之后才能写入。

如果保存的扇区只保存三两个位数不多的char数据,那好办,参考数据手册的做法,开辟相同的ram变量作为缓存,读保存之后再进行改写操作那是没太大问题的。

但是如果要在一个扇区里保存的大量数据呢?如果还是按上述方法来做,那么结果只会证明你太不会脑筋急转弯了。

以下是我一年前做项目时(需要保存2000多个数据)用到的解决思路,缓存变量只用一个char型或者一个int型足以。

思路非常简单,就是利用EEPROM作为缓存!

比如数据要保存在A扇区,则利用B扇区作为缓存,当要向A扇区里的C地址写入char数据时,先检查C地址里数据是否全为高,及0xFF,如果是,则直接写

入。如果不是,先擦除B整个扇区,读出A区的第一个数据,保存到B区第一个地址,读出A区的第二个数据,保存到B区第二个地址,当遇到C地址时,把待

写入的数据直接保存到B区的C地址,如此循环直至把A区的无需修改数据和待修改数据完全保存到B区,将A区擦除,再将B区数据回写A区,完毕!

具体程序如下:

/************************************************************************************/
//函数名称:
//函数功能:往指定扇区指定地址里写一个16位数据
//                                       
//入口参数:
//出口参数:
/************************************************************************************/
void write_block_one_word(u16 sector,u8 offset,u16 word,u16 sector_buf)
{
        u16 data temp;
        u16 data i;
        temp=eeprom_read_byte(sector*SIZE+offset*2);                //读高8位
        temp=temp<<8;
        temp+=eeprom_read_byte(sector*SIZE+offset*2+1);                //读低8位
        if(temp==word)                                                                                //数据与待写入相等,直接闪人
                {
                        ;
                }
        else if(temp==0xFFFF)                                                                //没必要再做保存擦出浪费cpu时间,直接写入
                {
                        eeprom_write_byte(sector*SIZE+offset*2,(u8)(word>>8));                                //写高8位
                        eeprom_write_byte(sector*SIZE+offset*2+1,(u8)word);                                        //写低8位
                }
        else
                {
                        eeprom_sector_erase(sector_buf*SIZE);
                        for(i=0;i<512;i++)
                                {
                                        if(i==offset*2)
                                                {
                                                        eeprom_write_byte(sector_buf*SIZE+offset*2,(u8)(word>>8));                //写高8位
                                                }
                                        else if(i==offset*2+1)
                                                {
                                                        eeprom_write_byte(sector_buf*SIZE+offset*2+1,(u8)word);                //写低8位
                                                }
                                        else
                                                {
                                                        eeprom_write_byte(sector_buf*SIZE+i,eeprom_read_byte(sector*SIZE+i));
                                                }
                                }
                        eeprom_sector_erase(sector*SIZE);
                        for(i=0;i<512;i++)
                        eeprom_write_byte(sector*SIZE+i,eeprom_read_byte(sector_buf*SIZE+i));       
                }
}

renpeng009 发表于 2011-6-24 12:25:01

mark

880705lpdhr 发表于 2011-6-24 12:43:12

mark

wajlh 发表于 2011-6-24 13:05:17

mark

electron_love 发表于 2011-6-24 14:06:53

蛋疼不已,首先说明,本人菜鸟,等待板砖

你要是写的频繁了,单片机就挂了

coyool 发表于 2011-6-24 17:36:24

说说我的方法:1,你要写入的东西很小的吧,不超过256吧,所以我就一个扇区(4K)分16段,第一次写第一段,第二次第二段,..写满之后擦除下一个扇区,继续写第一段。这样就很好了,不是每次都要擦除很省事。
如果用4个扇区做Eeprom的话就可以写4*16*1000次了,举例而已,数据不一定对。以前我 用瑞萨就是这样搞的

amazing030 发表于 2011-6-24 17:48:34

看看我的这个帖子,基于虚拟扇区的Flash存储管理技术,在SPI Flash中存储有结构的数据时我都这样用。

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4550158&bbs_page_no=1&search_mode=3&search_text=amazing030&bbs_id=9999

PS:貌似帖子中的程序有一点小问题...

cqfeiyu 发表于 2011-6-24 18:10:43

好方法,降低寿命,有得必有失

lindabell 发表于 2011-6-24 18:38:18

将A区擦除,再将B区数据回写A区

数据就不用搬回A区了,这样不省的时间吗

lzlym182 发表于 2011-6-24 19:14:08

回复【5楼】coyool
-----------------------------------------------------------------------

STC的一擦除就是整个扇区的数据(512字节),不保存不行

lzlym182 发表于 2011-6-24 19:18:57

回复【7楼】cqfeiyu
好方法,降低寿命,有得必有失
-----------------------------------------------------------------------

http://cache.amobbs.com/bbs_upload782111/files_41/ourdev_651786OKLGEA.jpg
(原文件名:未命名.jpg)


10万次,打1折只用,1万次,也够用

lzlym182 发表于 2011-6-24 19:23:09

回复【8楼】lindabell 欧海
将a区擦除,再将b区数据回写a区
数据就不用搬回a区了,这样不省的时间吗
-----------------------------------------------------------------------

要改的是A区,B区只是借来做暂存,确实是比较费时间

当然你可以改进,比如用虚拟映射方法。

lzlym182 发表于 2011-6-24 19:29:40

回复【4楼】electron_love
蛋疼不已,首先说明,本人菜鸟,等待板砖
你要是写的频繁了,单片机就挂了
-----------------------------------------------------------------------

我写的非常频繁,一写2000多个int型数据,运行一年多,单片机没见挂,谢谢。

lzlym182 发表于 2011-6-24 19:32:47

回复【6楼】amazing030
-----------------------------------------------------------------------

学习下

fjourdev 发表于 2011-6-24 19:33:46

回复【8楼】lindabell 欧海
将a区擦除,再将b区数据回写a区
数据就不用搬回a区了,这样不省的时间吗
-----------------------------------------------------------------------

我也这样想,以后需要改是再搬回来就是了

coyool 发表于 2011-6-24 20:25:39

回复【9楼】lzlym182
-----------------------------------------------------------------------

我知道啊,我意思是把所有的512个字节都写满了再擦,这样就可以少擦很多次了

416446891 发表于 2011-6-24 20:45:38

MARK
页: [1]
查看完整版本: STC单片机内部EEPROM读写操作避免使用大量ram指导思想及具体操作....