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

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

[复制链接]
STMCU小助手 发布时间:2021-11-17 23:02
STM32L0 内部EEPROM写读
6 k5 }( {. O% \5 ]0 A+ Z8 q说明- J) e, l) e# L0 `! ?  a0 g
STM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。
  W% S" h9 o* J! k& F
. Z! N  b3 S# s) x, E基础写读函数
0 M6 T2 S% P; H1 q2 l2 e定义内部EEPROM的地址空间:
- ]; G! g8 O, t: V
  1. //STM32L031K6T6; V8 L& m$ g6 M* Z4 S$ ?
  2. #define EEPROM_BASE_ADDR        0x08080000- z$ Z3 i; z3 H9 ~; M
  3. #define EEPROM_BYTE_SIZE        0x03FF
复制代码

. b" e1 a$ ]8 D; o: S基础字节写函数; f% m: R9 \$ H3 c3 B! a
  1. //Byte write8 J/ e5 @% `' @& H0 K
  2. void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)2 i5 \! h+ Q$ }2 _! O
  3. {
    # \0 q- E1 H5 H) A* t! X
  4.         uint16_t i;
    0 J# ~2 \+ W1 f2 ~: D
  5.         HAL_StatusTypeDef status = HAL_OK;2 |- X* _1 x3 O5 l
  6. + j3 X$ \/ d6 i. U
  7.         HAL_FLASHEx_DATAEEPROM_Unlock();7 M2 s/ l2 D% V, s% m+ _! D
  8.         for(i=0;i<len;i++)( y* W; L# ]( g, q
  9.         {
    5 S  q6 L% j4 K' \' P3 l2 U4 B
  10.                 status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);7 x2 G3 a9 `" r3 Y" O! g1 N( _
  11.                 Data++;
    1 {/ S, E0 @9 e" J0 J% |" t
  12.         }
    # |* P: c; _* y
  13.         HAL_FLASHEx_DATAEEPROM_Lock();
      d& S4 `1 W- l$ H! I+ E9 |
  14. }
复制代码
4 P) O# G2 Q) P6 T9 y  o
基础字节读函数
5 v. S: E2 F8 X- f: g9 f
  1. <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read# b6 K1 h' X6 s( K
  2. void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)
    ) L+ }2 }, C/ D
  3. {
    * r1 W( I) P4 h) R- j) \7 }
  4.         uint8_t *wAddr;8 _2 q2 m/ `; r; b; Q
  5.         wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);7 U3 S$ I9 y0 O) |' e
  6.         while(Len--)' ~$ t" ]. {7 n/ j
  7.         {, h% q* C8 M+ U: K8 Q
  8.                 *Buffer++=*wAddr++;
    + Q0 t/ t1 V' Q5 Y* R& ]
  9.         }
    & S* V( O: {: D! h& k* N4 T! u5 o
  10. }
复制代码
6 g& T% j& a( X) N0 j
带校验写读函数# U: a- [7 r4 X# l
如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。& K1 A/ y$ Z6 {- j. m% _5 u
对于写过程,需要将写入的数据,读回做比较。
! F$ {9 j- n+ Q. t5 @对于读过程,需要将两次读回的数据,进行比较。5 i1 a! t, U# t+ j8 B& o; \  D
如果比较正确,则操作完成。
/ Y' V4 T- j8 F6 U+ `如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。
. G) }: n; n+ Y! V/ G$ ?. G4 {+ I- Q: M; Y  B9 ^4 Q
设定重复校验次数
) K; O. H3 _, L
  1. #include <string.h>* `" F" e# ^- l; A
  2. #define iEEPROM_CHECK_NUM 2
复制代码

