STM32F10x芯片本身没有集成EEPROM,替代方案是用片上Flash来模拟EEPROM。Flash与EEPROM的区别主要是:一、EEPROM可以按位擦写,而Flash只能按块(页)擦除;二、Flash的擦除寿命约1 万次,较EEPROM低一个量级。ST网站有个Flash模拟EEPROM的范例:AN2594: EEPROM emulation in STM32F10x microcontrollers(包括源码和文档)。范例在保存修改的数据时,以写入新数据来替代对原数据的修改,并使用两个页面轮流写入,单页写满后进行数据迁移,再一次性擦除旧页面。这个策略可以有效降低Flash擦除次数。
" G9 D( f2 d9 m; x
0 ^) \* e2 N& W {% ` 不过,范例代码只能保存固定大小的数据(16bits),虽然容易改成不同的固定大小,但实际用起来还是很不方便。我改写了一下,新的特性包括:
+ B" T: t6 t0 ?2 b, ~& H2 T: P
2 e9 @9 s/ v3 B+ @+ N) k( V- \支持不同大小数据(字符数组、结构体等)的混合存储;. P, P) ]" v- j* s0 Y
增加对数据的校验和(Checksum)检查。2 n$ u: w/ }" |, Z1 d3 {; B
附件提供了源码。使用方法很简单,比如要保存一个字符数组 title 和一个 point 结构体:! |, v2 p4 `. n2 W' `
- #include "eeprom.h"+ M$ t2 S# J, f5 o" v" W
- $ o0 Q8 V: h0 g0 f* @4 j# ^
- #define TITLE_SIZE 80
5 r; A( d4 h# c4 d1 H - #define TITLE_KEY 15 q% y1 X% I z \ u' d
- #define POINT_KEY 2, [/ ~5 v2 A! H0 s2 f# W3 N' c$ ~
- - C8 G0 X6 n, i! G1 g$ Y
- typedef struct {
% I9 O f+ U: t - float x;
# [& v! o) q( w8 Y5 b - float y;
" B) a# R: r, f - float z;
" T/ y' V) l, g' Y# B; j) {: k3 O+ X - } Point;% M g8 U5 i" `# r3 h" N; w
- ' P$ P+ v$ v/ V7 i6 `1 M( D2 X
- char title[TITLE_SIZE] = "eeprom test string.";
4 o% y8 f- @7 J1 J0 N! a - Point point;
复制代码
' t4 D+ {3 h6 v0 f |执行必要的初始化操作后,就可以进行写入和读取:
) ?, A+ \/ Y V7 Y9 |# t- uint16_t result = 0;
/ E6 ~. ~* \* E
+ s6 ~( ?8 h, P3 t9 ?; a* J' K- FLASH_Unlock();
+ j0 @ }, T/ A1 t1 Y. P4 ] - : U! E4 o6 Q, N0 w5 n; X
- EE_Init();
! F5 ^: C- O! [! Z" W A& v/ d* r - ' ]/ x% ~% [4 f# n5 p6 V# o
- result = memcpy_to_eeprom_with_checksum(TITLE_KEY, title, TITLE_SIZE);, ?, _, b: @8 P2 k$ T
- result = memcpy_to_eeprom_with_checksum(POINT_KEY, &point, sizeof(point));# }" d8 O5 ?( B$ o4 q/ Q4 C; l
! w% q1 a7 Z/ O3 n9 O: D; {- result = memcpy_from_eeprom_with_checksum(title, TITLE_KEY, TITLE_SIZE);: j% ^/ `% T9 c T; B
- result = memcpy_from_eeprom_with_checksum(&point, POINT_KEY, sizeof(point));
复制代码
/ {/ F8 Q& c4 a+ D' X% @实现混合存储的办法,是给每个变量附加8字节的控制信息。因此,在存储小数据时会有较大的空间损耗,而在存储较大的数据结构时空间利用率更高(相对于范例)。代码是针对STM32F103VE的实现。不同芯片需要对应修改头文件中 EEPROM_START_ADDRESS 的定义:
" h$ d# Z) I. D7 A/ M- }8 F) R- #define EEPROM_START_ADDRESS ((uint32_t)0x0807F000)
复制代码 0 I1 w4 d E; X) j2 F. w
, R; B% B, @. e, ], [& L' U0 x7 A) z
|