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 ----------------------------*/


发布了48 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_42992084/article/details/104113132