STM32 FLASH模擬 EEPROM
阿新 • • 發佈:2019-02-11
2. 讀資料
讀資料時是從有效頁的末尾地址開始檢測是否是有效資料,如果是那麼立即返回,程式是通過虛擬地址判斷有
效資料的,第1 個匹配的虛擬地址的資料才是有效的
3. 頁滿時處理資料
說到這裡,看到不少使用例子程式不成功的問題,那麼就請注意下面了,他們的錯誤估計是下面的原因造成的。
當1 頁寫滿時其實裡面有很多無效資料,你只需要將【有效資料】複製到另外1 頁就成。如何複製有效資料呢?
我想很多人估計忽略了 【#define NumbOfVar ((uint8_t)0x03) /* Variables' number */】,NumbOfVar 就是你程
序中實際要儲存的資料量,這個必須與實際保持一致,不能多也不能少,這個如果不一致,那麼在換頁時將出
錯,沒換頁之前倒是沒問題的,原因在於:程式在換頁時將根據NumbOfVar 的值複製有效資料的個數,如果比
實際少,那麼換頁時將丟失資料,如果比實際多那麼將出現舊資料覆蓋最新資料
錯誤的例子:
/* Variables' number */
#define NumbOfVar ((uint8_t)0x05)
uint16_t VirtAddVarTab[NumbOfVar] = {0, 1, 2};
//NumbOfVar 定義的比用的多實際是{0, 1, 2, 0, 0},虛擬地址0 的資料換頁後將出現舊資料覆蓋最新資料
int main(void)
{
uint16_t temp;
for (VarValue = 0; VarValue < 100; VarValue++)
{
EE_WriteVariable(VirtAddVarTab[0], VarValue+10);
}
for (VarValue = 0; VarValue < 500; VarValue++)
{
EE_WriteVariable(VirtAddVarTab[1], VarValue);
temp=0;
EE_ReadVariable(0, &temp);//不換頁讀出資料是對的,換頁後讀出資料錯誤
}
}
//====================================================================================
/* Variables' number */
#define NumbOfVar ((uint8_t)0x03)
uint16_t VirtAddVarTab[NumbOfVar] = {0, 1, 2};
//NumbOfVar 定義為3,下面用到虛擬地址超過VirtAddVarTab 表裡面的值
int main(void)
{
uint16_t temp;
for (VarValue = 0; VarValue < 100; VarValue++)
{
EE_WriteVariable(VirtAddVarTab[0], VarValue);
}
for (VarValue = 0; VarValue < 50; VarValue++)
{
EE_WriteVariable(3, VarValue+2);
}
for (VarValue = 0; VarValue < 200; VarValue++)
{
EE_WriteVariable(2, VarValue);
temp=0;
EE_ReadVariable(3, &temp);//不換頁讀出資料是對的,換頁後讀出資料錯誤
}
}
STM32 FLASH 模擬EEPROM 使用注意:
不少人問該程式的FLASH 儲存資料多少和使用壽命
儲存資料多少跟FLASH 頁大小有關,如果頁大小是1K 那麼只能儲存1024/4-1=256-1 個16 位資料,如果你保
存8 位數,你可以2 個8 位資料組合後儲存或者直接儲存,如果儲存32 位資料那就拆成2 個16 位儲存,當然
關於壽命
現在STM32 的FLASH 壽命是10000 次,
如果你儲存255 個數據那麼每次修改1 個數據FLASH 就要擦寫1 次,如果你儲存1 個數據,那麼你修改255
次該頁才擦1 次,繼續用另外1 頁,建議儲存資料個數不要超過50%,當然如果你的資料基本都不修改你儲存
255 個也是沒有任何問題(你的資料都不修改根本不用關心壽命問題了:)。
STM32 FLASH 模擬EEPROM 優化
官方例程中讀寫資料每次要查詢讀寫位置,寫資料是從頁首地址開始查詢,讀地址是從頁末地址查詢。
假如只有1 個數據,讀資料時效率是很低的,要查到最後才能找到有效資料,
如果頁快滿了寫資料效率也很低,讀效率反而好一點了。
實際程式中記錄下一個可以寫資料的位置將提高資料的讀寫效率,這樣的話:寫資料就是立即寫不用查詢,讀
資料不從頁末地址查詢,而是從最後1 個寫入資料處查詢,這樣特別在頁資料少時效率提高不少。優化過的例
子程式碼只需要增加很少部分就能實現。
增加關鍵程式碼
uint32_t CurWrAddress;
//初始化寫地址,減少每次讀寫時查詢時間
uint16_t InitCurrWrAddress(void)
詳細請看修改後的例子,讀寫函式也做了相應更改
STM32 FLASH 模擬EEPROM 進一步優化
上面優化過的例子在寫資料無須查詢直接寫入就可,但是讀資料在頁資料少是效率提升明顯,在頁資料多時效
率不明顯,特別是頁資料快滿時就跟原來一樣的。
說明:不管是官方還是優化過的例子在頁交換時這個模擬EEPROM 程式都將耗費不少時間的
如果你對時間要求不高完全不用考慮下面的了。
下面就進一步提升它的效率,方法如下:
為每1 個儲存的變數定義1 個對映地址,就是在寫資料時將寫資料的地址偏移儲存起來。比如
第1 次的資料對映地址是0,第2 次的資料對映地址是1,那麼讀資料時就可以立即計算出地址。
此方法對於1K 頁大小的每個資料將增加1 個8 位對映地址,對於2K 頁大小的每個資料將增加
1 個16 位對映地址.
這裡只提供方法,當然方法不是唯一的,有興趣的自己去玩。
讀資料時是從有效頁的末尾地址開始檢測是否是有效資料,如果是那麼立即返回,程式是通過虛擬地址判斷有
效資料的,第1 個匹配的虛擬地址的資料才是有效的
3. 頁滿時處理資料
說到這裡,看到不少使用例子程式不成功的問題,那麼就請注意下面了,他們的錯誤估計是下面的原因造成的。
當1 頁寫滿時其實裡面有很多無效資料,你只需要將【有效資料】複製到另外1 頁就成。如何複製有效資料呢?
我想很多人估計忽略了 【#define NumbOfVar ((uint8_t)0x03) /* Variables' number */】,NumbOfVar 就是你程
序中實際要儲存的資料量,這個必須與實際保持一致,不能多也不能少,這個如果不一致,那麼在換頁時將出
錯,沒換頁之前倒是沒問題的,原因在於:程式在換頁時將根據NumbOfVar 的值複製有效資料的個數,如果比
實際少,那麼換頁時將丟失資料,如果比實際多那麼將出現舊資料覆蓋最新資料
錯誤的例子:
/* Variables' number */
#define NumbOfVar ((uint8_t)0x05)
uint16_t VirtAddVarTab[NumbOfVar] = {0, 1, 2};
//NumbOfVar 定義的比用的多實際是{0, 1, 2, 0, 0},虛擬地址0 的資料換頁後將出現舊資料覆蓋最新資料
int main(void)
{
uint16_t temp;
for (VarValue = 0; VarValue < 100; VarValue++)
{
EE_WriteVariable(VirtAddVarTab[0], VarValue+10);
}
for (VarValue = 0; VarValue < 500; VarValue++)
{
EE_WriteVariable(VirtAddVarTab[1], VarValue);
temp=0;
EE_ReadVariable(0, &temp);//不換頁讀出資料是對的,換頁後讀出資料錯誤
}
}
//====================================================================================
/* Variables' number */
#define NumbOfVar ((uint8_t)0x03)
uint16_t VirtAddVarTab[NumbOfVar] = {0, 1, 2};
//NumbOfVar 定義為3,下面用到虛擬地址超過VirtAddVarTab 表裡面的值
int main(void)
{
uint16_t temp;
for (VarValue = 0; VarValue < 100; VarValue++)
{
EE_WriteVariable(VirtAddVarTab[0], VarValue);
}
for (VarValue = 0; VarValue < 50; VarValue++)
{
EE_WriteVariable(3, VarValue+2);
}
for (VarValue = 0; VarValue < 200; VarValue++)
{
EE_WriteVariable(2, VarValue);
temp=0;
EE_ReadVariable(3, &temp);//不換頁讀出資料是對的,換頁後讀出資料錯誤
}
}
STM32 FLASH 模擬EEPROM 使用注意:
不少人問該程式的FLASH 儲存資料多少和使用壽命
儲存資料多少跟FLASH 頁大小有關,如果頁大小是1K 那麼只能儲存1024/4-1=256-1 個16 位資料,如果你保
存8 位數,你可以2 個8 位資料組合後儲存或者直接儲存,如果儲存32 位資料那就拆成2 個16 位儲存,當然
關於壽命
現在STM32 的FLASH 壽命是10000 次,
如果你儲存255 個數據那麼每次修改1 個數據FLASH 就要擦寫1 次,如果你儲存1 個數據,那麼你修改255
次該頁才擦1 次,繼續用另外1 頁,建議儲存資料個數不要超過50%,當然如果你的資料基本都不修改你儲存
255 個也是沒有任何問題(你的資料都不修改根本不用關心壽命問題了:)。
STM32 FLASH 模擬EEPROM 優化
官方例程中讀寫資料每次要查詢讀寫位置,寫資料是從頁首地址開始查詢,讀地址是從頁末地址查詢。
假如只有1 個數據,讀資料時效率是很低的,要查到最後才能找到有效資料,
如果頁快滿了寫資料效率也很低,讀效率反而好一點了。
實際程式中記錄下一個可以寫資料的位置將提高資料的讀寫效率,這樣的話:寫資料就是立即寫不用查詢,讀
資料不從頁末地址查詢,而是從最後1 個寫入資料處查詢,這樣特別在頁資料少時效率提高不少。優化過的例
子程式碼只需要增加很少部分就能實現。
增加關鍵程式碼
uint32_t CurWrAddress;
//初始化寫地址,減少每次讀寫時查詢時間
uint16_t InitCurrWrAddress(void)
詳細請看修改後的例子,讀寫函式也做了相應更改
STM32 FLASH 模擬EEPROM 進一步優化
上面優化過的例子在寫資料無須查詢直接寫入就可,但是讀資料在頁資料少是效率提升明顯,在頁資料多時效
率不明顯,特別是頁資料快滿時就跟原來一樣的。
說明:不管是官方還是優化過的例子在頁交換時這個模擬EEPROM 程式都將耗費不少時間的
如果你對時間要求不高完全不用考慮下面的了。
下面就進一步提升它的效率,方法如下:
為每1 個儲存的變數定義1 個對映地址,就是在寫資料時將寫資料的地址偏移儲存起來。比如
第1 次的資料對映地址是0,第2 次的資料對映地址是1,那麼讀資料時就可以立即計算出地址。
此方法對於1K 頁大小的每個資料將增加1 個8 位對映地址,對於2K 頁大小的每個資料將增加
1 個16 位對映地址.
這裡只提供方法,當然方法不是唯一的,有興趣的自己去玩。