本帖最后由 creep 于 2018-1-9 16:18 编辑
9 G5 P4 O2 j0 j, E( c% b2 q
% W6 \6 Q5 w2 U' V' p; F, | STM32L的EEPROM支持字、半字和字节的读写操作。写操作之前自动擦除,如果写的数据为0,则只执行擦除操作。
# G8 ]1 z0 T# O6 c) e/ X5 C- J6 T: o/ H" w
使用STM32Cube库对自带的EEPROM进行操作,代码如下:
- B6 n, u5 L9 R- * k+ X. D0 S0 D% k) z/ U
- #define EPROM_WR_TYPE_BYTE ((UNS8)0x00)
6 R( L" |& C- S9 K- x - #define EPROM_WR_TYPE_HALF_WORD ((UNS8)0x01)/ ~! S/ g' P3 H. e4 q0 ~2 O
- #define EPROM_WR_TYPE_WORD ((UNS8)0x02)9 u+ K! ]8 k' m' F
! n7 P, p" X( H* Q& j: s2 Q- #define EPROM_TEST_ADDR (STM_EPROM_ADDR_BASE + 12)! U& ?5 a% ?3 T; E- _
- #define EPROM_TESTE_ADDR (STM_EPROM_ADDR_BASE + 32)
, K. k7 P5 Z% [! x3 {( i - #define EPROM_TESTEE_ADDR (STM_EPROM_ADDR_BASE + 61)
. v; k; C+ j p& n! ^ - / { f. D- y7 |1 G" I
- //// Unlocks the data memory and FLASH_PECR register access; t! E; R$ U' h; G3 v
- //// ret :
0 X/ `. r# W6 o/ U4 r - //// OK = 0x00U,
J3 F$ I& d2 Z, I4 C( D - //// ERROR = 0x01U,, I2 B& Q' z& Y( z
- //// BUSY = 0x02U,
. x4 e" U3 ?2 x& \8 @$ p# [. p- z - //// TIMEOUT = 0x03U. p v3 j* h+ o& O* T! u; g( r. a" U
- UNS8 StmL0xxEpromUnlock(void)9 q Z" H* R& g% A5 y, C
- {3 I" l+ ]0 ^6 H" y$ U- x. C8 C6 t
- UNS8 ret=0;
/ }' t: x4 Q5 ^! d" W -
! @* o, H0 [- e2 W4 P% ]! Z - ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Unlock();) @( J1 U7 H5 @6 c8 s2 l$ A
-
5 Y1 E8 y$ m2 G f6 }6 j. w$ M - return ret;3 A- B3 c2 X8 a9 t8 A2 g& D: \! [9 J
- }0 a8 H, @6 Y6 \1 N& c/ U
7 i1 i% i' i- `8 T/ |# D/ q C% h- //// Locks the Data memory and FLASH_PECR register access6 c0 ?0 Z9 f, b1 G$ j: I+ G- \% c
- //// ret :4 b* f" D+ ]. ~8 {/ n
- //// OK = 0x00U,
) y8 v$ R( y) @' h+ q) R% ^ - //// ERROR = 0x01U,
4 {; k: H& i3 d5 g- { t0 c - //// BUSY = 0x02U,
7 G" p* q0 {6 c2 K - //// TIMEOUT = 0x03U
$ r* D2 O! g! T" f( C - UNS8 StmL0xxEpromLock(void)+ V1 N6 a& M! E/ M8 }% V1 O8 Q
- {
. m3 q1 @7 ?/ H+ y - UNS8 ret=0;) U; o6 }9 ^; e- X
-
9 \. r) h2 X* f0 n - ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Lock();
) i$ y/ `) l5 {" j -
. J/ w) A. Q f6 D: _3 f2 ` - return ret;
! K& L6 N$ H5 c* p$ b7 N - }
1 O8 V3 _ }8 q - * v& z: I/ B A. N4 T' i: G
- //// Erase a word in data memory.
- r, K. Y# N/ a) g - //// To correctly run this function, the @ref StmL0xxEpromUnlock() function8 }! S8 @. n y2 _. L+ x9 V% S g4 B
- //// must be called before.
" ]) B8 [7 G5 I R* _' ?/ O - //// addr -- specifies the address to be erased.0 l" A) k4 s3 Y
- //// ret :
7 ~) p7 b' f* W% W/ l9 [& X - //// OK = 0x00U,! z0 }5 Z4 x: o n% F
- //// ERROR = 0x01U,
; O# k1 n: H2 p - //// BUSY = 0x02U,7 ~ F2 A. o J8 ^5 e9 J H) C
- //// TIMEOUT = 0x03U" @- u+ v3 M5 e O
- UNS8 StmL0xxEpromWordErase(UNS32 addr) z" c. C. K* B8 W) z8 }, L. S
- {
. D, o* z- ` ` - UNS8 ret=0;5 f) N8 |: Z7 |2 J- i5 [4 y" k
-
3 W" k. ]7 S! R+ o: U# t - if ( (STM_EPROM_ADDR_BASE>addr) || (STM_EPROM_ADDR_END<addr) )" d* k/ o0 k7 _( I4 n6 c p G
- { ]. Y: ]8 C7 k$ L- e& E
- return ret;8 x( Y) e, G/ W7 p9 f# c) E
- }
- v! E0 X2 R/ o- [1 a -
5 K0 w+ |* D8 R6 F2 [% W - ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Erase(addr);2 Z4 P, o: w! g6 a4 ?) S( C( L$ v
- ) W5 T6 y4 q0 z+ C- K5 Z
- return ret;
# d+ `: W# d4 m% a5 \ - }4 S/ G# h; Z. ]9 c3 o7 d6 C
( k- }# C' |, W- //// Program data at a specified address
- g8 G5 T- v, S" P4 L0 A7 I4 } - //// type :7 _! t' c5 f' e5 V3 I
- //// Byte -- 0x00
0 b1 B2 \5 l# S+ x - //// HalfWord -- 0x01
6 D! E( V( x8 r( M9 D6 B$ q2 M4 W - //// Word -- 0x02
! G6 v- j" X( K. W6 h - //// addr -- specifies the address to be erased.
% ]+ R9 }: i. z8 ?; o7 b - //// ret :
. l+ {4 M' o" u9 F- {8 {3 r: I+ Z - //// OK = 0x00U,9 c5 r4 o) v# ^. j% C" d4 k. H. {
- //// ERROR = 0x01U,
5 l0 j9 S. ~5 a4 N9 Y - //// BUSY = 0x02U,
9 B- K" J$ [0 H$ K - //// TIMEOUT = 0x03U. T- S5 C0 C5 [+ W( c/ X, v/ T8 f) O
- UNS8 StmL0xxEpromSingleWrite(UNS8 type, UNS32 addr, UNS32 data)7 ^+ a& h* X2 X- q; R- W J
- {& ^9 F- A- H9 \! E
- UNS8 ret=0;
; |' B: X0 r" b6 Z - - U3 u/ s9 u( n4 `. M
- if ( (STM_EPROM_ADDR_BASE>addr) || (STM_EPROM_ADDR_END<addr) )
/ p- S: V% e9 R$ ] I$ K - {5 R8 s' V$ N) t; D
- return ret;
4 M+ I3 ~1 O7 ]. u; O - }) x. u( e3 _- M
-
3 \+ z- S0 d* w+ W' t - StmL0xxEpromUnlock();: x4 `( ]7 {7 w+ u- \; L
- ret = (UNS8)HAL_FLASHEx_DATAEEPROM_Program((UNS32)type, addr, data); //// 库函数
; g5 R5 q$ M) ?/ W* z# X3 Y - StmL0xxEpromLock();( m0 h; w+ f: Y) m. u' L$ ~
-
2 o) x/ l# Z; _0 P6 @* K2 ~ - return ret;
- n6 G r+ m2 T! Z) U: ] - }- d" G7 M' S" b- S) g/ ~
h5 P E5 b0 x1 T: d, B& M- //// read a byte at a specified address
% v0 b* [; |7 M8 _ - //// addr -- specifies the address to be erased.
6 R# q/ v9 m6 ] - //// ret :
8 J: l: P2 Y5 Z: \# S - //// OK = 0x00U,
7 P1 x) z; |+ O" _+ k - //// ERROR = 0x01U,
4 \, ~5 o( d3 l6 w4 `8 f - //// BUSY = 0x02U,; [7 r5 O' a4 w- L. c" D0 Y
- //// TIMEOUT = 0x03U, K( r% p# d+ W0 H4 Q3 o
- void StmL0xxEpromSingleByteRead(UNS32 addr, UNS8 *data)
9 c2 N9 R' I% A' m( z, Z/ r - {" I% q+ K& r# r8 m) ~+ K0 d# \6 k
- 7 E; C8 Y# l4 J# U8 e
- if ( (STM_EPROM_ADDR_BASE>addr) || (STM_EPROM_ADDR_END<addr) )3 u& Y @) U( M2 y% H
- {" V+ r+ h) [( O
- return ;! e+ ]/ I( Y4 u% M' j3 p
- }4 W# B- s* s+ w& x5 Y/ j; r! y- r
-
* {& e$ X# Q& n5 ~+ N0 C+ v; Y - StmL0xxEpromUnlock();
3 w" h6 F9 n6 a5 |& g: O - *data = *(volatile uint8_t *)(addr);
Y: G8 r4 A6 h% D) H) H - StmL0xxEpromLock();% N# N, }0 ^9 X# a
- }
复制代码 测试代码如下:% B5 C5 C% } S7 P; {
- void EpromTest(void)5 V9 [; P- B' E9 _% h
- {( o- i% s0 ^! w- T$ u) E& e
- UNS8 tmp[8] = {1, 2, 3, 4, 5, 6, 7, 8};7 J6 Q. G! W: U- a) h! x: L
- UNS8 read[8] = {0}, num=0, time=1;: l; ~' ~" N( o/ l) t$ ]) O
-
7 k" d8 a1 C+ ]! C A4 c - while(5>time)( f3 ~$ m3 [4 O, f3 x7 |# B
- {
% Z" Z/ n# Q: ?+ L# o7 n! H2 W - for (num=0; num<8; num++)8 J2 H0 A+ @! ?# K
- {0 [" @& x9 L/ @% h# {
- tmp[num] *= time;
m+ u& X" J3 I0 | - StmL0xxEpromSingleWrite(EPROM_WR_TYPE_BYTE, EPROM_TEST_ADDR+num, (uint32_t)tmp[num]);
. P: q* R2 K# ^9 p - }# T# q* ]% ^3 I
- a3 Q- B( m/ z A8 u( L! H+ o
- for (num=0; num<8; num++)
4 E7 D! I; T& g- A+ y - {) P6 ~. s. Y/ U7 Y) F% J' Y
- StmL0xxEpromSingleByteRead(EPROM_TEST_ADDR+num, &read[num]);
' H1 i/ A v" U4 G+ n8 K - if (tmp[num]!=read[num])
: ^& Q) l4 [( t2 a+ [ - {9 o: [. _% B5 t; _5 p; |
- time = 10;. `: M1 t# F6 P
- }/ \0 m4 ^. e( T" V3 y. g* @
- }* Q' v$ d U! O% x, r
-
4 n( b( m d' E. f! L - //// StmL0xxEpromSingleWrite(EPROM_WR_TYPE_HALF_WORD, EPROM_TESTEE_ADDR, *(uint16_t *)(&tmp[0])); //// 进入异常中断
& V: x. F, k6 ?" l0 k7 j% Q - //// StmL0xxEpromSingleWrite(EPROM_WR_TYPE_WORD, EPROM_TESTEE_ADDR, *(uint32_t *)(&tmp[0]));//// 进入异常中断
9 h( {# c9 M; M; K; B7 B - StmL0xxEpromSingleWrite(EPROM_WR_TYPE_WORD, EPROM_TESTE_ADDR, *(uint32_t *)(&tmp[0]));
* o# a9 o4 r+ X6 ]' p" g - StmL0xxEpromSingleWrite(EPROM_WR_TYPE_WORD, EPROM_TESTE_ADDR+4, *(uint32_t *)(&tmp[4]));
* `+ q, p, n3 |; v; ~; M! X) N - StmL0xxEpromSingleByteRead(EPROM_TESTE_ADDR+0, (UNS32*)(&read[0]));4 X" p/ }& d. J" y" s
- StmL0xxEpromSingleByteRead(EPROM_TESTE_ADDR+4, (UNS32*)(&read[4]));( m# q; b5 ^' P* o7 C, v. F; q
- : [5 @6 q6 A5 O# w+ [8 u
- time ++;
/ h$ @( L) Q- f; V4 s' x! e - }
: ^6 g. F( y! ^4 t' L6 A9 ] - }
复制代码 | | 2 f3 H# G5 E% |! d0 J
, O; }. U: K7 @2 T3 _7 t
: g1 m: Q6 \" Z5 y; J$ q
, [2 R r; ?+ h8 j( m1 n5 I
, f* E# L) z+ Q& w. Q5 r
, Z% Q" M# m/ q3 x5 {& ` | 总结:
* }( Z+ ^& w- E 1. 字节操作时,传入任何地址参数都可以,读写操作正常;$ B# C0 R0 M2 y. R
2. 但是当半字操作时,如果地址不是2对齐的,则调用函数StmL0xxEpromSingleWrite时进入HardFault中断;
* Y2 S0 e0 E+ ]+ n8 v# r 3. 但是当字操作时,如果地址不是4对齐的,则调用函数StmL0xxEpromSingleWrite时进入HardFault中断;% f* |3 C( M1 d' O+ T! K+ J
8 |! U+ I, o+ {5 H: \
调试发现调用HAL_FLASHEx_DATAEEPROM_Program函数时进入异常中断。: V; ]/ k* w _9 B
原因是EEPROM在内存结构上实际是以字为单位的:
% O9 m! r! {: ^& c
7 N: W! z# v3 z2 A% [/ ^
虽然可以进行字节、半字的参数,但是必须保证地址的对其方式——半字操作以2对齐,字操作以4对齐,否则会出错。
H! Z" h9 f& b9 M/ T( \
& v3 v% o3 N8 ]! u9 ?6 | !!!!这个代码的对其方式怎么跟贴代码之前不一样呢,完全左对齐了!!!& ]2 _# \4 N9 N. Y+ y4 \
0 ~1 S7 v6 n$ { B, M. a& }2 A& c' I7 N, a4 c$ D7 _8 f
|
https://www.stmcu.org.cn/module/forum/thread-614550-1-1.html