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

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

[复制链接]
STMCU小助手 发布时间:2021-11-17 23:02
STM32L0 内部EEPROM写读: b6 O& t7 _( p9 J( G6 k6 Y$ I: D8 H4 g
说明1 T; r; P# I% L3 Z
STM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。" m5 p' H# j7 Z
8 }6 Z( T3 }& K& g& n8 z/ B
基础写读函数
; N5 e# R3 D' o  ]定义内部EEPROM的地址空间:
" g& q4 j! b# u: n
  1. //STM32L031K6T6
    / v6 W9 U( V/ p; V. N: M' |; _6 C; D
  2. #define EEPROM_BASE_ADDR        0x08080000( H1 \& }0 s$ R9 B! n7 L5 L
  3. #define EEPROM_BYTE_SIZE        0x03FF
复制代码
; v* Y% |! R2 }% ]: y
基础字节写函数
- |8 X. U3 @- w# S
  1. //Byte write
    * Y! D6 F* `  X/ z8 T/ H+ ~
  2. void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)* c4 m& U8 c) ^( J
  3. {- g8 O! S+ m+ S; S; Z
  4.         uint16_t i;
    9 @0 J/ ]! U1 s3 T+ n
  5.         HAL_StatusTypeDef status = HAL_OK;6 K, S: ?  @' G
  6. 9 _0 @- _5 M5 }( e# L
  7.         HAL_FLASHEx_DATAEEPROM_Unlock();* l' `% R+ l2 `4 Y
  8.         for(i=0;i<len;i++)
    : \9 Q) P3 E+ l9 L4 m8 B0 ^
  9.         {' y: E2 h+ a, {
  10.                 status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
    9 L- e* ]+ q8 x# s
  11.                 Data++;
    ! Q, F0 E( o- f' J
  12.         }( ~, d' ]% {; l# Q9 p
  13.         HAL_FLASHEx_DATAEEPROM_Lock();( }+ U( A- ]8 h1 a- X. B" h
  14. }
复制代码
% {9 g! S) J9 h! [/ l' r7 h) q4 S
基础字节读函数
% O% E. D. a" ~9 S. }: K2 p
  1. <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read+ {9 }/ b4 G, I! I
  2. void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)' ]9 g! @% f+ y% O
  3. {  n& P# W. i+ o5 A# T8 ?/ z
  4.         uint8_t *wAddr;/ V8 W: W9 e2 W  l8 F; J
  5.         wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);
    $ l" H( A2 O! v7 v# O
  6.         while(Len--)
    ) C% D7 |1 z- d2 I2 }5 a# u5 A- o, W
  7.         {
    4 [# H/ W, x# `4 H5 ]' v
  8.                 *Buffer++=*wAddr++;
    ; @5 S, Y# K( b1 e, F
  9.         }# D. T, t9 @3 s$ \! o
  10. }
复制代码
. u1 ~* s+ J8 ?6 j$ S+ A8 I
带校验写读函数* ~! L$ {* _; F: E
如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。" J4 V% i( h% C' v
对于写过程,需要将写入的数据,读回做比较。; d( n; L: i- P7 }, `2 a7 d, E& |
对于读过程,需要将两次读回的数据,进行比较。9 O) b/ e4 L5 r' m5 b
如果比较正确,则操作完成。% G# u  e' K& ]) ]$ v+ _
如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。% ~& A& V. g% \* S& e  T- `
9 z( m( e' I9 |5 f3 C7 |  d) x
设定重复校验次数
8 _7 F$ H8 d1 o9 r: t
  1. #include <string.h>
    2 K5 i/ _6 V' i& @( D+ g% w- q+ J
  2. #define iEEPROM_CHECK_NUM 2
复制代码

# |4 {" i' O1 x; j3 V, l" h: l1 r7 z6 K9 F
带操作校验的写函数/ p3 Q' B9 W: i4 @  }9 \9 M  I: p1 S
  1. HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)4 n' Y" _, N4 X) D7 X+ {  w+ L. \
  2. {
      b& N5 ^+ c" |  @& B
  3.         uint8_t buff[len];
    0 j% v6 P6 w# O) \2 Q# f& Q
  4.         uint16_t i;
    " U% U! q: g) [! D$ j
  5.         for (i=0;i<iEEPROM_CHECK_NUM;i++)2 N1 o% c1 j' E: h, b' f
  6.         {7 c& V/ W2 c: S( o% ]
  7.                 EEPROM_WRITE(BiasAddress, Data, len);
    . l% L% ?8 T8 u: t- R
  8.                 EEPROM_READ(BiasAddress, buff, len);
    6 `6 \! ?% x1 @& b. o
  9.                 if (memcmp(Data, buff, len)==0)
    1 `! c( m8 _, N5 d& N3 H
  10.                 {! S; S1 k+ e2 R% e2 |2 v- N0 O, s% O
  11.                         return HAL_OK;* C9 b2 f  n, w
  12.                 }- V  `4 s2 b& _! E
  13.         }/ T% w* n, j$ z' s( T6 f; [

  14. + @$ g: e, s7 w& e1 ]. u1 s+ u( P
  15.         return HAL_ERROR;
    ! P( g: S3 N# I6 y8 Z1 S
  16. }
复制代码
$ H* K7 m% d# r- M' S) }) R! Q! @
带操作校验的读函数
3 s; I0 C" R2 g- H* t
  1. HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    * X% a5 M+ J, T6 D" p
  2. {
    9 c& Q9 ~; s- v: N6 l
  3.         uint8_t buff0[len];; X- R* H. X# S+ D! l: o
  4.         uint8_t buff1[len];
    7 K# ?$ }$ p3 e0 i
  5.         uint16_t i;# W- n: \# d3 Q  W
  6.         for (i=0;i<iEEPROM_CHECK_NUM;i++)  b  ~2 |0 V% a6 |( d6 o. a
  7.         {& [2 x) h% R9 t/ @9 K
  8.                 EEPROM_READ(BiasAddress, buff0, len);
    4 I+ L1 K5 Y: g& o% x8 y: G
  9.                 EEPROM_READ(BiasAddress, buff1, len);
    6 c3 y& {% h0 V6 o
  10. * \( V! j& N; H" o- `2 |
  11.                 if (memcmp(buff0, buff1, len)==0)
    # ?4 E2 \! r1 E5 p
  12.                 {$ Y2 i. h9 D/ d. G& k
  13.                         memcpy(Data, buff0, len);4 Q7 o8 P  q9 a& f* ]2 p4 |) F: n$ G
  14.                         return HAL_OK;
    7 k& S% ~' Y% R7 N
  15.                 }7 A& n* r- @' J1 C; B, w
  16.         }
    % }7 I1 i. J3 K. i6 |2 y( I

  17. 1 W3 ]' d# Z$ G2 {6 D
  18.         return HAL_ERROR;# d* j5 W0 s4 M) V$ S5 u" n
  19. }
