最近嘗試了一下對32的內置flash進行讀寫,衆所周知,芯片的flash是用來存放代碼指令和變量的,其中的數據即使掉電也不會丟失。而stm32的flash之大,對於初學者的小打小鬧完全不用擔心不夠用的情況。
因此,在需要保存一些芯片掉電之後依舊需要保存的數據(數據量不是特別大)時,運用內置flash的空閒部分可以爲我們省去一顆eeprom或外置flash的花銷。
知識總結:
1.flash的寫入之前需要先擦除,且擦除是直接擦除一頁(2KBytes),整個流程爲
(1)解鎖flash(2)擦除一頁或多頁(3)寫數據(4)鎖定flash
2.flash正常寫入一次是16bit
3.flash的地址從0x08000000開始,存儲代碼指令與變量。所以在用戶自己寫flash時,要注意不要把代碼指令與變量給覆蓋了。查看編譯過的代碼使用了多少內存,可在Keil中雙擊工程名查看*.map文件
基地址加上Size就是代碼指令與變量佔用的空間。在寫入用戶數據時,要避開這些地方。
以下是基於正點原子庫函數的flash讀寫代碼。在STM32F103RCT6測試通過。可以直接複製使用,好用請爲博客點個贊!
flash.h:
#ifndef _FLASH_H
#define _FLASH_H
#include "stm32f10x.h"
extern uint32_t Flash_EraseWriteOnePage(uint32_t WRITE_START_ADDR,u16 SizeOf_u32,uint32_t *DataAddress);
extern void Flash_ReadOnePage(uint32_t READ_START_ADDR,u16 SizeOf_u32,uint32_t *DataAddress);
#endif
flash.c
/////////////////////////////////////////
//Author: Read Air
//Version: 1.0
//Date:2019/4/18
/////////////////////////////////////////
#include "flash.h"
#include "stm32f10x.h"
///////////////////////////////////////////////////////
//WRITE_START_ADDR -- 開始寫的地址
//SizeOf_u32 -- 要寫入的32位(雙字)的數量
//DataAddress -- 等待被寫入的數據數組(32位的)
//返回值 -- 出現擦除失敗故障返回寫入地址,正常返回0
///////////////////////////////////////////////////////
uint32_t Flash_EraseWriteOnePage(uint32_t WRITE_START_ADDR,u16 SizeOf_u32,uint32_t *DataAddress)
{
char EraseCounter = 0;
static FLASH_Status FLASHStatus;
uint32_t Address;
u16 Remain_u32 = SizeOf_u32;
u8 err_time=0;
/* 解鎖 */
FLASH_Unlock();
/* 清空所有標誌位 */
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
/* 擦除一頁*/
FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR);
/* 嘗試擦除*/
while((FLASHStatus != FLASH_COMPLETE)&&(err_time<5))
{
FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR);
err_time++;
}
/* 擦除失敗*/
if (err_time >= 5) return WRITE_START_ADDR;
/* 向內部 FLASH 寫入數據 */
Address = WRITE_START_ADDR;
while ((Remain_u32 > 0) && (FLASHStatus == FLASH_COMPLETE))
{
FLASHStatus = FLASH_ProgramWord(Address, DataAddress[SizeOf_u32-Remain_u32]);
Address = Address + 4;
Remain_u32--;
}
/* 鎖定*/
FLASH_Lock();
return 0;
}
///////////////////////////////////////////////////////
//READ_START_ADDR -- 開始寫的地址
//SizeOf_u32 -- 要讀出的32位(雙字)的數量
//DataAddress -- 等待被讀出的數據數組(32位的)
///////////////////////////////////////////////////////
void Flash_ReadOnePage(uint32_t READ_START_ADDR,u16 SizeOf_u32,uint32_t *DataAddress)
{
uint32_t Address;
u16 Remain_u32 = SizeOf_u32;
/* 檢查寫入的數據是否正確 */
Address = READ_START_ADDR;
while ((Remain_u32 > 0))
{
DataAddress[SizeOf_u32-Remain_u32] = (*(__IO uint32_t*) Address);
Address += 4;
Remain_u32--;
}
}
//注意事項:
//1、對flash進行寫入操作,一定要遵循“先擦除,後寫入”的原則
//2、注意到stm32內置flash的擦除操作都是以頁爲單位進行,而寫入操作則必須以16位半字寬度數據爲單位,允許跨頁寫,嘗試寫入非16位半字數據將導致stm32內部總線錯誤。
//3、進行stm32的內置flash編程操作時(寫或擦除),必須打開內部的RC振盪器(HSI)
//4、注意stm32的內置flash最多隻有10萬次重複擦寫的生命週期,謹記切勿在程序中放任死循環對flash進行持續地重複擦寫。