STM32L0 内部EEPROM写读8 q) u2 I Y8 ~" P; Z
说明
$ l1 V$ a( S$ v- t- ]; FSTM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。( r3 H- ?* c* f
A9 n3 e' ]2 N" G2 y4 Y
基础写读函数, Y( @) z& p/ K% z& A; |* f
定义内部EEPROM的地址空间:
7 e9 E2 ]" g& b/ l- //STM32L031K6T6( z; ~: P/ e& D0 r: f' W6 @
- #define EEPROM_BASE_ADDR 0x08080000
& }5 @( S+ }* N4 ^) g0 }% | - #define EEPROM_BYTE_SIZE 0x03FF
复制代码
9 j8 \# M, O# F6 v9 d基础字节写函数
# ^' f4 N' D/ [7 k' @3 ?- //Byte write) j- G1 a/ }& G5 ^
- void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
) b" X& U1 W7 ?, @ F2 t; S* e6 V - {4 L8 G$ u2 G6 [- H: j) s9 i
- uint16_t i;
5 Z% n: L) V5 K& r& p5 H - HAL_StatusTypeDef status = HAL_OK;5 @8 p! i# Q9 Q5 _7 G) g8 o
, j$ R9 }% b6 o+ k3 @- N- HAL_FLASHEx_DATAEEPROM_Unlock();* k& x, C W+ Y; }+ n1 i
- for(i=0;i<len;i++)
: y6 u# r: J5 `7 ~2 O; a4 p - {% q: ~; j) h$ t4 ~ B2 A
- status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);4 o' k$ P4 a; ?6 ~
- Data++;2 d" c5 M6 y: ^0 {
- }
" C) b+ q) ^3 D4 T7 @8 Y - HAL_FLASHEx_DATAEEPROM_Lock();6 e$ N. n: D% B
- }
复制代码 & Z! Q( f/ N2 Q; }) w3 [: C
基础字节读函数5 H+ c- p6 e/ }$ t
- <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read% E; B9 ~) |8 G# f, H) s& ?9 Y! O
- void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)
0 E3 i+ [* z! E: v3 ` - {6 |4 u, J- t/ `7 X' |
- uint8_t *wAddr;; t+ I0 n. y7 T+ W$ p
- wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);6 s% O$ S. U/ h) Q1 N8 @. A/ Y
- while(Len--)
$ |0 S5 x0 Z& [6 r - {$ G; F# S5 F, Z
- *Buffer++=*wAddr++;6 j( I- ]) f: D1 W
- }0 T; @/ N0 T. t8 \, E7 V9 F [
- }
复制代码 4 N! f( N$ w: N' L/ O/ W8 t
带校验写读函数
5 K% ^" ]8 T$ N如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。! F# g7 R& A+ x/ e% b
对于写过程,需要将写入的数据,读回做比较。2 w" `2 c7 ?; O
对于读过程,需要将两次读回的数据,进行比较。
5 R+ {7 U6 G" D+ s2 t' l如果比较正确,则操作完成。
$ e1 u* S' k- Q如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。' F% o8 {* K8 o! y+ T" S
8 |+ v7 Z$ }/ V. e6 e设定重复校验次数
T$ D$ o! n0 C& ?4 E8 r4 X- #include <string.h>
3 G( j, l4 _+ M, X - #define iEEPROM_CHECK_NUM 2
复制代码
; q. e. ^0 ~ Q- b B
7 o+ d( _% L; H% f带操作校验的写函数
. f* z9 \7 d0 ~' f, S7 N% L- HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
& i- y4 b) r, f& ^' \ - {
6 \- G5 f# J# h0 \ - uint8_t buff[len];4 @) m, k3 {% s# F
- uint16_t i;
; G8 `3 S. J. s" G - for (i=0;i<iEEPROM_CHECK_NUM;i++)
. A3 E7 J" N& N/ G: B4 ~, q, t) V - {
, p% _6 [; G! L8 N$ C7 y - EEPROM_WRITE(BiasAddress, Data, len);6 o/ s+ o. W1 e& Z( }! l
- EEPROM_READ(BiasAddress, buff, len);4 P/ V) [0 C8 n& D3 r6 D' ^- G
- if (memcmp(Data, buff, len)==0)
" O6 ~$ t5 O t& V' l - {0 n! s5 h9 H) T0 w( _6 |
- return HAL_OK;
% J9 X" S/ E: g - }5 s# }/ i' m/ r/ L; ]. l) y
- }. ]% w' c; J/ X% c7 ~/ o$ E' }
- [5 y% J; W7 e( T" h
- return HAL_ERROR;
5 ^) m- n# ?5 V. K - }
复制代码 1 K. k% t6 _- g
带操作校验的读函数1 r% ?" V& n* a+ G; V& r$ K
- HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
( i7 T: X1 c# O1 D1 h - {& Z9 f [! |0 J1 P$ k# G
- uint8_t buff0[len];
0 V$ J. S9 C/ o: g- g+ z/ y - uint8_t buff1[len];
# u k- y( T8 D& u3 N - uint16_t i;
5 h7 D, P7 y, V/ }5 o - for (i=0;i<iEEPROM_CHECK_NUM;i++)
- A6 d4 ?2 s& @; M3 \: o - {
5 _6 _0 M, w) r8 ~( x# c; h - EEPROM_READ(BiasAddress, buff0, len);
5 I i. }( K4 h" t9 V - EEPROM_READ(BiasAddress, buff1, len);
/ Y/ A9 _) }% Q0 E: b
8 H' L/ z: v$ Z4 k6 \- if (memcmp(buff0, buff1, len)==0)
& P4 Z$ [' H. d7 G# }! M; Q3 G - {
0 [8 z& C$ L: }- _" L - memcpy(Data, buff0, len);
+ d5 o0 P0 q2 `6 R/ q/ n - return HAL_OK;
# B3 s% @# |! w1 ` - }
$ ^4 e, c7 o! B6 i5 u6 e5 o - }
$ E4 `' u9 r6 ], c2 j
" U6 z( f o+ a! L( n- return HAL_ERROR;4 d8 l8 f' z* E" O" l
- }
复制代码
6 n5 c$ @" Z- U6 m2 _- _7 F其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。3 H' H, p' M' U3 N6 b- B
' S9 Y6 D6 N+ z4 V" U
需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。
9 r0 d% |7 T9 t
, u% p7 O7 m0 H+ f. lHAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:; T+ `$ F9 p6 M% R6 Z8 \# R9 G
% r Y# f5 s$ X- /**
$ z1 C( K7 ~7 ^0 C8 Y - * @brief Erase a word in data memory.
) I% E6 H& l; B' I/ ]6 \ - * @param Address specifies the address to be erased.
& }( p. K3 W! v% o( J7 o! @ - * @note To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function
9 ^ _1 e3 H; n0 H& m: I1 q - * must be called before.
2 S* P U8 b* L+ @/ S I9 n) X - * Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access6 E# e1 o* F) x- F
- * and Flash program erase control register access(recommended to protect $ C" J6 Z3 J! D/ z; O# g+ G; B* ^
- * the DATA_EEPROM against possible unwanted operation).5 ?+ T) F0 ^$ e4 P6 E" R% I
- * @retval HAL_StatusTypeDef HAL Status$ o5 e% o- e3 F( G
- */
* P9 g0 V* k2 r# E$ u; g1 K - HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)+ D6 n% R/ z0 x% a: `9 Q0 F
- {3 j4 z h: t' F! V& U1 U
- HAL_StatusTypeDef status = HAL_OK;7 P" n) n2 {+ h& }* [
r/ S4 A! a6 F, s' T! l- /* Check the parameters */0 ?- T3 i$ [) ]3 ~" E
- assert_param(IS_FLASH_DATA_ADDRESS(Address));
; z5 l" j/ s' H - 0 D$ y# [$ Q! I+ Q
- /* Wait for last operation to be completed */
. n8 U8 k- w- d- Y% v - status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);7 s- v" \0 P+ a- \! K1 \ y
! u: B! Q' H+ x3 h' w( c. H- if(status == HAL_OK)) l7 I; `) V# B( [4 N8 P3 M- o
- {4 T$ L, k9 F. _9 |
- /* Clean the error context */3 g' `. \3 B+ c' L! q$ Z$ j
- pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
' U; ]: h: a5 s2 ] g+ y0 | M
9 B# Y& y7 p* k3 @( A9 z+ K- /* Write 00000000h to valid address in the data memory */* u5 V! }4 v( L4 n6 P" C
- *(__IO uint32_t *) Address = 0x00000000U;/ k5 u: n' V; e: z. |, S7 O
- 8 q: B* U+ }) B" h
- status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);0 @8 _) m8 o4 k; v( `1 c$ x% j) E
- }
1 U; P5 w( ]2 }
( C+ f/ c4 ?! v) b' b8 p- /* Return the erase status */
' [: R: B. m4 ^1 l; M* |& x - return status;% I) J+ o6 T0 i# A
- }
复制代码
* H( v* z$ C' ]; ~0 G" ?上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。
8 f% H+ ?" |" G+ p) z" I, @& u# ~# D% [; T, N
: n# W5 M1 O1 X8 d7 g2 h
|