STM32L0 内部EEPROM写读
, y5 b9 e/ h! I8 x0 `( J* u说明+ G# F* j- x4 L: }/ M
STM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。: Q) F+ V. a/ l* G" ], b
- Z4 l" z& G- W1 B基础写读函数
, f. C! z; l" S9 L- W- z! _定义内部EEPROM的地址空间:; A: Z0 F# N- b& H
- //STM32L031K6T6
F% T- z* l% V& p( A - #define EEPROM_BASE_ADDR 0x08080000% L% f' H+ o2 W: G( I
- #define EEPROM_BYTE_SIZE 0x03FF
复制代码 0 [% h8 z, V$ ~4 Y) M7 O( q
基础字节写函数
3 J7 o y) a- d; X- //Byte write
: [' b9 K/ B! r4 t1 r+ j+ r0 y - void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)* _ {- i3 Y/ K2 r) a% q
- {
) [$ |* `3 s2 ~& C' c3 k - uint16_t i;( e4 q1 E+ p* I1 `
- HAL_StatusTypeDef status = HAL_OK;! b% d) j: q( V* T& {4 C5 Y" _' R
- 1 _! k$ q( O1 W( F4 H' q/ I" H3 v
- HAL_FLASHEx_DATAEEPROM_Unlock();! F5 |, g* D( Y
- for(i=0;i<len;i++)
+ U& a/ Z! a! A, m- f5 j+ r9 m- l - {4 F5 f, @8 {- X0 p! c' B" `0 X
- status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
7 m- }/ c' K% U4 G& h% h! O1 ? - Data++;! @2 ?# m! B6 ~9 a! x
- }
1 P1 a4 Q. p) {" z( f - HAL_FLASHEx_DATAEEPROM_Lock();6 ?$ y# q- g; \, b
- }
复制代码
1 [1 x& Y+ N/ ?8 b' N% [4 C基础字节读函数/ J) O* t [, A: ^! n5 L
- <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read2 L6 B& X: A Y+ h7 ]
- void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)/ I2 i& I; l( s
- {+ u5 y1 N6 G% j3 M/ V, D7 R( i
- uint8_t *wAddr;( p8 m$ g7 Q5 H% n7 O6 W) {
- wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);6 g/ J7 w& ^! a! ]5 n8 g" g0 z
- while(Len--)
& r- x% {+ N) J; b1 K' y) f - {1 l! C2 k$ \, \2 f4 \" V- H
- *Buffer++=*wAddr++;0 l. J# h. U7 E, o
- }# Y/ p) N7 v7 N& Y1 k7 x% Z
- }
复制代码
6 J* V8 c5 _, _带校验写读函数
$ s, U/ b% p5 _: c如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。
2 o) Q! a: j& P; ]3 y对于写过程,需要将写入的数据,读回做比较。
6 G7 k5 n$ V# Y对于读过程,需要将两次读回的数据,进行比较。
- f6 J8 {% d* S/ C- T* [如果比较正确,则操作完成。+ N# l7 t0 c/ @& Z7 G- L
如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。
1 ~6 ?( M# \7 B6 W) q
7 q, v( [* {7 \' h设定重复校验次数
N3 @. Y) K' P8 i' V- #include <string.h>6 N2 i4 U3 f B) A( O
- #define iEEPROM_CHECK_NUM 2
复制代码 - b: ]2 h; G" j( n5 t1 i
4 u4 U1 V: F1 A: v6 T" x9 t带操作校验的写函数
/ B2 I d0 P0 f9 M, S( q( b1 \5 G- HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
V; D6 o. H Q - {* {% `0 b, k* d1 m) Y
- uint8_t buff[len];5 ?" h4 Q1 {& ~' P
- uint16_t i;" X8 k2 M$ x0 y. K. f
- for (i=0;i<iEEPROM_CHECK_NUM;i++): m8 F1 S A. B7 p/ c9 `$ l7 e
- {; E L5 q* E) b2 ^4 _! J
- EEPROM_WRITE(BiasAddress, Data, len);
& ]- @$ Y6 O6 U& p - EEPROM_READ(BiasAddress, buff, len);
5 O3 n4 ?9 n7 o4 [4 Z! U% t - if (memcmp(Data, buff, len)==0)) q# s% V! n0 N) U6 ~( A7 F
- {
& P8 d- |' L/ b' { - return HAL_OK;
6 m1 O% _: x6 S2 D - }2 z+ C3 V+ Z. i" l5 E' c
- }
3 C) i6 H t; c* O9 @
) b0 R$ j. u$ C8 T3 ]! e) p! a' C6 v; p- L- return HAL_ERROR;% R, }7 {; K; I( K6 t* g0 ^# h6 a: Q
- }
复制代码
; X( d: A$ e6 N# b! M: G带操作校验的读函数
- x0 q& s, z, u- A- HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
' w6 \+ }- a, r$ K! s' f' G6 Z0 b - {* G0 d4 ~4 i: u9 t9 w2 i: r3 x, `4 R
- uint8_t buff0[len];. V; k( }+ V1 j% n! W$ x# g8 f
- uint8_t buff1[len];
1 f$ B" y1 s% o& @7 h - uint16_t i;
$ `7 x; b* s) M) R1 r - for (i=0;i<iEEPROM_CHECK_NUM;i++); j' u( ~2 w' ]4 @) ?6 ~
- {3 K9 y' F0 ^& I/ U" s3 M1 u1 B* z; O
- EEPROM_READ(BiasAddress, buff0, len);
. U7 h O4 R/ n% ` - EEPROM_READ(BiasAddress, buff1, len); Z) u, D' k& I* q0 K7 G( X, X
- J: D( E" [; n1 i) L3 N- if (memcmp(buff0, buff1, len)==0)
: r: L- {5 R; U8 u - {& ]! {/ ?3 H8 Q
- memcpy(Data, buff0, len);; A; S6 u/ d; {6 C$ {
- return HAL_OK;
& `1 k3 _0 U) ] - }# c% e* _2 H+ }5 O g0 K
- }0 S# E1 @3 H/ J
6 D8 V" W. G, R0 b0 F$ I9 p! n" H- return HAL_ERROR;4 M, @: a+ ]& Q8 C! r* q# D6 b
- }
复制代码
4 B5 v3 u' {, ]其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。
" O( j8 [! e4 X- \. v& J
8 b4 T: p0 C/ l' T2 n需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。
" i# E8 h4 @. d6 D+ r6 a" g
7 ] i1 W) I, p* V0 l1 [) eHAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:* a y0 u+ E$ U
! N+ T' i% j; N+ L, o; G- /**
. k1 {* {: g* N8 q - * @brief Erase a word in data memory.
7 h8 M7 ]) o4 ^; V. R- M( O& @ - * @param Address specifies the address to be erased., \% H% ^" G8 Y. @$ x
- * @note To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function5 K2 @% y/ I7 m. U% g
- * must be called before.
$ f9 k& j3 r- i5 w - * Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access! ?; M% r/ T+ G1 T! }3 Q/ H
- * and Flash program erase control register access(recommended to protect
; d+ j! t! z& m$ l- R. S - * the DATA_EEPROM against possible unwanted operation).
( s- M y( A* y5 ^# v - * @retval HAL_StatusTypeDef HAL Status* W4 m# ]+ o9 W2 h
- */
g: U) b8 g5 e/ j5 {4 u7 k; h - HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)7 i9 w* R: U# O0 r2 C
- {6 Q# l4 b2 k9 t3 L5 `6 P6 S
- HAL_StatusTypeDef status = HAL_OK; I* a# U" c8 q1 ~
- - X! K3 _' Y1 a9 N6 x
- /* Check the parameters */" ~% j" t9 O2 S, E, D+ T1 l: v
- assert_param(IS_FLASH_DATA_ADDRESS(Address));
6 f0 ]; U, y5 N - 3 u1 T# n# q# v* G2 \' E( i
- /* Wait for last operation to be completed */2 b9 {$ n. P( X5 R5 L
- status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);8 X5 t+ ^: K4 @& [# Q0 L4 D0 H0 C" T
: R- ~# t+ j/ @+ M0 r6 l1 r0 i- if(status == HAL_OK)0 v; H- z5 q1 `8 B) ]
- {9 o/ `5 w. O0 H' n& E
- /* Clean the error context */. Y. b4 v: t' b+ {
- pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;5 n) [6 o- }; \: A1 O0 q5 x- r9 c
- / l, U" C R% Y. b3 d8 L
- /* Write 00000000h to valid address in the data memory */
: \3 }: {' z' d' \0 ] - *(__IO uint32_t *) Address = 0x00000000U;- J$ f! g. D% R) B# W0 n
- * O; S2 f3 E7 v& G% Z
- status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
; v3 }0 X8 {# c! u% n% M/ }3 [ - }/ e$ d3 W, X/ C* W! B
; x4 p1 l# r9 r6 ?7 U* H4 [1 y0 F- /* Return the erase status */+ p! c$ e- C' i! F, h e3 ~
- return status;' i! E& o9 z2 C! L4 T$ O( Z
- }
复制代码 4 N6 c" M* l4 d6 m
上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。
; k1 \, H x- X# \- I
3 O; U6 \! {6 R1 a, Z. i4 n) `! l% D
|