STM32L0 内部EEPROM写读9 ]$ i) |3 j1 i$ l$ M
说明, r) X- b! z2 r/ u: g- A3 m2 I3 Z
STM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。, \4 M- }2 n" c* {7 E" M! s1 J* k
! J- m! `. ~$ j+ s* @1 D基础写读函数
! h* K3 }% H) v0 o5 t* W) P7 F0 ~定义内部EEPROM的地址空间:
6 l9 R+ N3 M3 U8 D2 o# w) X- //STM32L031K6T6( a q4 x: J8 P3 f" ~1 U+ T' g
- #define EEPROM_BASE_ADDR 0x080800006 u, e+ J" W H# p
- #define EEPROM_BYTE_SIZE 0x03FF
复制代码
+ A7 E, y* V% ^; f k基础字节写函数) s& ^1 d* \4 U( G! O/ N P
- //Byte write
3 G+ E; w" N% X' l7 F- G2 O - void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)# J: L4 ?. n2 @( E1 V7 R
- {
) v+ h7 K: {/ ^0 g# b - uint16_t i;
X" E0 ~7 E8 c% J - HAL_StatusTypeDef status = HAL_OK;' D- U2 G+ l' U: E/ O% o
. a; P# I) Q/ k2 X. ?- HAL_FLASHEx_DATAEEPROM_Unlock();3 T7 `% w! X, i2 b, O0 F
- for(i=0;i<len;i++)& B6 M' B! g9 S) U) o/ `2 h
- {
3 Q& b! f. Y) h: h+ X - status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
2 H8 x/ W8 i4 E; P8 ?! r; ` - Data++;
9 Q; J! c. o$ [7 M - }
4 L# `: V* a$ w h: A - HAL_FLASHEx_DATAEEPROM_Lock();6 S- [* H2 m; F7 W
- }
复制代码 + S5 f6 y9 O: y7 r0 O4 V5 b
基础字节读函数, K- v b% L( e; h4 T2 N( ?3 ]
- <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read
" o+ v# D% J! ~. e0 ? - void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)9 D& o7 q! Z5 ?. b* o: g: o' ~5 z' _
- {
* _+ J k; r. e* Q" [! b' H1 [* E- Z - uint8_t *wAddr;% W7 f2 a, e$ V" b" {, R( M3 {/ v
- wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);3 c5 K) ~( A% @& a) ?% K' Q
- while(Len--)
n3 _% N. ~. P2 \2 h& N - {; p: `! M9 O. f, u
- *Buffer++=*wAddr++;% S8 ?8 `) j# m. h
- }/ g" L. ]6 z' }) _& R+ _
- }
复制代码
" p& x ?' \1 P$ F4 `9 W% Z: v9 ?/ J0 _带校验写读函数
3 z' w. P7 p @/ u, i1 B; z* c如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。
6 _; C% c% y# r对于写过程,需要将写入的数据,读回做比较。/ z! U/ g4 Y* C3 r5 i' j
对于读过程,需要将两次读回的数据,进行比较。
+ N+ c1 D4 V/ b1 n. i! R如果比较正确,则操作完成。2 J" J: Q1 I+ `
如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。- o% j' e- b% V0 O; N( k) j: L, u
, _# W7 f8 b( |2 D设定重复校验次数
! i' U O# N4 Z- #include <string.h>
* k" U0 l8 o* Y - #define iEEPROM_CHECK_NUM 2
复制代码 ) W4 W* K( g3 W
0 P; s. \* i" n7 Q带操作校验的写函数
' B2 D. Z4 t& u- HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
6 ^) N4 s( P1 ^2 | n9 s - {% `$ b V$ y6 ^$ G$ H
- uint8_t buff[len];+ E- j" w: `6 l# B
- uint16_t i;
3 `) a3 E& F$ v* z5 f" J - for (i=0;i<iEEPROM_CHECK_NUM;i++)
7 M. K& E# T' O) [' @ - {+ o" Y/ `/ }$ S
- EEPROM_WRITE(BiasAddress, Data, len);
6 q* u/ }! H4 C, L/ [: {% n - EEPROM_READ(BiasAddress, buff, len);/ r# g% H, R/ Q9 [2 F* N2 b
- if (memcmp(Data, buff, len)==0)
! R, m @- q9 o( }# H4 \- R - {
7 ~4 D1 r- C! h1 _& ~: e( Q; ~ - return HAL_OK;' G- L1 y/ {- @3 x# R
- }* j, S' v4 {& z9 J
- }
5 C9 b2 D/ f. z; \7 {6 s+ V
7 K- k% d& b+ I" H- return HAL_ERROR;) R5 I2 ^- c6 r# h( m+ r/ A8 ]3 A
- }
复制代码 + n* V% G6 n) o% r
带操作校验的读函数
/ |: r3 d/ v& y5 z- HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
2 |8 u0 {$ d' a ^% _/ v - {
" W7 z! v) s! D9 P2 ^3 q - uint8_t buff0[len];0 ^. z f* i9 K; a5 h* B
- uint8_t buff1[len];
4 p9 P! U) V( j4 y - uint16_t i;
( B' ~# P: I& u$ @' y: q - for (i=0;i<iEEPROM_CHECK_NUM;i++)# a+ L9 s4 R" I4 X0 s
- {
9 G: S4 m7 X4 k8 f* w5 i1 j# _ - EEPROM_READ(BiasAddress, buff0, len);$ u- H2 b8 g3 M% G
- EEPROM_READ(BiasAddress, buff1, len);
' a9 p( f& } a2 L
- s2 v( d+ _0 ~1 I2 x- if (memcmp(buff0, buff1, len)==0)
& ~, G+ ~; f! [( A6 ^ - {
" b' Q8 M/ m" w# Q. K - memcpy(Data, buff0, len);' e' w' L0 g7 k
- return HAL_OK;& V" m/ m) w4 I* X
- }
( e9 n" B. n# b: o7 |% L" N - }
! \6 d! o3 @6 S: L' T
3 j$ G) Q' z r$ y- return HAL_ERROR;
- j7 ]3 S9 o. k' }. E - }
复制代码
9 F; d+ p. v4 i2 y其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。0 X! _1 d( p6 R/ g5 t# \ A4 w
7 }/ o7 _: B/ k e; I需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。
) U) A( `! q1 h* u2 T+ B' e2 f9 ]
% y/ @ ~0 {2 e. K0 Y, pHAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:
% O8 ~6 ]& ]( S% D x) C. v$ P7 C& N
- /**
9 H9 B3 z2 M: F6 h# k' w - * @brief Erase a word in data memory.
( X. ]% {" G: p5 q - * @param Address specifies the address to be erased.2 q: p6 I/ k+ m5 I! F4 L) B
- * @note To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function
6 t% I0 G# B e) [8 X - * must be called before.
1 I# p, q% r W; R) H# M4 n' [; f - * Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access* h9 p) Z; q' C2 n" g
- * and Flash program erase control register access(recommended to protect & Q% y. c, \ r# ?- P# \7 [ o
- * the DATA_EEPROM against possible unwanted operation).4 T2 Q) S: B5 O2 ]- |4 \
- * @retval HAL_StatusTypeDef HAL Status* n1 c9 u/ t' i) J7 h
- */( y5 I2 q- e: j/ e
- HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)/ v5 O0 _9 a3 r2 R
- {
- b1 M+ t' H8 d7 I3 s0 X( @ - HAL_StatusTypeDef status = HAL_OK;
- d0 W2 s: O4 k7 J8 m
) R5 W2 E! ^7 [3 o- /* Check the parameters *// r- p* m- {+ V- ?# c
- assert_param(IS_FLASH_DATA_ADDRESS(Address));( T. Z2 N* x- g, X
- 4 A. H- U. e" [: E. ]
- /* Wait for last operation to be completed */; y: [" s( P; d: f$ F" t
- status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);# x1 i& { R6 h( j
% S. q( U0 w" i. M- if(status == HAL_OK); E; i: h. @( e. y
- {
6 E$ c# B$ N$ [6 T' y5 a - /* Clean the error context */
% n7 `% C+ q3 B! Q5 Q - pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
( K [' }' J( @
/ |" k1 I2 g' X- /* Write 00000000h to valid address in the data memory */
) Q$ Z. q+ `/ l" n6 X+ X+ j i - *(__IO uint32_t *) Address = 0x00000000U;2 O% [3 I' F, w, t, N
7 Z0 B% W1 e1 P/ p4 v5 a) X6 U2 c7 b1 }- status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);6 U/ ~1 Z" S& u2 v$ U! C4 [
- }
' w2 e1 G {/ a: m0 E9 z q) C3 h - 6 t0 v7 t8 v0 I: @& K
- /* Return the erase status */
) k$ m4 J1 |( W+ ]3 P5 n" g1 t6 m - return status;
- ?! h, _7 ]3 ~4 s, v - }
复制代码 ( V$ b4 m& p5 G' S$ E% g* Y1 c
上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。3 z' y/ K4 m! D0 E9 h) ]5 u; y- f
# n! S; y. N+ T( Z3 Z* i9 R) g
$ U5 j9 o& U* b4 w8 V
|