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

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

[复制链接]
STMCU小助手 发布时间:2021-11-17 23:02
STM32L0 内部EEPROM写读9 @8 a) o! U+ F6 m: Q* u
说明& K. {" i* ^8 f* b
STM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。
% m) {. \9 ?7 O4 {1 X
' P9 d( Y% v2 \) ^- Z. d' {基础写读函数9 M- c% ~$ F9 H
定义内部EEPROM的地址空间:
( C( x- j; D1 {" g. G( l; z2 K
  1. //STM32L031K6T6
    * {8 t* B9 N/ p" F- ]& U
  2. #define EEPROM_BASE_ADDR        0x08080000; r# ~* H+ w# B$ g0 z* B" D- z
  3. #define EEPROM_BYTE_SIZE        0x03FF
复制代码

0 A/ y/ U( T8 e( a+ P6 `基础字节写函数
# K9 ?1 h0 G' H3 l) t9 Y
  1. //Byte write
    : ], }( K! S5 u" B
  2. void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)4 `6 N5 F7 z1 u* y
  3. {1 f/ a0 v+ A# v8 m2 v- H. a' t/ L6 K
  4.         uint16_t i;
    4 z9 S8 R( k% y5 y) {' `
  5.         HAL_StatusTypeDef status = HAL_OK;$ x" i4 {+ E2 f
  6. 9 I, m+ q+ ~! W2 ?9 K: P
  7.         HAL_FLASHEx_DATAEEPROM_Unlock();
    % V& Z" i# H: d$ U! H/ o5 A' ^
  8.         for(i=0;i<len;i++)
    9 x, H( o1 W. g1 C/ Q+ }2 B
  9.         {
    : H# _) {  Y5 t4 D7 s! N6 R. a( x
  10.                 status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
    + B% q# Y9 W& Z& B% t: n& P2 y- l
  11.                 Data++;
    ) ?4 Y$ o8 @- E0 W3 n. d
  12.         }- i+ l6 f" n' u1 h
  13.         HAL_FLASHEx_DATAEEPROM_Lock();
    4 v! L, i! O- A$ ]6 A
  14. }
复制代码

/ s6 M1 E2 V4 Y0 M. X8 V基础字节读函数3 L6 Q8 K5 [4 x- j
  1. <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read
    ' ^5 a2 `8 C/ X; y* ~, J& z
  2. void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)' D( }2 `: ~" F) Q6 a$ I
  3. {- `; s7 T0 f- P+ p1 P7 B8 \  u# q* W
  4.         uint8_t *wAddr;
    8 j: Z: s( ]* W$ O" |* ?- d& p) p' l
  5.         wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);3 Z" p- S# D. ]/ K
  6.         while(Len--)
    * G' u$ v  {* j; N
  7.         {
    # s( ~$ n( `2 V) S+ s0 Q4 g
  8.                 *Buffer++=*wAddr++;
    ( {" G4 ^+ c% `3 Q4 i8 c
  9.         }: }6 H& O) S! A6 L
  10. }
复制代码
/ d5 j* p: s0 Q1 i: v0 R
带校验写读函数2 k( G( O' p. X
如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。
- {3 o6 b' |4 M) x5 X6 p对于写过程,需要将写入的数据,读回做比较。
/ b$ c" D- B7 C! S) `对于读过程,需要将两次读回的数据,进行比较。( X& f( \# U  \9 K+ e
如果比较正确,则操作完成。
: \1 Q7 \- ]' [如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。  m$ P7 r, P, {) Z5 v

& ]6 u: L6 w1 Z+ w4 [设定重复校验次数6 a% D% ^1 z' O/ [+ n7 q/ B4 Z. V
  1. #include <string.h># U+ t, d9 h, o; I- }
  2. #define iEEPROM_CHECK_NUM 2
复制代码
+ ]6 C6 E% u3 ]) x

8 t% I( N3 [9 z' e! d带操作校验的写函数
, x1 Q' l+ ^; m! g$ K) {
  1. HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    3 D  D$ }* `4 V2 J; ?
  2. {8 u% d0 p! ^+ p# g4 {/ @  C9 W
  3.         uint8_t buff[len];6 U: I8 t/ L1 B. }
  4.         uint16_t i;9 v9 t- ]  K" E+ [" D
  5.         for (i=0;i<iEEPROM_CHECK_NUM;i++)0 S) d' S3 J: t* R! k, X+ q# |: N
  6.         {
      X& b& B$ u# c+ U/ n- d! t, s
  7.                 EEPROM_WRITE(BiasAddress, Data, len);% ^7 @0 O5 |5 [3 y, {1 q8 K
  8.                 EEPROM_READ(BiasAddress, buff, len);% C. ]1 z6 @+ R) b
  9.                 if (memcmp(Data, buff, len)==0)8 }! I. h2 v9 I8 o6 j6 B# b
  10.                 {
    * b: r1 Y1 ]5 c* {
  11.                         return HAL_OK;
    - f: I/ g2 B/ o+ o4 i3 ]# @; e% `6 J
  12.                 }% `% `" m/ V' V
  13.         }+ z+ Y9 u* M2 M8 o  i

  14. 1 C5 b" I4 o# K- B
  15.         return HAL_ERROR;1 \1 _+ i$ G; H, p1 v; `( C' e
  16. }
复制代码

+ e/ j) Z% p/ L" g带操作校验的读函数
) g- ~! B! S4 Y
  1. HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    9 I2 p& e6 C/ H! c! ?+ F2 i7 H# S* b
  2. {
    1 L5 l& [: _1 Y7 v/ T
  3.         uint8_t buff0[len];
    8 S. e- {' A; c. N
  4.         uint8_t buff1[len];
    3 ?1 Y8 n" a* E2 q% V. d- U, W
  5.         uint16_t i;! z  [0 B: d$ y9 [* [3 V
  6.         for (i=0;i<iEEPROM_CHECK_NUM;i++)! C: D7 |7 s* s
  7.         {/ T2 D) q) z/ C
  8.                 EEPROM_READ(BiasAddress, buff0, len);
    3 T* |7 G$ c0 J  s$ n& p6 x" n
  9.                 EEPROM_READ(BiasAddress, buff1, len);, M3 u* z$ E% L# `7 D
  10. ' j0 d" s: X* _1 ?& Z
  11.                 if (memcmp(buff0, buff1, len)==0)1 U+ A! `4 W3 ~  V" @
  12.                 {
    7 q" ?) [% U9 ]" d! v
  13.                         memcpy(Data, buff0, len);
    ( w' G1 |$ i4 N- O3 Z
  14.                         return HAL_OK;
    0 n- b/ }' N& ?3 o' r( ~
  15.                 }, g1 x. C4 z7 m8 N
  16.         }
    ! X% G" r3 N7 V/ n7 i
  17. , {) x$ I' x6 |7 `, s2 a, x
  18.         return HAL_ERROR;2 z$ |) X8 r& t! P1 T
  19. }
复制代码
3 L# A( c- h- |. @8 i2 I
其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。" q! _9 N7 ^) w, \3 R2 h

! ^" d5 H- P/ c; Q& U需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。
% R2 @" i9 u. a3 g  w
8 O: |1 l' h) @HAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:
8 [9 w& c* h2 R* E8 P! P1 c7 b8 V* f" G! b
  1. /**
    ) h9 y# c$ m/ E& p- T: L  K
  2.   * @brief  Erase a word in data memory.0 q9 c) p2 f  a6 i7 v
  3.   * @param  Address specifies the address to be erased.7 I1 J( }0 C4 n9 L8 ?+ l3 p7 O
  4.   * @note   To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function  {8 F( @( B4 d+ a6 [9 A3 s8 l
  5.   *         must be called before.  n7 M; x) u, P& a+ {: h( g4 P% T* }- D
  6.   *         Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access
    : d- k' t/ Y: H2 Z, w8 K
  7.   *         and Flash program erase control register access(recommended to protect
    / |2 T& ]+ W) k4 N
  8.   *         the DATA_EEPROM against possible unwanted operation).
    / G! s- w, M' C$ h
  9.   * @retval HAL_StatusTypeDef HAL Status
    / u" i2 {( q* ^% p, Y4 `* T
  10.   */3 g" G8 J( }. Z7 i
  11. HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)
    - B1 v  ?, o+ T
  12. {& m# M. ?" ^4 S$ i. f
  13.   HAL_StatusTypeDef status = HAL_OK;
    ! ?$ ^/ P5 @  u; x9 H

  14. . v! r! U8 X1 e
  15.   /* Check the parameters */
    2 n; _) g( r5 n
  16.   assert_param(IS_FLASH_DATA_ADDRESS(Address));
    3 ?  q/ o8 I! L7 O. y
  17. ; d) [7 u( S. Q! s: m- i
  18.   /* Wait for last operation to be completed */7 [% S! l& c+ `6 A5 X& l7 [
  19.   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);+ e: ^5 w, c" b; ?$ ?7 U

  20. 6 {: ^; d# n4 m) J
  21.   if(status == HAL_OK)
    9 |* |* E* `) d+ i- _8 F
  22.   {
    / _, s2 K) g/ |; D0 G
  23.     /* Clean the error context */
    - P& B+ ^& a, c
  24.     pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;7 \4 S# @% p+ q+ w  }4 {: N
  25. ! V8 u$ d9 U( m# z2 g. U/ w& q
  26.       /* Write 00000000h to valid address in the data memory */
    ; h+ W# q- S( U
  27.       *(__IO uint32_t *) Address = 0x00000000U;
    ! y- e+ K; k) t7 c4 l7 s
  28. ! p4 L" _; s' o: [
  29.     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    + }; C! @' _4 x# l6 U7 U
  30.   }" Q/ k2 H& Y# [* C+ N
  31. 4 U' v! }$ r' [$ h0 C+ e. @
  32.   /* Return the erase status */
    2 W. z! A4 j& `7 }( }- I, z
  33.   return status;* M9 t- I$ L8 P/ j+ L0 E! s
  34. }  
复制代码

1 C6 n- _- l" S3 q上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。. z- o- x/ N5 Y

$ q" P; u. Z. V  a
6 X" S" E9 l5 T9 @0 a
赞 收藏 评论0 发布时间:2021-11-17 23:02

举报

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