Flash均衡保存算法
在实际应用中,用户经常需要在程序运行过程中保存或读取一些数据,这些数据在工作中经常会变化,而且掉电后也不能丢失,所以需要及时地进行存储,存储这些数据常用的存储器是EEPROM。单片机虽然本身不带EEPROM,但是它支持自编程技术,可以利用内部FLASH来模拟EEPROM,这样不仅简化了设计,而且降低了成本。
FLASH的擦写次数是有限的,一般是10W次, FLASH单个存储单元bit只能从1变为0,而不能从0变成1。想要变成1,只能page擦除,这里的page表示一个擦除单位,擦除过程就是把page所有的位都写1,这种硬件特性决定需要一种比较高效的写flash算法。总不能一次更改数值时擦除整一大片FLASH。
改进的保存方法:
处理方法是将1024字节按16字节大小分成64等份,按后面格式存储参数
地址 0x10*n +0x00 +0x01 +0x02 ... +0x0E +0x0F
内容 flag data1 data2 ... data15 check_sum
check_sum=(flag+data1+data2+...+data15)&0xFF
flag为0xA5表示当前16个字节为正在使用的记录,为其它值表示当前16字节已经丢弃
这种保存方法是使用空间来换取擦写次数。
具体代码实现
定义FLASH页大小,储存数据大小
#define FLASH_PAGE 1024
#define FLASH_DATAPACK 16
定义一个储存结构体
typedef struct {
u32 Addr; //地址为flash一页的首地址
u8 Read; //读地址的计数
u8 Write; //写地址的计数
u8 ReadBuff[FLASH_DATAPACK]; //读取缓存区
u8 WriteBuff[FLASH_DATAPACK]; //写入缓存区
}EEPROMTypeDef;
//FLASH写函数
void FlashWrite(EEPROMTypeDef *Flash_16)
{
u8 Flag;
while_1:
//获取标志位
Flag = *(vu8*)(Flash_16->Addr + (Flash_16->Write) * FLASH_DATAPACK);
if(Flash_16->Write < 64 && Flag == 0xff) //如果地址在一页内且内容空白
{
HT_Flash_ByteWrite(Flash_16->WriteBuff, Flash_16->Addr + (Flash_16->Write++) * FLASH_DATAPACK, FLASH_DATAPACK);
}
else if(Flash_16->Write < 63 && Flag != 0xff) //如果地址在一页内却有数据存储
{
Flash_16->Write++;
goto while_1;
}
else if(Flash_16->Write >= 64 )//如果地址不在一页内
{
Flash_16->Write = 63;
}
}
//FLASH读函数
void FlashRead(EEPROMTypeDef *Flash_16)
{
u8 Flag;
while_1:
//获取标志位
Flag = *(vu8*)(Flash_16->Addr + (Flash_16->Read) * FLASH_DATAPACK);
if(Flash_16->Read < 64 && Flag == 0xA5) //如果地址在一页之内且数据有效
{
HT_Flash_ByteRead(Flash_16->ReadBuff, Flash_16->Addr + (Flash_16->Read) * FLASH_DATAPACK, FLASH_DATAPACK);
HT_Flash_ByteWrite(00, Flash_16->Addr + (Flash_16->Read++) * FLASH_DATAPACK, 1); //标记数据无效
}
else if(Flash_16->Read < 64 && Flag != 0xA5) //如果地址在一页之内但数据无效
{
if(Flag != 0xff)
{
Flash_16->Read++;
goto while_1;
}
}
else if(Flash_16->Read >= 64) //如果地址不在一页之内
{
Flash_16->Read = 0;
Flash_16->Write = 0;
HT_Flash_PageErase(Flash_16->Addr); //页擦除
}
}

