STM32的内部Flash读写

本文详细介绍了STM32F103系列微控制器内部Flash的操作方法,包括清除标志、擦除页面及编程等核心函数的实现原理与使用流程。适用于所有STM32F10x设备。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内部Flash官方手册介绍

    STM官方关于stm32F103系列的芯片有一个专门介绍flash读写的手册。STM32F100xx超值型产品闪存编程手册

    通过J-Link查看自己的芯片内部的flash大小。我的大小为512k 是high-density

    

    手册中对应的内存表为:

    

相关库函数

在stm32f10x_flash.c文件中官方为我们定义好的很多关于内部flash操作的函数。

/**
  * @brief  Clears the FLASH's pending flags.
  * @note   This function can be used for all STM32F10x devices.
  *         - For STM32F10X_XL devices, this function clears Bank1 or Bank2’s pending flags
  *         - For other devices, it clears Bank1’s pending flags.
  * @param  FLASH_FLAG: specifies the FLASH flags to clear.
  *   This parameter can be any combination of the following values:         
  *     @arg FLASH_FLAG_PGERR: FLASH Program error flag       
  *     @arg FLASH_FLAG_WRPRTERR: FLASH Write protected error flag      
  *     @arg FLASH_FLAG_EOP: FLASH End of Operation flag           
  * @retval None
  */
void FLASH_ClearFlag(uint32_t FLASH_FLAG)
{
#ifdef STM32F10X_XL
  /* Check the parameters */
  assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)) ;

  if((FLASH_FLAG & 0x80000000) != 0x0)
  {
    /* Clear the flags */
    FLASH->SR2 = FLASH_FLAG;
  }
  else
  {
    /* Clear the flags */
    FLASH->SR = FLASH_FLAG;
  }  

#else
  /* Check the parameters */
  assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)) ;
  
  /* Clear the flags */
  FLASH->SR = FLASH_FLAG;
#endif /* STM32F10X_XL */
}
/**
  * @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;   //PERÖÃ1£¬Ñ¡ÔñÒ³²Á³ý²Ù×÷
    FLASH->AR = Page_Address; //Òª²Á³ýÒ³ËùÔÚµØÖ·
    FLASH->CR|= CR_STRT_Set;  // STRTλÖÃ1£¬Æô¶¯²Á³ý²Ù×÷
    
    /* 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  Programs a word at a specified address.
  * @note   This function can be used for all STM32F10x devices.
  * @param  Address: specifies the address to be programmed.
  * @param  Data: specifies the data to be programmed.
  * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
  *         FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. 
  */
FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)
{
  FLASH_Status status = FLASH_COMPLETE;
  __IO uint32_t tmp = 0;

  /* Check the parameters */
  assert_param(IS_FLASH_ADDRESS(Address));

#ifdef STM32F10X_XL
  if(Address < FLASH_BANK1_END_ADDRESS - 2)
  { 
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastBank1Operation(ProgramTimeout); 
    if(status == FLASH_COMPLETE)
    {
      /* if the previous operation is completed, proceed to program the new first 
        half word */
      FLASH->CR |= CR_PG_Set;
  
      *(__IO uint16_t*)Address = (uint16_t)Data;
      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastOperation(ProgramTimeout);
 
      if(status == FLASH_COMPLETE)
      {
        /* if the previous operation is completed, proceed to program the new second 
        half word */
        tmp = Address + 2;

        *(__IO uint16_t*) tmp = Data >> 16;
    
        /* Wait for last operation to be completed */
        status = FLASH_WaitForLastOperation(ProgramTimeout);
        
        /* Disable the PG Bit */
        FLASH->CR &= CR_PG_Reset;
      }
      else
      {
        /* Disable the PG Bit */
        FLASH->CR &= CR_PG_Reset;
       }
    }
  }
  else if(Address == (FLASH_BANK1_END_ADDRESS - 1))
  {
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastBank1Operation(ProgramTimeout);

    if(status == FLASH_COMPLETE)
    {
      /* if the previous operation is completed, proceed to program the new first 
        half word */
      FLASH->CR |= CR_PG_Set;
  
      *(__IO uint16_t*)Address = (uint16_t)Data;

      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastBank1Operation(ProgramTimeout);
      
	  /* Disable the PG Bit */
      FLASH->CR &= CR_PG_Reset;
    }
    else
    {
      /* Disable the PG Bit */
      FLASH->CR &= CR_PG_Reset;
    }

    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastBank2Operation(ProgramTimeout);

    if(status == FLASH_COMPLETE)
    {
      /* if the previous operation is completed, proceed to program the new second 
      half word */
      FLASH->CR2 |= CR_PG_Set;
      tmp = Address + 2;

      *(__IO uint16_t*) tmp = Data >> 16;
    
      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
        
      /* Disable the PG Bit */
      FLASH->CR2 &= CR_PG_Reset;
    }
    else
    {
      /* Disable the PG Bit */
      FLASH->CR2 &= CR_PG_Reset;
    }
  }
  else
  {
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastBank2Operation(ProgramTimeout);

    if(status == FLASH_COMPLETE)
    {
      /* if the previous operation is completed, proceed to program the new first 
        half word */
      FLASH->CR2 |= CR_PG_Set;
  
      *(__IO uint16_t*)Address = (uint16_t)Data;
      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
 
      if(status == FLASH_COMPLETE)
      {
        /* if the previous operation is completed, proceed to program the new second 
        half word */
        tmp = Address + 2;

        *(__IO uint16_t*) tmp = Data >> 16;
    
        /* Wait for last operation to be completed */
        status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
        
        /* Disable the PG Bit */
        FLASH->CR2 &= CR_PG_Reset;
      }
      else
      {
        /* Disable the PG Bit */
        FLASH->CR2 &= CR_PG_Reset;
      }
    }
  }
#else
  /* Wait for last operation to be completed */
  status = FLASH_WaitForLastOperation(ProgramTimeout);
  
  if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to program the new first 
    half word */
    FLASH->CR |= CR_PG_Set;
  
    *(__IO uint16_t*)Address = (uint16_t)Data;
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation(ProgramTimeout);
 
    if(status == FLASH_COMPLETE)
    {
      /* if the previous operation is completed, proceed to program the new second 
      half word */
      tmp = Address + 2;

      *(__IO uint16_t*) tmp = Data >> 16;
    
      /* Wait for last operation to be completed */
      status = FLASH_WaitForLastOperation(ProgramTimeout);
        
      /* Disable the PG Bit */
      FLASH->CR &= CR_PG_Reset;
    }
    else
    {
      /* Disable the PG Bit */
      FLASH->CR &= CR_PG_Reset;
    }
  }         
#endif /* STM32F10X_XL */
   
  /* Return the Program Status */
  return status;
}

Flash读写函数的实现

    这里用的基地址为0x0807 F800

#include "stm32f10x_flash.h"
#define START_ADDR 0x0807F800

void FLASH_WriteByte(u32 addr,uint32_t Data)
{
	
	FLASH_Status FLASHstatus = FLASH_COMPLETE;
	FLASH_Unlock();
	FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR); 
 FLASHstatus=FLASH_ErasePage(START_ADDR);
	if(FLASHstatus == FLASH_COMPLETE)
	{
		FLASHstatus = FLASH_ProgramWord(START_ADDR+addr*2, Data);
	}
	FLASH_Lock();
}



uint32_t FlashRead(uint32_t addr, uint8_t *buffer, uint32_t length)  
{  
  memcpy(buffer, (void *)(START_ADDR + addr*2), length);  
  
  return length;  
}  






