你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32学习之:内部Flash

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

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

1.png

      根据上面的Flash组织模式,我们可以根据自己的使用方便来作相应的定义。因为大容量每个扇区定义为2K,而小容量和中容量都定义为1K,所以我们做如下宏定义:
  1. #define FLASH_SIZE 512          //所选MCU的FLASH容量大小(单位为K)

  2. #if FLASH_SIZE<256
  3.   #define SECTOR_SIZE           1024    //字节
  4. #else
  5.   #define SECTOR_SIZE           2048    //字节
  6. #endif
复制代码
     虽然ST的库函数比较全面,但都是基本操作,为了使用方面,根据我们自己的需要对其进行再次封装。

      对于读操作相对比较简单,内置闪存模块可以在通用地址空间直接寻址,就像读取变量一样。
  1. //从指定地址开始读取多个数据
  2. void FLASH_ReadMoreData(uint32_t startAddress,uint16_t *readData,uint16_t countToRead)
  3. {
  4.   uint16_t dataIndex;
  5.   for(dataIndex=0;dataIndex<countToRead;dataIndex++)
  6.   {
  7.     readData[dataIndex]=FLASH_ReadHalfWord(startAddress+dataIndex*2);
  8.   }
  9. }

  10. //读取指定地址的半字(16位数据)
  11. uint16_t FLASH_ReadHalfWord(uint32_t address)
  12. {
  13.   return *(__IO uint16_t*)address;
  14. }

  15. //读取指定地址的全字(32位数据)
  16. uint32_t FLASH_ReadWord(uint32_t address)
  17. {
  18.   uint32_t temp1,temp2;
  19.   temp1=*(__IO uint16_t*)address;
  20.   temp2=*(__IO uint16_t*)(address+2);
  21.   return (temp2<<16)+temp1;
  22. }
复制代码
      对于写操作相对来说要复杂得多,写操作包括对用户数据的写入和擦除。为了防止误操作还有写保护锁。但这些基本的操作ST的库函数已经为我们写好了,我们只需要调用即可。

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

2.png

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

3.png

     如下为Flash全擦除过程,

4.png

     根据以上图示我们便写数据写入函数如下:
  1. void FLASH_WriteMoreData(uint32_t startAddress,uint16_t *writeData,uint16_t countToWrite)
  2. {
  3.   if(startAddress<FLASH_BASE||((startAddress+countToWrite*2)>=(FLASH_BASE+1024*FLASH_SIZE)))
  4.   {
  5.     return;//非法地址
  6.   }
  7.   FLASH_Unlock();         //解锁写保护
  8.   uint32_t offsetAddress=startAddress-FLASH_BASE;               //计算去掉0X08000000后的实际偏移地址
  9.   uint32_t sectorPosition=offsetAddress/SECTOR_SIZE;            //计算扇区地址,对于STM32F103VET6为0~255
  10.   
  11.   uint32_t sectorStartAddress=sectorPosition*SECTOR_SIZE+FLASH_BASE;    //对应扇区的首地址

  12.   FLASH_ErasePage(sectorStartAddress);//擦除这个扇区
  13.   
  14.   uint16_t dataIndex;
  15.   for(dataIndex=0;dataIndex<countToWrite;dataIndex++)
  16.   {
  17.     FLASH_ProgramHalfWord(startAddress+dataIndex*2,writeData[dataIndex]);
  18.   }
  19.   
  20.   FLASH_Lock();//上锁写保护
  21. }
复制代码
     在擦除之前应该将页面上的数据读取出来与要写入的数据合并,待擦除后再写入,但这样数据量很大(大容量是2K一个扇区),所以考虑到是少量数据存储,所以每次都将全部数据同时写入,简化操作,也减少数据处理量。经测试以上程序写入和读出数据均正确,可以实现内部Flash的读写操作。




转载自JawSow

评分

参与人数 1 ST金币 +2 收起 理由
MrJiu + 2 给与鼓励!!!

查看全部评分

收藏 评论3 发布时间:2018-5-24 09:21

举报

3个回答
MrJiu 回答时间:2018-5-24 09:37:44
疯de_恒 回答时间:2018-5-24 10:39:41
擦写平衡算法考虑一下?
xinnian-400985 回答时间:2018-5-24 22:49:57
呵呵,我现在就是想用此功能,参考了,谢谢!

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版