lihui710884923
认证:VIP会员
所在专题目录 查看专题
嵌入式串口通讯处理机制(附FIFO源码)
STM32 嵌入式平台上的语音识别系统
STM32F767ZI 之人工智能(AI) 应用
STM32 HAL库中断(绕来绕去)——剖析回调函数机制
stm32如何用虚拟地址存储数据
500A功率采集电路原理和源码分析
作者动态 更多
单片机RTC的中断剖析
03-09 15:28
串口通讯的来龙去脉
02-14 17:32
stm32单片机的USB烧录程序
2023-09-08 22:48
基于CUBEMX的HID双向通讯
2023-08-24 20:46
单片机的增量编码器正交解码
2023-08-24 20:17

stm32如何用虚拟地址存储数据

先看Flash操作的简单流程

1、确定要写入Flash的首地址(稍后介绍确定地址的方法)

2、解锁Flash

3、对Flash进行操作(写入数据)

4、对Flash重新上锁

但是在实际项目中,直接操作FLASH地址的话,会导致单片机flash寿命大大降低,具体用啥方法呢,在官方给的优化文档中,采用虚拟地址的方法来读写存储数据。

一、falsh模拟eeprom,如何移植到自己的工程中,非常详细的,然后我们在分析虚拟地址,下面是具体操作流程

1、在ST 的网站上下载 AN2594 及例程。

2、在例程中src目录中找到eeprom.c 及inc目录中找到eeprom.h拷贝到自己的工程目录中。

3.、在工程中添加这个eeprom.c

4、在工程中的外设库里添加 stm32f10x_flash.c

5、在eeprom.c 文件中包含 #include "stm32f10x_flash.h"

6、main.c中包含include "eeprom.h"

7、添加数据,在 AN2594中,存入到FLASH的数据是以16位的方式存的。每个数据包含数据本身,还需要存16位的虚拟地址。所以在main.c中需要定义虚地址。:

/* Virtual address defined by the user: 0xFFFF value is prohibited */

uint16_t VirtAddVarTab[NumbOfVar] = {0x5555, 0x6666, 0x7777};

需要多少个16位的数据,将定义在 eeprom.h 中的将NumbOfVar修改成需要的个数。虚地址需要是16位,非0xFFFF,互不重复就可以。

定义数据,如果实际的数据不是16位的,可以定义一个联合来解决。

union {

uint16_t SeatStorage[NumbOfVar+1];

uint8_t SeatByte[NumbOfVar * 2+2];

}Seat;

8、使用时,先初始化

EE_Init();

读出数据

if((0 == EE_ReadVariable(VirtAddVarTab[0], &Seat.SeatStorage[0])) &&

(0 == EE_ReadVariable(VirtAddVarTab[1], &Seat.SeatStorage[1])) &&

(0 == EE_ReadVariable(VirtAddVarTab[2], &Seat.SeatStorage[2])))

// 可以用EE_ReadVariable的返回值是否为0判断FLASH中存储的数据是否有效。

就是把虚拟地址的数据读出到数组SeatStorage中。

二、虚拟地址的具体原理分析

这是STM32模拟EEPROM的使用和优化文档的部分截图

如图中所示,你就明白什么是虚拟地址。

对于EPPROM,读取数据是通过I2C的,传入的是Addr,读出的是数据。这里地址就是物理地址。

对于FLASH模拟EPPROM,我们假设FLASH里面的一块区域0x10000000-0x10001000这4K空间用来模拟,其中数据结构都是

typedef Struct

{   

       UINT16 data;    

       UINT16 Address;

}STRUCT_EPPROM;

若在0x10000000处的数据为{0x0001, 0x5555}这里面0x10000000就是物理地址,结合一些逻辑和接口,就可以通过0x5555(结构体中的Address)这个地址找到数/数组,也就是被称为虚拟地址的原因data就是内部存储的数据。

意思就是如果变量是 16 位,则每个变量都占用 32 位( 16 位数据加 16 位虚拟地址),这意味着每次写入新数据时,各个变量分别使用 4 字节的 Flash 。也就是每个变量实际占用四个物理地址,每个 1 KB 页在变满之前可执行 256 次 变量写入。

三、看看项目中具体怎么用,以stm32f103为例,64K的flash,程序中我们选择后4k作为物理地址来存储数据
#define EEPROM_START_ADDRESS    ((uint32_t)0x0800F000) /* EEPROM emulation start address:
                                                  after 4KByte of used Flash memory */

结束地址就是0x0800FFFF,就是4k的空间

举个实例

在EEPROM.H中修改

/* Variables' number */
#define NumbOfVar               ((uint8_t)0x03) 定义要写的 halfword 数量。

用的时候需要定义一个数组

/* Virtual address defined by the user: 0xFFFF value is prohibited */

uint16_t VirtAddVarTab[NumbOfVar];

需要初始化  

1.虚拟地址写数据

uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data); //写VirtAddress 取VirtAddVarTab中内容,相当于编号为0至NumbOfVar-1个数据写入模拟EEPROM中,写入时写入数据紧跟后面写入虚地址VirtAddVarTab(0<=i<NumbOfVar)

相同地址再次写入时不会把上次写的擦掉,而是在模拟EEPROM区尾部未写过的地方再次写入数据、虚地址,读的时候是从尾部开始匹配地址,也就是读取最后一次写的内容。模拟EEPROM区分为2页,如果一页满了把这一页内地址不重复的数据复制到另一页后擦除,2页交替使用。

2.虚拟地址读数据

uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data); //读

这个函数返回的是虚拟地址所对应的数据,虚拟地址是作为一个参数被传送的。只有最后更新的被读取。这个函数进入的时候是一个循环,在这个循环内读变量目录到最后一个。如果找不到该地址,读状态变量将返回1,否则就重置表明变量已经被发现并且变量值被返回到Data变量。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 8
收藏 9
关注 191
成为作者 赚取收益
全部留言
0/200
  • 小董 2021-03-25 12:40
    不亚于看了一篇高质量论文
    回复
  • dy-blNlwnWV 2021-02-24 23:08
    什么时候更新
    回复
  • 星球居民-YBPLIKJ1 2021-01-24 13:01
    内部存储有风险?
    回复
  • keyhei66 2021-01-15 11:53
    实例讲解
    回复
  • 米修儿 2021-01-14 16:55
    不错不错
    回复
  • liuxiaofei126 2021-01-12 21:24
    学习了
    回复