日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

c语言flash里能存文件吗,STM32内部FLASH打包读写

發布時間:2025/4/16 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言flash里能存文件吗,STM32内部FLASH打包读写 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近做到的項目在運行需要把一組uint8_t(unsigned char)的數據進行掉電儲存,想到單片機STM32f030f4p6內部flash可以直接由程序操作,寫了以下代碼用于uint8_t數據打包保存和讀取。

1、程序清單 與 測試結果

本程序包含5個文件,分別是:

1、Flash.c:內部flash讀取儲存相關函數

2、Flash.h:flash頭文件

3、USART1.c:STM32F030F4P6的串口驅動,串口僅用于打印數據觀察。

4、USART1.h:串口頭文件

5、main.c:防止程序主入口

1、Flash.c

?

View Code

2、Flash.h

?

View Code

3、USART1.c

?

View Code

4、USART1.h

?

View Code

5、main.c

?

View Code

測試結果:

第54-199省略..

2、程序詳解

2.1、內存結構:

STM32F0xx的flash結構如下:最多具有64頁,每頁1KByte大小。

我使用的STM32F030F4P6 flash區域有16K,所以實際上只有0-15頁,本程序中把需要保存的數據數據存放在最后一頁(第15頁)中。

2.2、定義數據包結構

為了保證儲存和讀出flash的數據是正確的,本程序將寫入flash數據分為3個區域

報頭區:寫入數據的時候,將第15頁的第1、2字節寫入0xaa55,在讀出的時候如果此位置不是0xaa55,則表示這段數據數據無效,不是由自己存入的數據或者程序出現了異常;

長度:寫入數據的時候,第15頁的第3、4字節寫入有效數據的長度,讀出這個字段,就知道上次自己一共存入了多少數據;

數據段:從第15頁的第5字節開始,全部字節(1020byte)用于儲存uint8_t類型的數據;

2.3、寫操作

寫操作有如下步驟:

保護:由于我們只有1Kbyte空間,出去4個字節的報頭和長度,實際只能存儲1020個u8類型,寫太多返回失敗。

解flash鎖

頁擦除

寫入數據包

上鎖

/*******************************************************************************

* Function Name : Flash_eeprom_WriteWithPacked

* Description : Write a group of datas to flash.

* Input : buff:pointer of first data, length: write length

* Output :

* Return : true/false

*******************************************************************************/

bool writeMessageToFlash( uint8_t *buff , uint16_t length)

{

uint16_t temp;

int i;

/*Protection*/

if( (length+4) > STM32F0xx_PAGE_SIZE )

{

return false;

}

FLASH_Unlock( );

/*Clear all flags*/

FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR );

/*Erase first . Do not rember.*/

if(FLASH_COMPLETE != FLASH_ErasePage(STM32F0xx_FLASH_PAGE15_STARTADDR))//°üo?á?μè′ybusy

{

return false;

}

/*Write head*/

FLASH_ProgramHalfWord( STM32F0xx_FLASH_PAGE15_STARTADDR, EEPPROM_PACKAGEHEAD );

/*Write length*/

FLASH_ProgramHalfWord( STM32F0xx_FLASH_PAGE15_STARTADDR+2 , length );

/*Write datas*/