复制代码
; I$ t% ~* o+ c! }: v1 ?
其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。' D; m3 A$ V' l8 \+ M- I9 Z

+ N9 _+ n8 w$ l+ i8 `, P4 j! w+ O需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。) y. ?7 V0 b5 C1 W% _

1 s; e9 k( U0 k" Y+ b. uHAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:
" U5 d7 v$ D' h7 c: }: J7 ]! b# D0 @2 ], q1 L" M6 _4 a! `
  1. /**" @& P) {8 Z# F0 u7 I0 k7 A
  2.   * @brief  Erase a word in data memory.
    9 J/ O5 A* f# J! u% D! |+ W, D
  3.   * @param  Address specifies the address to be erased.
    4 Z/ u9 R1 Z( R3 n" [
  4.   * @note   To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function% M. H$ |1 D, r
  5.   *         must be called before./ D% V- S( j' g+ Y
  6.   *         Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access
    4 ~8 w% ]2 a- A! F$ N
  7.   *         and Flash program erase control register access(recommended to protect
    3 ]2 w- V# G/ T9 U
  8.   *         the DATA_EEPROM against possible unwanted operation).
    7 L, K, T6 U9 k! V4 A* B: `% b1 d
  9.   * @retval HAL_StatusTypeDef HAL Status
    , \* m6 N4 w. ^3 H* G  i
  10.   */
    $ x$ Y; M1 k$ ~% h; C0 ~$ X, B2 B
  11. HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)
    $ z; n3 g  q7 _2 \$ u2 Y
  12. {
    7 l' v5 K  N& w8 s; V' @/ A
  13.   HAL_StatusTypeDef status = HAL_OK;' W: E2 I7 K; |- w. G8 s/ O: h
  14. 7 w$ t9 S' t7 H' e& @/ l9 V
  15.   /* Check the parameters */
    / M: I$ @7 }* P) d( C
  16.   assert_param(IS_FLASH_DATA_ADDRESS(Address));: W) p0 T4 F* u

  17.   H) g" M3 [4 q: {7 p
  18.   /* Wait for last operation to be completed */
    % b& h% o+ _5 x- p
  19.   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
      g2 b( I# K* n3 n: r
  20. 5 e3 o* S% W5 N4 \3 F% z
  21.   if(status == HAL_OK)
    ) k( r% v! [0 e$ c
  22.   {
    ; h  @" e5 E4 C1 k& O6 u, d
  23.     /* Clean the error context */
    $ X8 t# F! ?' e) h! I- ]# N
  24.     pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;: l. j! [1 s" q4 Y# E+ V/ T
  25. # n( o, F  b5 q, Z4 j
  26.       /* Write 00000000h to valid address in the data memory */9 T' J4 G  W/ u- p
  27.       *(__IO uint32_t *) Address = 0x00000000U;
    ; E! @7 i1 R) K$ S5 [5 P& D

  28. 0 ^, J+ n9 P  r* B1 k6 ]% G# V
  29.     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);; `( E1 a" i# W, |7 K
  30.   }
    $ Z* m, G0 I, \  j2 H
  31. 7 P* E( y6 H; X' \0 n9 W
  32.   /* Return the erase status */
    * Y2 d- F0 \) m" T+ M( r" V
  33.   return status;8 V# }5 I& G# [. k) n
  34. }  
复制代码

% s# C" ^4 _8 ^1 p: l; M: h9 L上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。
2 x" J$ e0 Z) i, r4 f9 c$ x
/ @! @1 I& I  ~: L
8 T, Q  J8 Z7 C) w9 m" C
收藏 评论0 发布时间:2021-11-17 23:02

举报

0个回答

所属标签

相似分享

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