STM32筆記之 FLASH(內存)

寫在前面:
本文章旨在總結備份、方便以後查詢,由於是個人總結,如有不對,歡迎指正;另外,內容大部分來自網絡、書籍、和各類手冊,如若侵權請告知,馬上刪帖致歉。

 

目錄

一、內存大小

二、STM32F103xx系列內存大小

三、閃存概述

四、寫和擦除閃存

五、讀操作

六、總代碼實現


 

一、內存大小

內存的容量一般都是 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 ----------------------------*/


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章