for(i=0 ;i

{

temp = buff[2*i]|(uint16_t)buff[2*i+1]<<8;

FLASH_ProgramHalfWord( STM32F0xx_FLASH_PAGE15_STARTADDR+4+2*i , temp);

}

if( isItOddNumber(length) )//Write one more if length is odd number.

{

temp = (uint16_t)buff[length-1];

FLASH_ProgramHalfWord( STM32F0xx_FLASH_PAGE15_STARTADDR+4+(length-1) , temp);

}

/*Read out and check*/

for(i=0 ;i

{

if( *(uint8_t*)(STM32F0xx_FLASH_PAGE15_STARTADDR+4+i) != buff[i] )

{

FLASH_Lock();

return false;

}

}

FLASH_Lock();

return true;

}

2.3.1、解鎖操作:

用戶手冊描述如下:

在(芯片)重置過后,為了防止多余的擦寫操作flash會被保護。除了OBL_LAUNCH位用于重載option bit,FLASH_CR寄存器的其他部分都不可以訪問。

需要把以下兩個解鎖序列寫入FLASH_KEY寄存器,才能訪問FLASH_CR:

0x45670123

0xCDEF89AB

檢索官方庫定位FLASH_Unlock()這個函數,它的底層實現與文檔描述相符,另外增加了防止重復解鎖的操作,直接使用FLASH_Unlock()這個函數即可以完成解鎖。

2.3.2、頁擦除

用戶手冊描述如下:

1、通過檢查FLASH_SR寄存器的BSY位來確認flash沒有使用

2、把FLASH_CR寄存器的PER位置SET

3、通過編寫FLASH_AR寄存器來確認要擦除的頁

4、將FLASH_CR寄存器的STRT位置SET

5、等待BSY位rst

6、檢查FLASH_SR寄存器中的EOP標記(成功會置SET)(流程圖沒有、庫函數沒檢查)

7、清除EOP標記(流程圖沒有、庫函數沒清除)

檢索官方庫定位到FLASH_ErasePage(uint32_t Page_Address)這個函數,它的底層實現與文檔流程圖描述相符,值得注意的是,手冊描述中6、7步并沒有出現在手冊的流程圖和庫函數中(庫版本V1.2.0)。但在使用中沒有出現問題,這里先記錄看以后使用中會不會出現問題

2.3.3、往flash中寫入數據

用戶手冊描述如下

1、通過檢查FLASH_SR寄存器的BSY位來確認flash沒有使用

2、設置FLASH_CR寄存器的PG位

3、在目標地址上寫入半個word的數據

4、等BSY位reset

5、檢查FLASH_SR寄存器的EOP標記(SET表示成功)(流程圖沒有出現、庫函數中沒檢查)

檢索官方庫定位到FLASH_ErasePage(uint32_t Page_Address)這個函數,它的底層實現與文檔流程圖描述相符,同樣地,庫函數沒有檢查第五步的EOP標記

2.3.4、上鎖操作

根據手冊提示,定位到庫函數void FLASH_Lock(void)。只要置位LOCK位就上鎖了。

2.4、讀操作

程序如下

/*******************************************************************************

* Function Name : readPackedMessageFromFlash

* Description : Read packed message form flash

* Input : buff:point to first location of received buffer.length:Maxmum length of reception

* Output :

* Return : reception length

*******************************************************************************/

uint16_t readPackedMessageFromFlash( uint8_t *buff , uint16_t length)

{

int i;

uint16_t getLength;

if( !doseFlashHasPackedMessage() )

return 0;

/*Get valuable length*/

getLength = getValuablePackedMessageLengthofFlash();

/*Read out message*/

for(i=0;i

{

buff[i]= *(uint8_t*)(STM32F0xx_FLASH_PAGE15_STARTADDR+4+i);

}

return MIN(getLength,length);

}

根據用戶手冊提示,讀操作是可以直接取址的,所以讀操作實際只有如下一句只要用uint8_t類型取出目標地址再取值就可以了。

但是,我們的數據是打包的(詳見2.2),所以還需要:

1、根據報頭判斷是不是有效數據

2、根據長度判斷要讀取多少數據

3、最后才是讀出數據

2.4.1、判斷數據有效性:

我們通過報頭來判斷數據是不是自己寫入的。

也就是判斷flash第15頁的第1、2個字節是不是0xaa55,如果不是,那這段數據是無效的。

另外再判斷一下長度字段,如果長度等于0,也就是后面沒有數據,那這段數據也是無效的。

/*******************************************************************************

* Function Name : doseFlashHasPackedMessage

* Description : Does flash has packed messages

* Input : None

* Output :

* Return : ture/false

*******************************************************************************/

bool doseFlashHasPackedMessage(void)

{

uint16_t length;

uint16_t getHead;

/*Is head matched*/

getHead = (uint16_t)(*(uint16_t*)(STM32F0xx_FLASH_PAGE15_STARTADDR ));

if( EEPPROM_PACKAGEHEAD != getHead )

{

return false;

}

/*Is length zero*/

length = (*(uint16_t*)(STM32F0xx_FLASH_PAGE15_STARTADDR+2));

if( 0 == length)

{

return false;

}

return true;

}

2.4.2、根據長度讀出數據:

在讀Flash程序中,getLength是從flash中讀出的長度,length是我們指定的最大讀取長度。如果getLength大于我們指定讀取長度,很可能會造成溢出,所以兩者取小的一個防止溢出。

總結

以上是生活随笔為你收集整理的c语言flash里能存文件吗,STM32内部FLASH打包读写的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。