STM32F10x芯片本身没有集成EEPROM,替代方案是用片上Flash来模拟EEPROM。Flash与EEPROM的区别主要是:一、EEPROM可以按位擦写,而Flash只能按块(页)擦除;二、Flash的擦除寿命约1 万次,较EEPROM低一个量级。ST网站有个Flash模拟EEPROM的范例:AN2594: EEPROM emulation in STM32F10x microcontrollers(包括源码和文档)。范例在保存修改的数据时,以写入新数据来替代对原数据的修改,并使用两个页面轮流写入,单页写满后进行数据迁移,再一次性擦除旧页面。这个策略可以有效降低Flash擦除次数。9 d! b5 N+ B) _- S
) _/ e: v- ^5 G6 a* ~" g$ t 不过,范例代码只能保存固定大小的数据(16bits),虽然容易改成不同的固定大小,但实际用起来还是很不方便。我改写了一下,新的特性包括:
8 s! Z/ J% t1 t# k t
) O U2 d! E1 D支持不同大小数据(字符数组、结构体等)的混合存储;
/ n4 M9 u; ~( j1 Y! L* M6 Q2 C增加对数据的校验和(Checksum)检查。- ]0 p4 N; Y0 v7 Z* F
附件提供了源码。使用方法很简单,比如要保存一个字符数组 title 和一个 point 结构体:2 F% u, f1 g8 F- W$ _0 Z
- #include "eeprom.h"
6 n" k u- h1 j# \ - 3 m/ l$ Y7 v6 a9 r: a0 R5 U5 Y( i
- #define TITLE_SIZE 80, k! h& i. a$ X* n3 T
- #define TITLE_KEY 1. P- m' X: V- k8 {9 n7 P
- #define POINT_KEY 2
$ r3 ~7 r6 d( f& R) }* s - 5 p+ h3 g, I: ]) w$ H! a; T. n+ X0 m
- typedef struct {
- y5 f1 ?0 H- z* C, R% u7 X - float x;9 L1 s5 X l4 t! c! U
- float y;
7 D5 M* t3 g h, g8 _- i3 m - float z;
% j" T* w( T& n* b - } Point;
; K( [! c/ c6 z/ z8 V- M. Y - ( g1 S# n0 Z0 ]; r* d ? p7 B& ^7 o
- char title[TITLE_SIZE] = "eeprom test string.";
) l) |0 e f/ k - Point point;
复制代码 $ a, O5 ]4 e- R3 f, y0 ?# i
执行必要的初始化操作后,就可以进行写入和读取:
3 n" s) H+ N. Z. l2 G% ^' G- uint16_t result = 0;
0 H0 T E2 C8 N7 q e5 K/ r
% p1 J5 i0 P5 X% j5 f' R- FLASH_Unlock();% r, w N9 V; ] \; P* M
: {5 D3 ^) D, v' u' K* T0 L- EE_Init();
0 u) y6 C- m4 R4 n: r: C9 g" ?
9 B1 P# \3 G& E2 R9 z5 a- result = memcpy_to_eeprom_with_checksum(TITLE_KEY, title, TITLE_SIZE);
1 z s: }& }1 l5 V - result = memcpy_to_eeprom_with_checksum(POINT_KEY, &point, sizeof(point));
. n1 G+ m2 ?4 C+ Y - ' w/ S8 o! ?+ u% X3 b! ]
- result = memcpy_from_eeprom_with_checksum(title, TITLE_KEY, TITLE_SIZE);
9 U. N: e$ f) ? - result = memcpy_from_eeprom_with_checksum(&point, POINT_KEY, sizeof(point));
复制代码
) n! w- `8 q" p7 _实现混合存储的办法,是给每个变量附加8字节的控制信息。因此,在存储小数据时会有较大的空间损耗,而在存储较大的数据结构时空间利用率更高(相对于范例)。代码是针对STM32F103VE的实现。不同芯片需要对应修改头文件中 EEPROM_START_ADDRESS 的定义:
: ?: e/ X0 N1 U' H- #define EEPROM_START_ADDRESS ((uint32_t)0x0807F000)
复制代码
* k1 C& [5 t6 a I" K% D/ q
" ?8 H" \* \9 x* ^& m: S& m* }% J. t* U) p' w* p$ D
|