STM32的FLASH是用來存儲主程序的,ST公司為了節約成本,沒有加入 EEPROM,但是許多場合下我們需要用EEPROM;不過FLASH的容量還是可觀的,我們可以利用FLASH模擬EEPROM。
根據《STM32F10X閃存編程》中的介紹,FLASH除了保存用戶代碼的部分,其余部分我們是可以利用其作為數據存儲使用的。stm32的FLASH分為主存儲塊和信息塊。主存儲塊用于保存具體的程序代碼和用戶數據,信息塊用于負責由stm32出廠是放置2KB的啟動程序(Bootloader)并鎖死,用戶無法更改。選項字節存儲芯片的配置信息及對主存儲塊的保護信息。STM32的FLASH主存儲塊按頁組織,有的產品每頁1KB,有的產品每頁2KB。頁面典型的用途就是用于按頁擦除FLASH。從這點來看,頁面有點像通用FLASH的扇區。
通常情況下程序也不會把FLASH寫滿;在沒滿的時候我們可以把最后一或兩頁用來模擬EEPROM;這樣我們就可以不用在外部另外來加EEPROM了。下面是STM32F103中文手冊關于FLASH的截圖;由于我用的是STM32C8T6做的實驗;手冊中沒有給STM32C8T6的FLASH的地址信息,容量是64K,可以算出第63頁地址是0X800FC00-0X800FFFF。
由于太晚了直接上代碼:
頭文件:
#ifndef __ST_FLASH_H
#define __ST_FLASH_H
/**@file StFlash.h
*@brief stm32 flash的讀寫操作
* 使用:
* * 此文件主要是針對STM32F103系列的芯片,注意不同容量大小的芯片的地址范圍不一樣
* * 使用Read和Write函數進行讀寫,具體參數和返回值見函數說明
* * 可以利用flash模擬EEPROM使用
*
*@author DHS(746769845@qq.com)
*
*/
#include "stm32f10x.h"
#include "stm32f10x_flash.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////
//用戶根據自己的需要設置
#define STM32_FLASH_SIZE 64 //所選STM32的FLASH容量大小(單位為K)
#define STM32_FLASH_WREN 1 //使能FLASH寫入(0,不是能;1,使能)
//////////////////////////////////////////////////////////////////////////////////////////////////////
#if STM32_FLASH_SIZE<256
#define STM_SECTOR_SIZE 1024 //字節
#else
#define STM_SECTOR_SIZE 2048
#endif
//FLASH起始地址
#define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址
//FLASH解鎖鍵值
class STFLASH
{
private:
bool mUseHalfWord;//
uint32_t mStartAddress;//
public:
STFLASH(uint32_t startAddress=(0x08000000+1000),bool useHalfWord=true);
//讀取指定地址的半字(16位數據)
//faddr:讀地址(此地址必須為2的倍數!!)
//返回值:對應數據.
u16 ReadHalfWord(u32 faddr);
//WriteAddr:起始地址
//pBuffer:數據指針
//NumToWrite:半字(16位)數
void Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite) ;
//從指定地址開始寫入指定長度的數據
//WriteAddr:起始地址(此地址必須為2的倍數!!)
//pBuffer:數據指針
//NumToWrite:半字(16位)數(就是要寫入的16位數據的個數.)
void Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite);
//從指定地址開始讀出指定長度的數據
//ReadAddr:起始地址
//pBuffer:數據指針
//NumToWrite:半字(16位)數
void Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead) ;
};
#endif
程序文件:
#include "StFlash.h"
/**@file StFlash.h
*@brief stm32 flash的讀寫操作
* 使用:
* * 此文件主要是針對STM32F103系列的芯片,注意不同容量大小的芯片的地址范圍不一樣
* * 使用Read和Write函數進行讀寫,具體參數和返回值見函數說明
* * 可以利用flash模擬EEPROM使用
*
*@author DHS(746769845@qq.com)
*
*/
u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];//最多是2K字節
STFLASH::STFLASH(uint32_t startAddress,bool useHalfWord)
{
if(startAddress%STM_SECTOR_SIZE!=0)//不是頁的開始,將開始處設置為下一個頁開始的地方
startAddress+=(STM_SECTOR_SIZE-(startAddress%STM_SECTOR_SIZE));
mStartAddress=startAddress;
mUseHalfWord=useHalfWord;
}
//讀取指定地址的半字(16位數據)
//faddr:讀地址(此地址必須為2的倍數!!)
//返回值:對應數據.
u16 STFLASH:: ReadHalfWord(u32 faddr)
{
return *(vu16*)faddr;
}
//WriteAddr:起始地址
//pBuffer:數據指針
//NumToWrite:半字(16位)數
void STFLASH::Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
{
u16 i;
for(i=0;i { FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]); WriteAddr+=2;//地址增加2. } } //從指定地址開始寫入指定長度的數據 //WriteAddr:起始地址(此地址必須為2的倍數!!) //pBuffer:數據指針 //NumToWrite:半字(16位)數(就是要寫入的16位數據的個數.) void STFLASH::Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite) { u32 secpos; //扇區地址 u16 secoff; //扇區內偏移地址(16位字計算) u16 secremain; //扇區內剩余地址(16位字計算) u16 i; u32 offaddr; //去掉0X08000000后的地址 if(WriteAddr FLASH_Unlock(); //解鎖 offaddr=WriteAddr-STM32_FLASH_BASE; //實際偏移地址. secpos=offaddr/STM_SECTOR_SIZE; //扇區地址 0~127 for STM32F103RBT6 secoff=(offaddr%STM_SECTOR_SIZE)/2; //在扇區內的偏移(2個字節為基本單位.) secremain=STM_SECTOR_SIZE/2-secoff; //扇區剩余空間大小 if(NumToWrite<=secremain)secremain=NumToWrite;//不大于該扇區范圍 while(1) { Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//讀出整個扇區的內容 for(i=0;i { if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除 } if(i { FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除這個扇區 for(i=0;i { STMFLASH_BUF[i+secoff]=pBuffer[i]; } Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//寫入整個扇區 }else Write_NoCheck(WriteAddr,pBuffer,secremain);//寫已經擦除了的,直接寫入扇區剩余區間. if(NumToWrite==secremain)break;//寫入結束了 else//寫入未結束 { secpos++; //扇區地址增1 secoff=0; //偏移位置為0 pBuffer+=secremain; //指針偏移 WriteAddr+=secremain; //寫地址偏移 NumToWrite-=secremain; //字節(16位)數遞減 if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一個扇區還是寫不完 else secremain=NumToWrite;//下一個扇區可以寫完了 } }; FLASH_Lock();//上鎖 } //從指定地址開始讀出指定長度的數據 //ReadAddr:起始地址 //pBuffer:數據指針 //NumToWrite:半字(16位)數 void STFLASH::Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead) { u16 i; for(i=0;i { pBuffer[i]=ReadHalfWord(ReadAddr);//讀取2個字節. ReadAddr+=2;//偏移2個字節. } } main文件: #include "stm32f10x.h" #include "StFlash.h"/要寫入到STM32 FLASH的字符串數組 const u8 TEXT_Buffer[]={"Flash_test"}; #define SIZE sizeof(TEXT_Buffer) //數組長度 #define FLASH_SAVE_ADDR 0X0800FC00 //設置FLASH 保存地址(必須為偶數,且其值要大于本代碼所占用FLASH的大小+0X08000000) u8 datatemp[SIZE]; STFLASH flash1;// int main() { SysTick_Config(72000); flash1.Write(FLASH_SAVE_ADDR,(u16*)TEXT_Buffer,SIZE);//寫數據,第一次下載程序到32,第二次注釋掉此行,斷電重新編譯下載 //keil watch查看datatemp數組的數據正是之前寫進去的數據 flash1.Read(FLASH_SAVE_ADDR,(u16*)datatemp,SIZE);//讀數據 while(1) { } }
上一篇:J-Link燒寫STM32失敗的問題
下一篇:使用IAR+Jlink開發STM32關于下載Flash的一點發現
推薦閱讀
史海拾趣
隨著產品線的不斷豐富,Compostar Technology Co Ltd開始積極尋求市場拓展。公司通過與國內外知名電子品牌建立戰略合作關系,成功將產品打入國際市場。同時,公司還積極參加各類行業展會和技術交流會,與業界同行建立了廣泛的聯系。這些努力不僅為公司帶來了更多的商機,也進一步提升了公司的知名度和影響力。
1995年,皮埃爾·奧米迪亞(Pierre Omidyar)以AuctionWeb的名字推出了eBay,最初只是一個在線拍賣個人物品的平臺。隨著互聯網的普及和用戶對在線交易需求的增長,eBay迅速吸引了大量用戶。其獨特的商業模式和用戶友好的界面使eBay成為在線拍賣市場的領軍者。1998年,eBay成功上市,成為當時最成功的互聯網公司之一。
1982年,Fabrimex AG收購了瑞士領先的實驗室電源制造商Erlenbach的K. Witmer Elektronik AG博士。這一收購不僅增強了公司在實驗室電源領域的實力,還進一步鞏固了其在電子行業中的地位。通過整合雙方的技術和資源,Fabrimex AG在實驗室電源領域取得了更高的市場份額和更廣泛的客戶認可。
在2015年,跨境銀行間支付清算有限責任公司(CIPS Co., Ltd.)正式成立,并隨之推出了人民幣跨境支付系統(CIPS)。這一系統的誕生,標志著中國電子支付行業在跨境支付領域邁出了堅實的一步。CIPS系統的建立,不僅滿足了國內外金融機構對高效、安全、便捷的跨境支付服務的需求,更為人民幣國際化進程提供了有力支持。
在光電技術領域,AOTC始終保持領先地位。公司不斷推出創新產品,如高效能的光電傳感器、智能照明系統等,這些產品不僅提升了人們的生活品質,還推動了整個電子行業的變革。AOTC的技術創新得到了業界的廣泛認可,公司逐漸成為了行業的領軍企業。
ETI Systems一直將產品品質視為企業的生命線。公司嚴格把控從原材料采購到產品生產的每一個環節,確保每一件產品都符合高標準的質量要求。正是這種對品質的執著追求,讓ETI Systems的產品在市場上贏得了良好的口碑和廣泛的認可。同時,公司也建立了完善的售后服務體系,為客戶提供及時、專業的技術支持和解決方案。
一、概況 韓國通信開展ADSL業務的主要原因是由于激烈的市場競爭。由于電信業務完全放開,除韓國通信之外,還有不少寬帶業務提供商也在提供電信業務。當韓國通信還在推廣ISDN業務時,一些CATV公司已利用CableModem占去了不少寬帶Internet接入市場。 ...… 查看全部問答∨ |
MFC requires WINVER to be #defined to 0x0400 or greater 項目建立的時候是wm5.0,后來選擇別的模擬器,編譯的時候出現“MFC requires WINVER to be #defined to 0x0400 or greater”,應該如何解決?… 查看全部問答∨ |
條碼手持終端開發工程師 1. 2名,大專以上學歷; 2. 了解制造業物流業務和條碼/RFID技術,有倉庫和生產線條碼/RFID手持終端開發經驗。 3. 熟悉C#語言編程 ...… 查看全部問答∨ |
熱光源:利用熱能激發的光源,如白熾燈在3,000-4,000K溫度時熱輻射發光。白熾燈有80-90%的能量轉換能熱能,10%左右的能量轉換為光能。因此發光效率較低。我們不是根據燈具外殼的溫度來定義為冷光源,還是熱光源。燈具週邊的溫度高低,只能評判 ...… 查看全部問答∨ |
轉貼自:http://www.2cto.com/os/201108/98426.html init的進程號是1(ps -aux | less),從這一點就能看出,init進程是系統所有進程的起點,Linux在完成核內引導以后,就開始運行init程序。 init程序需要讀取配置文件/etc/ini ...… 查看全部問答∨ |
|
有一塊別人用過的LaunchPad,第一次插上電腦,就LED0閃了一下,然后就滅了,其他LED都沒亮,不知怎么回事。電腦也一點反應都沒有。 用自己新的LaunchPad,第一次插上就很正常,LED0亮,LED1和LED2交替閃爍。 想求助 ...… 查看全部問答∨ |
|
《ADI有獎下載 — 太陽能光伏發電解決方案》中的文章,提到幾款ADI很有特色的電路: AD7401 AD7401A是一款二階Σ-Δ調制器,片上的數字隔離采用ADI公司的iCoupler®技術,能將模擬輸入信號轉換為高速1bit數據流。AD7401A采用5V電 ...… 查看全部問答∨ |
【TI首屆低功耗設計大賽】sacq的金剛狼(2):重裝IAR (1)IDE真的要升嗎 打開金剛狼開發板的盒子,首先看到的是黃色項目的標簽——提醒更新到最新版的IDE 開發環境IDE用什么呢,CCS 還是IAR? 個人選擇了已經是稍微熟悉點的IAR。 以前玩過430G2,裝過IAR5.4。 這次到手的金剛狼是430FR5969, ...… 查看全部問答∨ |