### STM32 内部 Flash 读写教程 对于STM32系列微控制器而言,内部Flash的操作是一项基本技能,在开发过程中扮演着重要角色。下面将详细介绍如何利用STM32F103C8T6进行内部Flash读写操作。 #### 准备工作 为了便于理解与实践,建议先获取一份官方提供的示例代码[^1]。这份资料不仅涵盖了完整的工程文件,还附带详细的文档指导,有助于初学者快速入门。按照指引完成资源下载、解压以及项目导入至开发环境(如STM32CubeIDE或Keil),之后便可以着手编写具体的读写逻辑了。 #### 定义常量与变量 在执行任何I/O之前,需定义好待处理的数据及其目标位置: ```c // 需要被写入到STM32 FLASH的内容 const uint8_t TEXT_Buffer[] = "STM32 FLASH TEST"; #define BUFFER_SIZE sizeof(TEXT_Buffer) // 设置FLASH保存地址(注意:此地址应为偶数值,并且大于当前应用程序占用的空间加上基址) #define FLASH_SAVE_ADDR 0x08020000UL ``` 上述代码片段中声明了一个字符数组`TEXT_Buffer`用于存储想要记录的信息;同时设定了一个宏定义来指定数据最终存放的位置——即`FLASH_SAVE_ADDR`。这里特别强调的是,所选地址应当满足特定条件以确保不会覆盖已有程序或其他敏感信息。 #### 实现写入函数 接下来展示一段简单的写入流程实现方式: ```c HAL_StatusTypeDef WriteToInternalFlash(uint32_t address, const uint16_t* data, size_t length){ HAL_FLASH_Unlock(); // 解锁Flash编程/擦除权限 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR); while(length--){ if(HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, *data)){ HAL_FLASH_Lock(); return HAL_ERROR; } address += 2; // 移动到下一个半字单元 ++data; } HAL_FLASH_Lock(); // 锁定Flash编程/擦除权限 return HAL_OK; } ``` 这段函数接收三个参数分别是目的地址(`address`)、源数据指针(`data`)及传输长度(`length`)。它会依次遍历输入缓冲区内的每一个元素并将它们逐个写入到指定的目标区域内直到全部完成为止。值得注意的是每次调用前都需要解除保护状态以便允许后续动作的发生;而在结束之时则重新加回锁定机制防止意外发生。 #### 执行读取过程 相比之下,从内建闪存里提取已有的内容就显得更加直观一些: ```c void ReadFromInternalFlash(uint32_t address, uint16_t* buffer, size_t length){ volatile uint16_t* flash_ptr = (volatile uint16_t*)address; for(size_t i=0 ;i<length;i++){ *(buffer+i) = *flash_ptr++; } } ``` 此处采用了一种较为直接的方法来进行批量加载:通过创建一个新的指向给定偏移处的临时指针对象,随后循环迭代直至达到预期的数量限制。由于整个过程仅涉及内存间的复制活动而无需额外请求硬件支持因此效率较高同时也减少了可能出现错误的概率。 #### 测试验证 最后一步就是检验先前所做的改动是否正确无误。可以通过比较原始字符串同新获得的结果之间是否存在差异来做初步判断: ```c int main(void){ /* 初始化系统 */ SystemClock_Config(); /* ...其他初始化... */ static uint16_t readBuffer[BUFFER_SIZE / 2]; // 清空缓存以防干扰测试结果 memset(readBuffer, 0xFF, BUFFER_SIZE); // 尝试向预设地点写入消息 if(HAL_OK == WriteToInternalFlash(FLASH_SAVE_ADDR, (uint16_t*)TEXT_Buffer, BUFFER_SIZE / 2)){ // 成功后尝试从中恢复出来看看能否匹配原样 ReadFromInternalFlash(FLASH_SAVE_ADDR, readBuffer, BUFFER_SIZE / 2); // 输出对比情况... }else{ // 处理失败情形... } /* 主循环体 */ while (1){} } ``` 以上便是关于STM32内部Flash读写的简明指南,希望能够帮助读者建立起对该主题的基础认知并为进一步探索打下良好基础。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值