7 ^# a& H5 z2 G4 P; s6 f. u6 k6 o( n9 V4 O: D1 f
带操作校验的写函数
1 T- H6 U  L5 i, I7 m- p) E
  1. HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    $ r6 v2 i8 g6 n; c
  2. {
    0 Y9 E7 K1 |* I8 p, W) D& ]- b
  3.         uint8_t buff[len];
    8 c0 g/ K6 E7 ]. b# ]7 r
  4.         uint16_t i;7 R7 o9 {6 \8 q9 g& z# @/ j
  5.         for (i=0;i<iEEPROM_CHECK_NUM;i++)
    : D: Y6 w8 h7 Y
  6.         {3 S) |, r1 F- Y, _
  7.                 EEPROM_WRITE(BiasAddress, Data, len);" d7 D2 a* V; p* ?4 o: [
  8.                 EEPROM_READ(BiasAddress, buff, len);
      }5 V& A! [1 E! p! g0 P
  9.                 if (memcmp(Data, buff, len)==0)
    * V7 g/ X  W% _2 `
  10.                 {
    ; u" c0 d6 X( k! i" _; A
  11.                         return HAL_OK;$ M) g5 [2 ~# E9 M( R
  12.                 }! Q6 I7 b8 V# x% X" S
  13.         }
    5 s/ ^$ Z4 c3 c, X: v& N* d
  14. ! f9 U: e' k3 G! w5 w0 b2 I
  15.         return HAL_ERROR;
    # |& L% U4 {0 B4 A; o# Q, b, i6 L/ Z
  16. }
复制代码
/ S" u! q2 @9 h9 a! O( t2 `5 f, \
带操作校验的读函数7 R7 j* ~% J2 Y$ l) F  |! h
  1. HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    & @- @5 j1 p* o
  2. {
    / J, [1 X6 o, H& Y( O, x
  3.         uint8_t buff0[len];9 J- ?; K7 \- x$ f, W* ]
  4.         uint8_t buff1[len];
    . q4 A7 X8 a+ A+ a1 S5 Y" W
  5.         uint16_t i;
    7 H0 C. a3 |" _5 k5 u
  6.         for (i=0;i<iEEPROM_CHECK_NUM;i++)
    # {  {$ W! E, z4 C( h* K# q
  7.         {8 {* m  }' Z* A1 Q
  8.                 EEPROM_READ(BiasAddress, buff0, len);
    8 Y$ I; H1 u8 }. [/ u
  9.                 EEPROM_READ(BiasAddress, buff1, len);' x" ]# D7 L9 Z. X

  10. / w  R1 W& k  K+ Y: Y" G/ J6 I$ V
  11.                 if (memcmp(buff0, buff1, len)==0)
    ( B" s* E/ t9 a2 _! U% V4 E
  12.                 {
    5 G: ~7 |7 Z8 G: }" ]
  13.                         memcpy(Data, buff0, len);) V6 v! w0 K5 M  p
  14.                         return HAL_OK;& N4 Y, }3 F7 R1 H8 g; u/ E
  15.                 }
    , y) ?: ?8 ?  i3 \  i
  16.         }
    4 l+ {, l: F. u
  17. , Z1 \8 N0 A' e% @, J  o
  18.         return HAL_ERROR;
    - D% j6 E+ a: R& M
  19. }
复制代码
* F  C! b: m+ h/ i# O' h5 g. {
其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。
+ M2 h3 ^# ^& }$ E# i& I' t: E; F9 [# `
需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。
8 F$ _- X2 j! `# G
9 A% z( x* E: }! }1 k& THAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:7 S+ n9 W$ Z# `9 k1 T! F% \1 n- q

1 l5 x/ W6 c' U) q5 T/ t
  1. /**7 F% J( e; e3 y
  2.   * @brief  Erase a word in data memory.
    ( _6 @3 H- L; L
  3.   * @param  Address specifies the address to be erased.
      P3 j- r0 m; T% Y
  4.   * @note   To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function' w& U' P# b2 d1 f% n, s2 k
  5.   *         must be called before.
    0 g* @# a  {3 z9 T4 d5 c) R8 {2 A! a
  6.   *         Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access* _: r% h  Z, R$ w/ \4 b% |: k% W8 o
  7.   *         and Flash program erase control register access(recommended to protect
    5 k" Q6 P3 h) r! t: ]
  8.   *         the DATA_EEPROM against possible unwanted operation).
    3 p: ]1 a( k) V+ F
  9.   * @retval HAL_StatusTypeDef HAL Status" _6 ?5 d! ]4 F( a# B# ^
  10.   */
    ' L1 ?; O4 i4 b, m
  11. HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)2 o1 S' W7 O. B" y
  12. {4 i* R- h2 z" W$ L* X
  13.   HAL_StatusTypeDef status = HAL_OK;/ n0 o% E) [5 _" V5 B3 o- h9 }- A, I
  14. % _0 d- P' t" G- d, w2 a
  15.   /* Check the parameters */
    & C5 z% @4 T) c% t  y9 A+ Z
  16.   assert_param(IS_FLASH_DATA_ADDRESS(Address));. p, I! W9 \9 j8 X* L9 X
  17. ; v/ q4 a6 ^8 t# Z) B
  18.   /* Wait for last operation to be completed */
    + X5 [  G/ ]: i8 o$ @; f" h6 _
  19.   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);; m3 K8 q. s7 }
  20. 1 x9 C- |% ~9 W4 ?% B: b
  21.   if(status == HAL_OK)
    ! P% l, A8 p4 p0 _
  22.   {
    : }( H. k' v" A+ T) z1 T" u
  23.     /* Clean the error context */$ y- q5 m9 ~* Q+ }* t. i" k
  24.     pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;4 G" e% ?; C. F" A+ x

  25. 9 R* w0 a. K! ?* }4 }
  26.       /* Write 00000000h to valid address in the data memory */: Z+ X9 W6 i8 D& U" F: Y
  27.       *(__IO uint32_t *) Address = 0x00000000U;
    - n# a9 o$ g: B

  28. # H8 N. H2 k8 P& ]3 i, V9 j
  29.     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    & ^$ i. y6 n5 U* b. ?
  30.   }
    * ]/ L( ]6 A! p# f

  31. 8 t: D( S; J, u! b! @  C0 Y3 ~' t
  32.   /* Return the erase status */
    * o3 R& y5 y3 K9 Z
  33.   return status;
    ; n* w2 y* i( t; e% P5 L& g  |
  34. }  
复制代码
5 a% ]3 l& g( C4 _4 `
上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。
4 n6 c1 v' N7 A) b& F+ L7 k# ?% {3 v" A5 y. R$ I

* |* G/ x3 n' V, {) S8 T) h% c
收藏 评论0 发布时间:2021-11-17 23:02

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版