寫在前面:
本文章旨在總結備份、方便以後查詢,由於是個人總結,如有不對,歡迎指正;另外,內容大部分來自網絡、書籍、和各類手冊,如若侵權請告知,馬上刪帖致歉。
目錄
一、內存大小
內存的容量一般都是 2的整次方倍,系統對內存的識別是以Byte(字節)爲單位,每個字節由 8位二進制數組成,即 8bit(比特,也稱“位”)。按照計算機的二進制方式,1Byte=8bit;1KB=1024Byte;1MB=1024KB;1GB=1024MB;1TB=1024GB。
除了字節,還有 “ 位 ” 和 “ 字長 ” 這些單位
- 位(Bit) :最小的存儲單位(可以容納0和1其中之一)
- 字節 (Byte):常用的計算機存儲單位。1字節 = 8 位(這是字節的標準定義)
- 字(word) :即機器字長,是自然的存儲單位。計算機是多少位的,一個字就有多少位。(如64位的機器,一個機器字長就是64位)
如果是一臺 16位機,它的 1個字就由 2個字節構成,字長爲 16位; 字長的長度是不固定的,對於不同的 CPU,字長的長度也不一樣的;而 STM32是 32位機,所以它的 1個字就相當於 4個字節,那半個字(即字長大小的一半)爲 2個字節(16 Bit)
二、STM32F103xx系列內存大小
更多的內存查看可以在選型手冊中查找 STM32&STM8選型手冊(pdf文檔)
三、閃存概述
在 STM32F103xx系列中有高達512K字節的內置閃存存儲器,用於存放程序和數據。因此,根據實際代碼大小,我們可以利用剩下的內存對 Flash進行編程來存儲一些特定的數據(例如:密碼,專用的 ID碼等),也可以用來模擬 EEPROM的使用
特性:
1、小容量
2、中容量
3、大容量
4、互聯網型
更多詳細的介紹可以看 STM32F10xxx閃存編程手冊
四、寫和擦除閃存
在執行閃存寫(或擦除)操作時,任何對閃存的讀操作都會鎖住總線,在寫(或擦除)操作完成後讀操作才能正確地進行;既在進行寫(或擦除)操作時,不能進行代碼或數據的讀取操作。
進行閃存編程操作時(寫或擦除),必須打開內部的 RC振盪器(HSI)。
閃存存儲器可以用 ICP或 IAP方式編程。
1、寫操作
閃存編程一次可以支持寫入16位(半字)。
流程圖:
代碼實現:
/************************************************
函數名稱 : Flash_WritenHalfWord
功 能 : 向 Flash寫半個字(16 bit)
參 數 : address ---- 地址位
Buff ---- 存儲的數據
Len ---- 長度
返 回 值 : 0 / 1
*************************************************/
uint8_t Flash_WritenHalfWord( uint32_t addr, uint8_t *Buff, uint16_t Len )
{
volatile FLASH_Status FLASHStatus;
uint8_t k = 0;
uint32_t Address;
Address = WRITE_START_ADDR + addr;
FLASHStatus = FLASH_COMPLETE;
FLASH_Unlock(); //解鎖
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);//清除所有標誌
FLASHStatus = FLASH_ErasePage(Address); //扇區擦除
if(FLASHStatus == FLASH_COMPLETE)
{
for(k = 0;(k<Len) && (FLASHStatus == FLASH_COMPLETE);k++)
{
FLASHStatus = FLASH_ProgramHalfWord(Address, *(Buff + k)); //寫入半個字(16位)的數據入指定地址
Address = Address + 2; //地址偏移 2個字節
}
FLASH_Lock(); //重新上鎖,防止誤寫入
}
else
{
return 0;
}
if(FLASHStatus == FLASH_COMPLETE)
{
return 1;
}
return 0;
}
2、擦除操作
閃存擦除操作可以按頁面擦除或完全擦除(全擦除);全擦除不影響信息塊。 爲了確保不發生過度編程, 閃存編程和擦除控制器塊是由一個固定的時鐘控制的。 寫操作(編程或擦除)結束時可以觸發中斷。僅當閃存控制器接口時鐘開啓時,此中斷可以用來從WFI模式退出。
①頁擦除流程圖:
代碼實現(官方封裝的):
/**
* @brief Erases a specified FLASH page.
* @note This function can be used for all STM32F10x devices.
* @param Page_Address: The page address to be erased.
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ErasePage(uint32_t Page_Address) // 頁檫除
{
FLASH_Status status = FLASH_COMPLETE;
/* Check the parameters */
assert_param(IS_FLASH_ADDRESS(Page_Address));
#ifdef STM32F10X_XL
if(Page_Address < FLASH_BANK1_END_ADDRESS)
{
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase the page */
FLASH->CR|= CR_PER_Set;
FLASH->AR = Page_Address;
FLASH->CR|= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
/* Disable the PER Bit */
FLASH->CR &= CR_PER_Reset;
}
}
else
{
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase the page */
FLASH->CR2|= CR_PER_Set;
FLASH->AR2 = Page_Address;
FLASH->CR2|= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(EraseTimeout);
/* Disable the PER Bit */
FLASH->CR2 &= CR_PER_Reset;
}
}
#else
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase the page */
FLASH->CR|= CR_PER_Set;
FLASH->AR = Page_Address;
FLASH->CR|= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
/* Disable the PER Bit */
FLASH->CR &= CR_PER_Reset;
}
#endif /* STM32F10X_XL */
/* Return the Erase Status */
return status;
}
②全擦除流程圖:
代碼實現(也是官方封裝的):
/**
* @brief Erases all FLASH pages.
* @note This function can be used for all STM32F10x devices.
* @param None
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_EraseAllPages(void) // 全擦除
{
FLASH_Status status = FLASH_COMPLETE;
#ifdef STM32F10X_XL
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase all pages */
FLASH->CR |= CR_MER_Set;
FLASH->CR |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
/* Disable the MER Bit */
FLASH->CR &= CR_MER_Reset;
}
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase all pages */
FLASH->CR2 |= CR_MER_Set;
FLASH->CR2 |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(EraseTimeout);
/* Disable the MER Bit */
FLASH->CR2 &= CR_MER_Reset;
}
#else
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase all pages */
FLASH->CR |= CR_MER_Set;
FLASH->CR |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
/* Disable the MER Bit */
FLASH->CR &= CR_MER_Reset;
}
#endif /* STM32F10X_XL */
/* Return the Erase Status */
return status;
}
五、讀操作
內置閃存模塊可以在通用地址空間直接尋址,任何32位數據的讀操作都能訪問閃存模塊的內容並得到相應的數據。
代碼實現:
/************************************************
函數名稱 : Flash_ReadHalfWord
功 能 : 從 Flash連續讀半個字(16 bit)
參 數 : address ---- 地址位
Buff ---- 讀取的數據
Len ---- 長度
返 回 值 : 無
*************************************************/
void Flash_ReadHalfWord( uint32_t addr, uint8_t *Buff, uint16_t Len )
{
uint8_t k;
uint32_t Address;
Address = WRITE_START_ADDR + addr;
for(k = 0;k < Len;k++)
{
*(Buff + k) = (*(vu32*) Address); //讀指定地址的半個字的數據
Address += 2; //地址偏移 2個字節
}
}
/************************************************
函數名稱 : ReadFlash_HalfWord
功 能 : 從 Flash讀半個字(16 bit)
參 數 : address ---- 地址位
Buff ---- 讀取的數據
Len ---- 長度
返 回 值 : 無
*************************************************/
uint16_t ReadFlash_HalfWord( uint32_t addr )
{
uint32_t Address;
Address = WRITE_START_ADDR + addr;
return (*(vu16*) Address); //讀指定地址的半個字的數據
}
六、總代碼實現
bsp_flash.c 源文件
#include "bsp_flash.h"
/************************************************
函數名稱 : Flash_ReadHalfWord
功 能 : 從 Flash連續讀半個字(16 bit)
參 數 : address ---- 地址位
Buff ---- 讀取的數據
Len ---- 長度
返 回 值 : 無
*************************************************/
void Flash_ReadHalfWord( uint32_t addr, uint8_t *Buff, uint16_t Len )
{
uint8_t k;
uint32_t Address;
Address = WRITE_START_ADDR + addr;
for(k = 0;k < Len;k++)
{
*(Buff + k) = (*(vu32*) Address); //讀指定地址的半個字的數據
Address += 2; //地址偏移 2個字節
}
}
/************************************************
函數名稱 : Flash_WritenHalfWord
功 能 : 向 Flash寫半個字(16 bit)
參 數 : address ---- 地址位
Buff ---- 存儲的數據
Len ---- 長度
返 回 值 : 0 / 1
*************************************************/
uint8_t Flash_WritenHalfWord( uint32_t addr, uint8_t *Buff, uint16_t Len )
{
volatile FLASH_Status FLASHStatus;
uint8_t k = 0;
uint32_t Address;
Address = WRITE_START_ADDR + addr;
FLASHStatus = FLASH_COMPLETE;
FLASH_Unlock(); //解鎖
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);//清除所有標誌
FLASHStatus = FLASH_ErasePage(Address); //扇區擦除
if(FLASHStatus == FLASH_COMPLETE)
{
for(k = 0;(k<Len) && (FLASHStatus == FLASH_COMPLETE);k++)
{
FLASHStatus = FLASH_ProgramHalfWord(Address, *(Buff + k)); //寫入半個字(16位)的數據入指定地址
Address = Address + 2; //地址偏移 2個字節
}
FLASH_Lock(); //重新上鎖,防止誤寫入
}
else
{
return 0;
}
if(FLASHStatus == FLASH_COMPLETE)
{
return 1;
}
return 0;
}
/************************************************
函數名稱 : ReadFlash_HalfWord
功 能 : 從 Flash讀半個字(16 bit)
參 數 : address ---- 地址位
Buff ---- 讀取的數據
Len ---- 長度
返 回 值 : 無
*************************************************/
uint16_t ReadFlash_HalfWord( uint32_t addr )
{
uint32_t Address;
Address = WRITE_START_ADDR + addr;
return (*(vu16*) Address); //讀指定地址的半個字的數據
}
/*---------------------------- END OF FILE ----------------------------*/
bsp_flash.h 頭文件
#ifndef __BSP_FLASH_H
#define __BSP_FLASH_H
#include "stm32f10x.h"
/* STM32大容量產品每頁大小2KByte,中、小容量產品每頁大小1KByte */
#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) || defined (STM32F10X_XL)
#define FLASH_PAGE_SIZE ((uint16_t)0x800) //2048
#else
#define FLASH_PAGE_SIZE ((uint16_t)0x400) //1024
#endif
// 寫入的起始地址與結束地址
#define WRITE_START_ADDR ((uint32_t)0x08008000)
#define WRITE_END_ADDR ((uint32_t)0x0801FC00)
void Flash_ReadHalfWord( uint32_t addr, uint8_t *Buff, uint16_t Len );
uint8_t Flash_WritenHalfWord( uint32_t addr, uint8_t *Buff, uint16_t Len );
uint16_t ReadFlash_HalfWord( uint32_t addr );
#endif /* __BSP_FLASH_H */
/*---------------------------- END OF FILE ----------------------------*/