一般32位單片機的內部FALSH是不支持字節操作的,有的可以按字節讀取,但是不能按字節寫入。
而且,一般單片機內部FALSH擦除的最小單位都是頁,如果向某頁中的某個位置寫入數據,恰好這個位置的前面存了其他數據,那么就必須把這頁擦除,存的其他數據也會丟失。
實際上就是說內部的FALSH不好做改寫的操作,如果有很多數據需要存放,最好是分頁存儲。這也是FALSH與E2PROM最大的區別,后者支持按字節操作且無需擦除,即使某一個地址寫壞了,也不影響其他地址。
下面介紹一種方法讓內部FLASH“支持”字節操作,且同一頁的其他數據不受影響。
方法原理很簡單,下面簡單介紹下原理:
1.根據要寫入地址,計算出該地址位于哪一頁;
2.讀出整個頁,存入緩存BUF;
3.將要寫入的數據按位置更新到BUF中;
4.擦除該頁;
5.寫入整個BUF。
可以看出這種方法弊端很明顯:
1.耗時長 每次寫都要讀整個BUF,然后還要先把數據存到BUF里,然后再寫入整個BUF;
2.FALSH擦寫次數增加,降低使用壽命;
下面給出測試代碼:
#include
#include
#include //C語言標準庫
#include “flash.h”
#define USER_FLASH_START_ADDR 0x01070000 //FLASH最后兩個扇區 供用戶使用
u32tou8 u32data;//定義一個聯合體
//==================================================================================
// 獲取某個地址所在的頁首地址
// addr:FLASH地址
// 返回:該地址所在的頁 共128頁(0~127)
//==================================================================================
unsigned int FLASH_GetFlashPage(unsigned int addr)
{
if (IS_FLASH_ADDRESS(addr))
{
return (addr&(~0xFFF));//清0低12位就是該頁的起始地址
}
}
//==================================================================================
// 從FLASH中讀取 一個字(32位)
// addr:讀取地址
// 返回: 讀到的字數據
//備注: 地址為4字節對齊
//==================================================================================
unsigned int FLSAH_ReadWord(unsigned int addr)
{
return (*(unsigned int *)addr);
}
//==================================================================================
//從FLASH指定地址 讀取數據
//備注: 讀取數據類型為32位 讀取地址為4字節對齊
//==================================================================================
void FLASH_Read(unsigned int ReadAddr,unsigned char *pBuffer,unsigned int NumToRead)
{
unsigned int i;
u32tobyte cache;
for(i=0; iRO = 0;//去掉所有扇區寫保護
//==================================================================================
// 判斷寫入地址是否非法 起始地址或者結束地址不在FALSH范圍內則退出
//==================================================================================
if(!(IS_FLASH_ADDRESS(startaddr)&& IS_FLASH_ADDRESS(endaddr))) return FLASH_ERROR_PG;
while(startaddr remain)//需要寫入的數據量大于緩沖buf剩余字節數
{
for(i=index;i《4096;i++)//將需要寫入FALSH的數據寫入緩沖buff
{
buffer[i]=*(pBuffer++);
}
NumToWrite-=remain;//需要寫入的數據長度-本次已經寫入的數據長度
startaddr+=remain;//地址向后偏移本次寫入的字節數
}
else
{
for(i=index;i
其中還有個聯合體的定義:typedef union
{
unsigned int data;
unsigned char buf[4];
}
u32tou8;FLASH_ErasePage、FLASH_ProgramWord、IS_FLASH_ADDRESS 這三個都是單片機FLASH的庫函數各家單片機不同,但功能基本相同,這里不再提供源碼。最后提供以下兩個FLASH接口即可:FLASH_Write(unsigned int WriteAddr,unsigned char *pBuffer,unsigned int NumToWrite);
FLASH_Read(unsigned int ReadAddr,unsigned char *pBuffer,unsigned int NumToRead)演示:1.為方便查看結果,測試從0x1070FFC的位置開始寫入數據,FLASH地址分布如下圖所示:這里展示了FLASH連續兩頁的地址,首先將這兩頁全部擦除。
2.接著從1070FFC的位置開始寫入56個1,這樣就保證了數據跨越了1頁。unsigned char write[]= {“1111111111111111111111111111111111111111111111111111111111111111111111111111111111111”};
FLASH_Write(0x01070FFC,write,sizeof(write));
注意:最后的00是因為字符串的結尾字符是“/0”3.緊接著,在0x1070FFE位置寫入新的字符串,也要保證寫入長度跨越1頁。unsigned char write2[]={“23456789”};
FLASH_Write(0x01070FFE,write2,sizeof(write2));
可以看出,0x1070FFE~0x1071006的位置被寫入了新的字節,但這兩頁的其他位置數據保持不變。總結:1、實際使用時,如果不是受限于成本或者FLASH大小,不建議這樣讀寫內部FLASH,以為stm32內部FLASH也就10W次壽命,這樣頻繁擦寫會大大降低FLASH壽命。2、如果保存的數據不多,建議每個數據都單獨存1頁,這樣不用考慮擦除時會把其他數據也一并擦除。版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。本文鏈接:https://blog.csdn.net/qq_24835087/article/details/103541322審核編輯:何安
-
單片機
+關注
關注
6067文章
44952瀏覽量
648631 -
FlaSh
+關注
關注
10文章
1672瀏覽量
151281
發布評論請先 登錄
第二十九章 讀寫內部FLASH

請問flashdb的flash操作接口是否可以異步?
MCU片上Flash
調試時Memory窗口中Flash內容不更新的原因和解決辦法

存儲技術探秘 NAND Flash vs NOR Flash:藏在芯片里的"門道之爭"
cubeide的代碼怎么編譯到內部+外部FLASH里面去?
DLPDLCR4710EVM-G2是否可以在flash或內部存儲中設置投射的彩色圖像?
工業智能網關查詢flash的操作步驟

字節起訴前實習生篡改代碼案獲受理
tpl0102讀寫正常但是阻值沒變化是哪里的問題?
探索字節隊列的魔法:多類型支持、函數重載與線程安全

評論