你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32L0 内部EEPROM写读

[复制链接]
STMCU小助手 发布时间:2021-11-17 23:02
STM32L0 内部EEPROM写读' \+ e" m9 \) \* B* j
说明) A* N2 L! t* |
STM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。* {& S" K  H' H8 T) p7 E

( ^% t+ u9 }& q3 A% g# g基础写读函数
0 |4 _# E4 \5 c' Q/ X定义内部EEPROM的地址空间:
7 W% b8 e* S% W, m
  1. //STM32L031K6T6
    / Z. ?' G" R$ j* \1 F1 P( X
  2. #define EEPROM_BASE_ADDR        0x080800008 u3 _8 r* D) k3 _
  3. #define EEPROM_BYTE_SIZE        0x03FF
复制代码

6 G8 i8 D6 m9 J8 a6 l# x基础字节写函数6 G' _& K! P. `
  1. //Byte write
    2 ^6 w7 r3 A. H9 R+ I
  2. void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    % y0 f* \, M+ X. K/ O0 x4 F
  3. {0 m) v$ N( ?2 B' b+ i/ O  d
  4.         uint16_t i;
    5 y+ s' y8 c1 d% g
  5.         HAL_StatusTypeDef status = HAL_OK;2 k0 b, Z# \# j0 n: k/ M( c* W
  6. 7 p+ l. a: j' k0 ]% S& ]
  7.         HAL_FLASHEx_DATAEEPROM_Unlock();( [2 m6 T5 [# b0 U; E0 p
  8.         for(i=0;i<len;i++)) u; b0 _8 n+ X
  9.         {
    1 r# }( ]) B: ^! W5 b
  10.                 status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);* p* R7 D% @% x
  11.                 Data++;7 `! F: \& z9 e1 [- Q' L8 p3 C, ~
  12.         }' S0 ^. M( w. G
  13.         HAL_FLASHEx_DATAEEPROM_Lock();5 C. l+ V" w% w) {( k+ D0 q' a
  14. }
复制代码
  o+ x; S1 H% a( u
基础字节读函数7 |3 `. L+ ^. Q, e5 ~+ P
  1. <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read
    . |; I6 {- q* V8 G- e( T- j
  2. void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)
    5 g+ X+ l3 z' M* z9 V/ R
  3. {
    7 f- {8 {7 K" d$ c! C" A2 X
  4.         uint8_t *wAddr;& N8 N! A# i* q. W( m! H. @
  5.         wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);
    5 W7 x" ?# v* o. O' u$ \
  6.         while(Len--)# {% E0 C% s0 w+ r- q
  7.         {# ^# D8 u0 {. R  I* a) ^% U
  8.                 *Buffer++=*wAddr++;
    : H4 q. R; D- x! P1 N1 k. Z
  9.         }7 h- S* _0 o0 F  \# f" j& H4 v2 y
  10. }
复制代码
- S, ^3 ?' Q5 d# N, O9 g$ _
带校验写读函数
; e( L+ o; y0 B' \如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。2 O1 a; Q* S' `& x6 |+ S  D! \
对于写过程,需要将写入的数据,读回做比较。
1 N8 K' Y& ]  ~3 U对于读过程,需要将两次读回的数据,进行比较。! A( Q# j8 x: w* \0 W1 y
如果比较正确,则操作完成。+ g- P7 |% H/ U( _
如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。
' |2 K0 O! n. O0 q8 K3 D! R
6 E1 ]$ l) t$ O. {* @设定重复校验次数/ R1 z0 }4 N: W  _, E6 n
  1. #include <string.h>$ I' I4 Y! a; m  F8 C
  2. #define iEEPROM_CHECK_NUM 2
复制代码
  K" F( q% e( K# X% G
0 y+ E# q# r( C( ^  o
带操作校验的写函数
7 L& m* }" G# ?
  1. HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)& _7 E. ]9 t) ]1 ^6 Y2 M
  2. {
    : F+ ~- t- R6 G) J% w
  3.         uint8_t buff[len];
    % y( \: X, t3 c& n9 n* `( U
  4.         uint16_t i;$ E# Z3 c& H3 v. T2 X; B; U
  5.         for (i=0;i<iEEPROM_CHECK_NUM;i++)4 @% Y" E/ ^- d6 p
  6.         {3 L$ M6 `6 B! }" x& q+ p' n: h+ o
  7.                 EEPROM_WRITE(BiasAddress, Data, len);
    ) n- L4 I, f4 O* ~  R5 U, K2 F
  8.                 EEPROM_READ(BiasAddress, buff, len);
    3 q( ~% |  J! X  [: v
  9.                 if (memcmp(Data, buff, len)==0)  X! g7 m; O8 s! b& B; b
  10.                 {0 E% U. _& F; B" m1 y2 ]% r8 D" K
  11.                         return HAL_OK;
    5 Q' h  A2 `: s/ L
  12.                 }9 U( ]# ^' k+ e$ d
  13.         }( Z5 @9 }6 f1 c
  14. 5 s. ?0 z4 ^! ?
  15.         return HAL_ERROR;0 R1 E; \5 }7 R& H( @- G7 Y
  16. }
复制代码
8 R2 B1 C0 s- Z2 p1 ^( i/ v) W5 D1 `
带操作校验的读函数
- a$ @' o, Z5 b% [) J
  1. HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    2 w1 ?  O9 b% |; d! p8 P
  2. {3 Q$ _2 I3 O8 U7 c
  3.         uint8_t buff0[len];
    * Y3 a, `4 z+ R' ^1 ?' U! i; g* U
  4.         uint8_t buff1[len];
    " r8 a. U" a" D5 G! U% H7 Y, E
  5.         uint16_t i;
    7 x+ B- _7 {4 k  X: I) S
  6.         for (i=0;i<iEEPROM_CHECK_NUM;i++)7 A% Y  I% i% l
  7.         {
    6 t0 _6 [8 F3 L5 o' X. f, I1 O
  8.                 EEPROM_READ(BiasAddress, buff0, len);
    3 l6 j* z* y8 g% E) ~7 c
  9.                 EEPROM_READ(BiasAddress, buff1, len);
    8 a2 F: V$ ^- F8 f" r

  10. 1 B9 s  o: C8 c1 G, H
  11.                 if (memcmp(buff0, buff1, len)==0); Z  {- U4 U' o$ c7 c1 \' N
  12.                 {0 }1 [7 A" y, _" b4 |  J
  13.                         memcpy(Data, buff0, len);
    . o6 F$ I: s% A- ^1 T' g1 {
  14.                         return HAL_OK;
    ' [# e: T9 M/ A, P
  15.                 }
    9 I. ]0 f8 ^7 S$ T: _5 q, K, J. J
  16.         }* d+ k1 S+ u1 I( m& D5 o5 H

  17. 5 q2 c7 M, g3 q* t$ x
  18.         return HAL_ERROR;7 T6 }( ~5 b" M; E
  19. }
复制代码

1 s+ _. y8 t0 }/ L" w其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。6 }' v, O) k! f" X- V

0 V5 H2 C, x4 D6 F4 R; V" ^需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。7 U: N2 m6 n" L1 c
8 x) g8 K& X9 V/ d2 t) L
HAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:% h! t1 O9 X) p, k( T
& Z( K6 w8 H9 V9 ~
  1. /**
    2 g5 {" a2 n' E( h' L
  2.   * @brief  Erase a word in data memory.
    & A. \" M: N/ W7 o" `! m  i& K
  3.   * @param  Address specifies the address to be erased.( z# ]0 ]$ X2 K: Y( t
  4.   * @note   To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function
    ; u8 c* _- h+ b, T* ^
  5.   *         must be called before.+ d% E; X+ \! s  f% P& Z! z3 Y# Z
  6.   *         Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access% T) q0 w7 ?7 z( f
  7.   *         and Flash program erase control register access(recommended to protect
    ( v: v3 G6 o/ M# s
  8.   *         the DATA_EEPROM against possible unwanted operation).4 Q  O& c& F3 h; r( T: S+ l
  9.   * @retval HAL_StatusTypeDef HAL Status
    , A/ a  h2 F8 U. ?* ]  [3 P
  10.   */$ [/ i7 O4 V& W9 C9 N
  11. HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)) m9 Y4 t4 l- `& P! w* J. S( Z
  12. {
    . Y+ L6 ~, U' }
  13.   HAL_StatusTypeDef status = HAL_OK;
    / j4 E3 Q2 `: R9 G

  14. $ v7 ?% L' X  @$ t
  15.   /* Check the parameters */
    5 i+ ~( b5 P" s( Z
  16.   assert_param(IS_FLASH_DATA_ADDRESS(Address));7 t# V  w) v- E+ t8 w3 l

  17. 1 l6 V% v5 A7 p, X" t, Y
  18.   /* Wait for last operation to be completed */1 k& w- }' b3 ?
  19.   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);& a! h/ u0 O* u

  20. ! g. G4 r2 K  A
  21.   if(status == HAL_OK)
    ; Z! ?% _* T6 W3 U
  22.   {
    ( d: ?% k  D( @4 W; C
  23.     /* Clean the error context */; D/ E; t3 i$ K( L; M# n* e/ y0 [
  24.     pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;  Z- {# p1 F9 J3 @% ^* e% Q% H
  25. * r) Q7 ]# K" i1 y. ]) {
  26.       /* Write 00000000h to valid address in the data memory */
    ( w  N% @  c3 {. A6 d5 l& X6 L
  27.       *(__IO uint32_t *) Address = 0x00000000U;8 J/ `6 w6 p% I0 h
  28. . M8 i9 W- U9 p
  29.     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    $ {$ L$ K2 M$ k9 H, u: E2 b2 T8 P
  30.   }
    5 ]5 e- Q0 w8 c& r$ c

  31. 4 e. D' K3 C+ l( D: E
  32.   /* Return the erase status */1 j: ]8 C1 j/ r) [6 @: l( X
  33.   return status;$ w1 [' `" U1 g! K3 l- W. Z" O
  34. }  
复制代码

. H9 G) T8 R# h7 G, C上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。3 U8 m4 n; [. O5 g
2 q/ [7 Y; a9 L5 l( {: L* ]* S
. F, o* _: m; @' ^" \9 a
赞 收藏 评论0 发布时间:2021-11-17 23:02

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版