STM32L0 内部EEPROM写读
! f$ {0 q" T7 q @- l8 [7 Y: T& c说明
; t8 }5 l* P7 K+ FSTM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。
9 a n. s3 D' B8 Y* x5 @
- d, j9 c7 l+ C0 f: M基础写读函数6 @/ I* Q# C+ e
定义内部EEPROM的地址空间:
8 `0 J& w" t0 B7 ~; P- //STM32L031K6T6
* Z+ t4 D( o( L5 ~1 j& s; t- } - #define EEPROM_BASE_ADDR 0x08080000; ?2 ]8 R P* G7 }+ p+ Z- j8 N% t
- #define EEPROM_BYTE_SIZE 0x03FF
复制代码
: q1 K' R7 o* o$ n r/ ?基础字节写函数! I# m( ?% S) j0 a
- //Byte write
, O/ u( I+ D5 z' d: e - void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)* }+ Z/ m K: N \3 q
- {4 ?- w: N2 u, j
- uint16_t i;3 t, q9 V+ Z2 o
- HAL_StatusTypeDef status = HAL_OK;
9 ~& C; t: q8 R; R& Y9 ` - 5 V; |, e9 x; R4 I" K5 k; M$ R
- HAL_FLASHEx_DATAEEPROM_Unlock();
5 f0 ~7 v" W2 J - for(i=0;i<len;i++)
+ u5 W/ v, p) C- b: Y" M+ Q% o7 U: i" z - {
4 b9 g% u& i. ~ - status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
$ m% n3 z2 v& k+ \" Z - Data++;
2 @. q9 A* Z' ]4 u - }3 b+ A( f1 \. y j0 e4 h
- HAL_FLASHEx_DATAEEPROM_Lock();4 ^% O5 M, N% p1 u
- }
复制代码
4 a5 p5 C% O$ I8 p基础字节读函数4 l8 j+ n4 I n% E+ V% R( O
- <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read" \8 E. z+ n& F6 }
- void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len), K* V: O8 M: w
- {
S( B& W" W5 ?3 b) r0 P3 ?" O - uint8_t *wAddr;
2 O6 r4 U: ?3 ?7 f: p8 D5 l7 t8 q - wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);
: l: f, J2 R( C; L% v - while(Len--)
2 |) b% j! F& C5 f1 F7 \2 ^ - {, b0 ^! \" c2 l4 E( P0 _
- *Buffer++=*wAddr++;
# h2 j' ]1 U* o5 p - }
# T" |) a" L1 @9 U0 Z$ f- h - }
复制代码 . g" J; d% J# ]
带校验写读函数5 N$ L/ Q7 s& z& r. G
如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。
2 v$ p' b. v* A5 f/ O3 ~0 q8 B对于写过程,需要将写入的数据,读回做比较。7 l0 H' ~4 V( B9 `, u7 A' R ~
对于读过程,需要将两次读回的数据,进行比较。: x: W$ O0 K& _" X7 M+ N( n
如果比较正确,则操作完成。
9 g0 l( l% ]% P如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。
" h- V8 E7 c N1 O1 d' {- h# S0 y+ Q+ T
设定重复校验次数
- Q* s! f' f i& s/ [2 w/ [- #include <string.h>$ N- O4 {" m, J k# m3 e7 A
- #define iEEPROM_CHECK_NUM 2
复制代码
7 a0 ~4 |( [0 `5 e9 Y: x
; h1 R. L: u; V1 G- H6 C+ w3 ~带操作校验的写函数7 q6 j% ?# j! g6 ^8 j2 K2 |* x2 a
- HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
: f8 ?3 @& V1 A- C( e; h! b - {& t: d3 x) }* G2 S( N; G* l, }4 [
- uint8_t buff[len];
8 D: c: P s' L& Z* Y* O! q" P - uint16_t i;6 P- d" P; L9 g
- for (i=0;i<iEEPROM_CHECK_NUM;i++)
G. a* s6 G( l% g# K& }4 D* M - {- t& u2 [8 g; K* ~
- EEPROM_WRITE(BiasAddress, Data, len);
P b; }% h- A( H6 A: p' F. |$ h - EEPROM_READ(BiasAddress, buff, len);
5 u5 S8 h% ]6 r/ q4 G - if (memcmp(Data, buff, len)==0)9 f9 B8 t$ O' c* s6 A/ h
- {
( W; {; H( R# c) y$ c/ z5 z - return HAL_OK;
/ I+ e) A! o# J2 x - }$ V* L5 t( W5 L3 ~+ z$ n
- }1 l- d" z7 `* V7 \+ q1 z7 E j
V/ z: T# k0 y$ @! B" m6 b- return HAL_ERROR;9 J0 ~3 \: V( f5 M# H" Z% [
- }
复制代码 x/ O8 R5 g3 R$ y' S
带操作校验的读函数" e9 m: \* X- k2 g
- HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)! g5 y# b, ]2 _% T X
- {
! @2 F" u$ ^9 d - uint8_t buff0[len];
7 _" u+ R# h. u. P; P9 {+ u) \7 m - uint8_t buff1[len];
1 S& e% E* o) g - uint16_t i;
4 Z1 G5 Q1 w0 Z, C - for (i=0;i<iEEPROM_CHECK_NUM;i++)1 x6 j* F5 Q, N( h- B1 {, i
- {3 i) J# g# w) ]& x2 D' |4 m4 s
- EEPROM_READ(BiasAddress, buff0, len);/ v3 l4 {9 l \ U# K! C' o
- EEPROM_READ(BiasAddress, buff1, len);
4 Y, C8 |+ E4 d - * r8 ]; `8 K2 K9 T1 N- l
- if (memcmp(buff0, buff1, len)==0)) o0 }) I9 G7 I+ t& [ {! l
- {0 a4 l+ o% M, p$ B1 X: `
- memcpy(Data, buff0, len);% X" ~; n5 l, I+ u5 |: s
- return HAL_OK;
6 D# {& v$ c% p3 b* V' a - }
9 z) Y+ i7 C5 b! N6 k# e1 J; s6 { - }
& H* i' M8 X- v - ; U8 _6 K( d' ]' w
- return HAL_ERROR;4 U& s$ _' q0 \
- }
复制代码
$ _8 ~+ |5 x$ B6 q: w其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。! g) G6 W8 w2 a/ ]% @
' ?3 i! Y* L( j- n
需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。
7 ~7 K0 h# _4 w: D( |4 P, ?) W+ s3 C: x& u
HAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:, ]- a" ?" f6 @# C; d; o
e. }. w5 H; D. E P1 t4 z9 p- /**
0 B6 c) K) T3 S - * @brief Erase a word in data memory.* [2 y; l# F: e R( O
- * @param Address specifies the address to be erased.
$ a( @: s* M+ w& f - * @note To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function- p, ?( T7 y4 h7 E; F
- * must be called before.
7 i4 p# U$ L& m2 ~6 n - * Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access
# f/ Q2 Z7 W! @' Z - * and Flash program erase control register access(recommended to protect
( W3 v+ F; C3 B6 h" ?/ b% I - * the DATA_EEPROM against possible unwanted operation).
: P# C2 @7 L) E! y/ w9 M' p - * @retval HAL_StatusTypeDef HAL Status
+ g1 p* [9 q7 p3 u0 k1 ?0 H. V7 k - */
! ]4 G1 }# v, n* V- S& G' t; P - HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)% l4 s. |; Z& @; T) u0 ?; \3 _
- {" E. N, P- d& o
- HAL_StatusTypeDef status = HAL_OK;
4 N7 Z, G; ?8 C3 B$ J% S* J - ) e% l, X9 u2 V' y$ x/ O5 m) w
- /* Check the parameters */
/ D+ T+ B3 u2 ^# E - assert_param(IS_FLASH_DATA_ADDRESS(Address));
5 ^: j1 P- w7 r* m8 s% }& x2 _; t
' i n7 w7 K, g: e2 c# h- /* Wait for last operation to be completed */
5 Z. H3 M# e8 H2 F3 r6 N l - status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
+ a9 L7 `1 l* E' H
6 m4 V3 Y; F H+ Z' ?2 X; A- if(status == HAL_OK)$ Y% y% b3 N! g$ G8 G+ T! v6 L
- {( T3 a S5 \: J+ g. K; | w
- /* Clean the error context */+ r4 D+ g! l% J1 i" `6 w
- pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;3 l9 R/ ~9 j2 {7 @2 f
- 4 n2 j. p9 H. l9 e/ H4 R
- /* Write 00000000h to valid address in the data memory */; D/ j" [$ F/ e( j9 s' p0 ^
- *(__IO uint32_t *) Address = 0x00000000U;
6 i9 ?& I9 g; r. m - ! x* G% \. ? A( ?2 Z* I
- status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
) b6 n* W/ U% v) t) K) h" \ - }- e. D7 D8 e7 w( Z0 ]: z9 A1 q# b
8 N, r/ B; g+ X" t- U( }- /* Return the erase status */9 K+ L1 z. y! Q( Q2 ?' _) P2 d
- return status;
/ }3 m1 _8 i8 [5 V - }
复制代码
- C4 H3 Z$ A' i6 V, k5 M上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。% Z$ A8 f5 K2 v7 _
2 b2 B6 n5 p8 v9 T" b* K3 `- @1 ], K: M
% Q5 j1 a/ j5 u* l
|