STM32L0 内部EEPROM写读, V0 x" h$ b5 A
说明
0 h5 Q8 ?# A1 C0 ?STM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。, w5 B1 T2 \" j- t: Q. ~# k' F4 z
4 \* ^$ |0 [+ E% r n基础写读函数1 _! ? w- k1 N4 S2 _: ?0 F, [4 l' s
定义内部EEPROM的地址空间:
% \2 p2 r( C2 L* H9 e- //STM32L031K6T6
: X) t; j' Y v! d9 ^- d - #define EEPROM_BASE_ADDR 0x080800008 o& p- \! {9 K
- #define EEPROM_BYTE_SIZE 0x03FF
复制代码
3 Z: H9 x) g2 J2 f) C基础字节写函数
# r6 r% a4 c7 w+ r- ^; H( j- //Byte write
# P6 n t6 `/ ?7 N: H - void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
4 x, B& P7 i1 L& g( d - {
4 u) Q" O9 E4 M& P# i" p - uint16_t i;
! n: l3 y6 m$ Y* T0 M - HAL_StatusTypeDef status = HAL_OK;, u8 H9 l! t/ t& `
- O+ u8 b# r9 y( E2 p; h) N# L) ]
- HAL_FLASHEx_DATAEEPROM_Unlock();
% f7 \) k. k) Q& V - for(i=0;i<len;i++)
& B9 {9 q. d: ~# v6 d7 d - {
' }6 c; \3 c4 W- u( Q7 Q* I, m - status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
& y$ ~1 R! Z6 @- n6 W$ X - Data++;/ j# S [1 H( M* P0 m
- }) ?4 ]6 l" \9 l* O7 t& M
- HAL_FLASHEx_DATAEEPROM_Lock();
+ e) `. o" x. W - }
复制代码 ( @% f8 s1 V0 ?$ Z
基础字节读函数
8 m; q' i2 Y' g9 H' ^- <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read
8 M4 y) ~, m* @) ^ - void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)8 d8 ]3 u- @# M+ a
- {
5 t3 N9 I1 j3 R3 \ - uint8_t *wAddr;
! Y/ O5 G8 g- T6 c2 @1 s! b - wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);; H! Q5 q8 w/ h( W/ a$ [) O ]
- while(Len--)8 W3 Y" K. L. g. a, j
- {
' \9 t8 x1 [2 l4 F! ~ - *Buffer++=*wAddr++;
# k7 v# n$ n2 q: r1 \. H- _5 G% U) | - }% S* {" [* d# ^7 i& t* A
- }
复制代码 , R3 x: t% V+ c6 d$ @
带校验写读函数
; ]& v) A/ t; V* _( |如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。, y' b. x# y4 {; C! C2 n
对于写过程,需要将写入的数据,读回做比较。
5 }7 s5 ~3 y; @5 p0 Q对于读过程,需要将两次读回的数据,进行比较。# k' \) g! j: J: ~" J( o
如果比较正确,则操作完成。7 p$ d1 o. J2 I5 d+ j
如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。
* a5 F% Q7 \) u, q
/ y" a; `' k, f设定重复校验次数
' p$ y2 N: S. |! y! y8 T5 @4 R- #include <string.h> a5 @6 F0 Y; L8 D4 \1 x
- #define iEEPROM_CHECK_NUM 2
复制代码
' r. Z! S+ I0 n+ _4 ]: s3 v6 b& I- j7 ^4 o8 m P# T
带操作校验的写函数
" k# l' j) U# [) C, {' h- HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)& q3 x& ~* n+ Q9 s# P
- {# m5 n0 I" Y6 B3 _8 S I
- uint8_t buff[len];
0 J6 z f4 @5 g6 {5 i6 c9 | - uint16_t i;
/ A. }- C# x3 F' T9 r* l - for (i=0;i<iEEPROM_CHECK_NUM;i++), ^8 y7 g- a' @8 k$ B% O
- {
4 _+ V3 j* o, f6 y+ r4 Z - EEPROM_WRITE(BiasAddress, Data, len);% I7 a9 h- _' B9 j, X: a( E
- EEPROM_READ(BiasAddress, buff, len);
& A$ e0 h6 o: e# H: g - if (memcmp(Data, buff, len)==0)
) G; g* _. X! v" t, O - {
& K; _& D z! {+ N5 s$ |7 D - return HAL_OK;
6 B0 S: A* H1 y. F2 ? b - }
7 F4 t& V5 x0 j7 E5 L - }
. \9 P5 w! |( g* ~8 ^: `% b
4 K0 w" v. a" U# P+ j5 H- return HAL_ERROR;
4 Y# D+ \$ i4 w( W! | - }
复制代码 3 Z) I: X2 a/ A* R/ T4 Q% P
带操作校验的读函数) E; o; j6 U9 v! T) Z! r
- HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)( N( p+ D1 j. ]8 H
- {
( M7 m u+ h0 y* b3 u6 v* Z" A - uint8_t buff0[len];, u" u: p+ }; V, o! d6 W
- uint8_t buff1[len];
4 H: I1 i( ^# Q: F5 e* B9 D9 A; | - uint16_t i;
+ ~6 Q) J" ?* h) A. `3 { - for (i=0;i<iEEPROM_CHECK_NUM;i++)' }7 f0 ]4 _! e) ^- n
- {$ ]7 B* h8 a6 b4 ^8 Q0 s& [
- EEPROM_READ(BiasAddress, buff0, len);6 W K6 l1 {/ V4 g7 w, P2 H
- EEPROM_READ(BiasAddress, buff1, len);* @: D+ l8 n* B$ X
5 N, T2 C+ \$ b( a" g: T- if (memcmp(buff0, buff1, len)==0)
' |* {+ |0 z# E: s# T3 @ - {
/ ?4 ~0 [5 K9 i) q3 I: U7 }+ h4 y - memcpy(Data, buff0, len);
6 w( V9 z5 d) q0 y: a - return HAL_OK;
! `1 a8 a2 v, e. Q* E+ X2 r - }# S6 A4 y) n: ^# X/ C
- }
2 I0 V! a2 P2 ^; q7 C
( e: [! g$ \. e! x4 y' g. R; k- return HAL_ERROR;7 p: ]# U: _& [& W6 |) F2 A: t
- }
复制代码
3 U/ }) R3 k; v4 O& P% f% G! J其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。! t. _- K" a/ k l" C4 X0 ?7 h7 c
1 c( b _3 w+ D$ u2 }: i, S
需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。
5 D! K' o/ a8 ^
/ [$ V! c$ T( o% t& P6 XHAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:: ~9 w. s/ ?0 Z' j4 I0 L. q
- @6 m, u. C8 d5 A; `
- /**2 C; K5 D+ ^, t& x, A
- * @brief Erase a word in data memory.7 @, j4 A) G# `, l4 w, L
- * @param Address specifies the address to be erased.* e$ l! C( q! M; U% d& @' i
- * @note To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function; K, j$ K2 j$ @1 n
- * must be called before.+ M) k6 x. ?7 ?% S
- * Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access/ z i) n9 S7 k
- * and Flash program erase control register access(recommended to protect
; f- |1 a( @& U. G& c - * the DATA_EEPROM against possible unwanted operation).. Z4 J3 y3 f1 ^1 w3 @" N2 M S9 [
- * @retval HAL_StatusTypeDef HAL Status
, {0 E% j$ l; p" ?7 C - */
5 z v# L! @9 I) R( B - HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address) B1 \ T6 G) E& q& w$ Y
- {
' [. R% X" S8 h4 T) R - HAL_StatusTypeDef status = HAL_OK;
( r) h% @6 E4 J6 C P3 U - + X9 b# @! U# N' K0 }1 @
- /* Check the parameters */
+ N. E: h: Q7 X0 ~; K! u - assert_param(IS_FLASH_DATA_ADDRESS(Address));) ~" s7 l4 `7 o4 c
, o( M% O! F$ E6 _; D/ `- /* Wait for last operation to be completed */4 W; e0 ?5 Q+ q8 \
- status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);3 u2 [) `& z# c d
% U0 ~+ l7 ~, O$ U1 P- if(status == HAL_OK)
0 k/ w6 Q4 w, A" l5 T. C - {
1 H$ S# t1 q+ ?! t& u - /* Clean the error context */
* A- h$ z% X% I1 U - pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
: {3 a* T( a0 V
4 R% F' f; y ?8 c" w& {- /* Write 00000000h to valid address in the data memory */
$ B1 n( L; \6 c, E$ a+ {4 _ - *(__IO uint32_t *) Address = 0x00000000U;0 H; p2 r2 a5 N5 v( b' A5 U
* j# C4 _# J7 f+ B- X e- status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
, Y* S0 v# F/ Q4 L$ l7 Q - }0 y, O' x2 B! |) t8 @- w, s
7 r# [9 X% n; `2 g! H! t- /* Return the erase status */
# r6 N3 A* ?3 Q0 Y7 o' v - return status;
1 S4 u: \& }, H! y3 [9 e$ o. A - }
复制代码
. g- c% {9 ]9 i$ [/ b上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。
, q' s# s& M, ?# y) r; L6 ]
1 k/ h, h4 U4 u6 [$ I$ S0 i5 n9 E; d/ k7 E
|