stm32f103zet6如何识别flash大小

发布时间:2023-10-20  

  在我们应用开发时,经常会有一些程序运行参数需要保存,如一些修正系数。这些数据的特点是:数量少而且不需要经常修改,但又不能定义为常量,因为每台设备可能不一样而且在以后还有修改的可能。将这类数据存在指定的位置,需要修改时直接修改存储位置的数值,需要使用时则直接读取,会是一种方便的做法。考虑到这些数据量比较少,使用专门的存储单元既不经济,也没有必要,而STM32F103内部的Flash容量较大,而且ST的库函数中还提供了基本的Flash操作函数,实现起来也比较方便。


  以大容量产品STM32F103ZET为例,其Flash容量达到512K,可以将其中一部分用作数据存储。如下是大容量的Flash组织模式:  stm32f103zet6如何识别flash大小

  STM32的闪存模块由:主存储器、信息块和闪存存储器接口寄存器等 3 部分组成。

  1)主存储器,该部分用来存放代码和数据常数(如 const 类型的数据)。对于大容量产品,其被划分为 256 页,每页 2K 字节。注意,小容量和中容量产品则每页只有 1K 字节。从上图可以看出主存储器的起始地址就是0X08000000, B0、B1 都接 GND 的时候,就是从 0X08000000开始运行代码的。

  2)信息块,该部分分为 2 个小部分,其中启动程序代码,是用来存储 ST 自带的启动程序,用于串口下载代码,当 B0 接 V3.3,B1 接 GND 的时候,运行的就是这部分代码。用户选择字节,则一般用于配置写保护、读保护等功能,本章不作介绍。

  3)闪存存储器接口寄存器,该部分用于控制闪存读写等,是整个闪存模块的控制机构。对主存储器和信息块的写入由内嵌的闪存编程/擦除控制器(FPEC)管理;编程与擦除的高电压由内部产生。

  在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后读操作才能正确地进行;既在进行写或擦除操作时,不能进行代码或数据的读取操作。

  根据上面的Flash组织模式,我们可以根据自己的使用方便来作相应的定义。因为大容量每个扇区定义为2K,而小容量和中容量都定义为1K,所以我们做如下宏定义:

  #define FLASH_SIZE 512 //所选MCU的FLASH容量大小(单位为K)

  #if FLASH_SIZE《256

  #define SECTOR_SIZE 1024 //字节#else

  #define SECTOR_SIZE 2048 //字节#endif

  虽然ST的库函数比较全面,但都是基本操作,为了使用方面,根据我们自己的需要对其进行再次封装。

  对于读操作相对比较简单,内置闪存模块可以在通用地址空间直接寻址,就像读取变量一样。

  //从指定地址开始读取多个数据void FLASH_ReadMoreData(uint32_t startAddress,uint16_t *readData,uint16_t countToRead)

  {

  uint16_t dataIndex;

  for(dataIndex=0;dataIndex《countToRead;dataIndex++)

  {

  readData[dataIndex]=FLASH_ReadHalfWord(startAddress+dataIndex*2);

  }

  }

  //读取指定地址的半字(16位数据)uint16_t FLASH_ReadHalfWord(uint32_t address)

  {

  return *(__IO uint16_t*)address;

  }

  //读取指定地址的全字(32位数据)uint32_t FLASH_ReadWord(uint32_t address)

  {

  uint32_t temp1,temp2;

  temp1=*(__IO uint16_t*)address;

  temp2=*(__IO uint16_t*)(address+2);

  return (temp2《《16)+temp1;

  }

  对于写操作相对来说要复杂得多,写操作包括对用户数据的写入和擦除。为了防止误操作还有写保护锁。但这些基本的操作ST的库函数已经为我们写好了,我们只需要调用即可。

  STM32复位后,FPEC模块是被保护的,只有在写保护被解除后,我们才能操作相关寄存器。STM32闪存的编程每次必须写入16位,任何不是半字的操作都会造成错误。如下图是Flash写的过程:

  stm32f103zet6如何识别flash大小

  STM32的FLASH在编程的时候,也必须要求其写入地址的FLASH 是被擦除了的(也就是其值必须是0XFFFF),否则无法写入。Flash的擦除要求必须整页擦除,所以也必须整页写入,否则可能会丢失数据。如下图是Flash页擦除过程:

  stm32f103zet6如何识别flash大小

  如下为Flash全擦除过程,

  stm32f103zet6如何识别flash大小

  根据以上图示我们便写数据写入函数如下:

  //从指定地址开始写入多个数据void FLASH_WriteMoreData(uint32_t startAddress,uint16_t *writeData,uint16_t countToWrite)

  {

  if(startAddress《FLASH_BASE||((startAddress+countToWrite*2)》=(FLASH_BASE+1024*FLASH_SIZE)))

  {

  return;//非法地址 }

  FLASH_Unlock(); //解锁写保护

  uint32_t offsetAddress=startAddress-FLASH_BASE; //计算去掉0X08000000后的实际偏移地址

  uint32_t sectorPosition=offsetAddress/SECTOR_SIZE; //计算扇区地址,对于STM32F103VET6为0~255

  uint32_t sectorStartAddress=sectorPosition*SECTOR_SIZE+FLASH_BASE; //对应扇区的首地址

  FLASH_ErasePage(sectorStartAddress);//擦除这个扇区

  uint16_t dataIndex;

  for(dataIndex=0;dataIndex《countToWrite;dataIndex++)

  {

  FLASH_ProgramHalfWord(startAddress+dataIndex*2,writeData[dataIndex]);

  }

  FLASH_Lock();//上锁写保护

  }

  在擦除之前应该将页面上的数据读取出来与要写入的数据合并,待擦除后再写入,但这样数据量很大(大容量是2K一个扇区),所以考虑到是少量数据存储,所以每次都将全部数据同时写入,简化操作,也减少数据处理量。经测试以上程序写入和读出数据均正确,可以实现内部Flash的读写操作。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>