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); //頁擦除
}
}

