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

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

[复制链接]
STMCU小助手 发布时间:2021-11-17 23:02
STM32L0 内部EEPROM写读# c' @. ]1 F, }3 V: D2 J7 u5 f
说明
0 o) h! k: I9 p' _5 fSTM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。) _  ~6 Z% }: `% b
  r9 m$ F, j% c) Q% K$ S
基础写读函数- |6 {" M0 u2 a* I2 k* X
定义内部EEPROM的地址空间:' X/ n& i# c  y8 c  F2 Z
  1. //STM32L031K6T6
    - ^# e4 W2 w3 |0 P4 M$ O
  2. #define EEPROM_BASE_ADDR        0x08080000) ^! y! q8 T; s8 P$ g8 T
  3. #define EEPROM_BYTE_SIZE        0x03FF
复制代码
. p6 e% P3 z# e
基础字节写函数- ~5 N7 \/ U- s5 l
  1. //Byte write7 w$ j7 m5 k1 s+ j/ g" l
  2. void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    6 U1 E/ Y% _( ~/ p5 T
  3. {- H; M4 Q( u: P9 E( C7 f$ Y
  4.         uint16_t i;3 E& I- T5 I4 E, a' F
  5.         HAL_StatusTypeDef status = HAL_OK;
    8 Y7 {3 k- O6 v: t' L6 S

  6. 5 g: p; r& x4 h3 {
  7.         HAL_FLASHEx_DATAEEPROM_Unlock();: L1 r- {; h! s) E
  8.         for(i=0;i<len;i++)
    6 \2 A+ y6 W0 G" g
  9.         {
    6 R/ L/ Z. S) J# c
  10.                 status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
      D9 c$ B( G, n4 G/ D& @
  11.                 Data++;# D% _% B+ q) r& l" `: n
  12.         }
    ' S7 g( L8 L0 Q
  13.         HAL_FLASHEx_DATAEEPROM_Lock();- a9 p) ~2 e4 G; ?4 Q- N
  14. }
复制代码
# |3 ~. t( A/ p  S
基础字节读函数
9 b: Q! u. |. Y) k" }, T
  1. <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read1 s* T+ e) @$ q5 v6 b) A9 u" {
  2. void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)6 o  D1 c3 o, d$ Q- @
  3. {
    " p  |2 k' o2 _; B# u
  4.         uint8_t *wAddr;
    $ Y6 V  K) i. Z# o$ E* D
  5.         wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);; g6 H" X1 i8 k. j5 k4 m7 M
  6.         while(Len--)
    * w( c. B) H( k& Z
  7.         {
    7 }& v5 T5 e  O- |2 E% |
  8.                 *Buffer++=*wAddr++;
    3 m7 N' n% J3 [+ d3 d* |2 U8 h
  9.         }3 Z* |" `! p( _. [1 Z
  10. }
复制代码

- K' e4 Y% X0 D' j+ P4 |7 }2 z带校验写读函数
6 y/ ?) q- Y! N如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。8 s+ X, o# e8 @) i9 ^6 Z* H7 G' G
对于写过程,需要将写入的数据,读回做比较。- s3 g+ J+ f  {% K$ c0 |; X
对于读过程,需要将两次读回的数据,进行比较。
- Y( i7 c- K% ?+ _" c3 K如果比较正确,则操作完成。
0 V5 ~2 k2 m1 D8 o& l1 l4 x如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。
$ P5 N; L1 f6 H" F0 u7 g; l6 w" K7 j" \! O1 |$ _
设定重复校验次数
) {- N" y0 u0 e( m
  1. #include <string.h>. P1 P! d2 e. W* |2 A% Y/ d" y7 @
  2. #define iEEPROM_CHECK_NUM 2
复制代码
+ M1 b6 I) t/ d0 h- Z: a

- \; Z& [5 M) e6 P7 e8 @带操作校验的写函数
) k% T7 [$ n- v: R. k
  1. HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)3 d2 z* W$ @9 |) N
  2. {
    6 M9 j. t4 r9 j" J  }  G  @
  3.         uint8_t buff[len];& @' _* {1 p7 `
  4.         uint16_t i;. T  p* a& O+ {* u5 t# ]
  5.         for (i=0;i<iEEPROM_CHECK_NUM;i++)
    8 w) V/ K, I$ d3 _
  6.         {
    $ i. z( f8 t& E! Z. s0 b( a0 e
  7.                 EEPROM_WRITE(BiasAddress, Data, len);) ?3 c5 B& _; d9 p
  8.                 EEPROM_READ(BiasAddress, buff, len);
    % t- x  g" d7 f& s0 E$ e; p
  9.                 if (memcmp(Data, buff, len)==0)" e( l3 p  R9 K$ t. Y  T0 F
  10.                 {
    : _9 w$ ?# x  R1 W( e9 C) U3 ~
  11.                         return HAL_OK;8 r- C$ k, L1 v& J, a" K9 e+ m; s
  12.                 }
    2 w- D3 r& j; N5 `3 v
  13.         }
    & ]9 z7 n; V2 e
  14. . x; Y$ O5 a4 L& A4 Q3 {
  15.         return HAL_ERROR;
    + w4 T8 W8 n% R' ?0 g; H+ n
  16. }
复制代码
& X! v5 r( C4 V% L  K3 z
带操作校验的读函数
+ r  Y; I# W( p. ~  l* C
  1. HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    # k# ]7 a* P! U; l: U" Z+ a, ^
  2. {3 s, w/ Q0 m& O+ {1 U
  3.         uint8_t buff0[len];* g; t0 [: w. y1 z  {. O& J1 G
  4.         uint8_t buff1[len];
    - d% p7 I, _* A: W9 P$ f
  5.         uint16_t i;
    # b- ~6 r5 }& ?( t% q# X
  6.         for (i=0;i<iEEPROM_CHECK_NUM;i++)
    3 t, l5 }5 I5 R$ P
  7.         {' I& d% R# D3 a  I
  8.                 EEPROM_READ(BiasAddress, buff0, len);
    $ N+ x8 M7 a5 v& D. J( N
  9.                 EEPROM_READ(BiasAddress, buff1, len);
    + W) c8 ]9 S% }8 f$ _4 h
  10. - i* f/ ]! `) k$ Q" A# ^
  11.                 if (memcmp(buff0, buff1, len)==0)& ^: w9 X% h. n  S7 q' h9 Z; i
  12.                 {
    & k& g5 F1 N& P4 |
  13.                         memcpy(Data, buff0, len);
    , s5 i3 |% u1 V8 U- V" H) @
  14.                         return HAL_OK;) C' l4 U$ \4 y  }$ H& a! O
  15.                 }" P9 [" J% y. |: x
  16.         }0 k( j1 m" `* w9 }8 x

  17. 3 z$ i- _7 j5 y" {" u
  18.         return HAL_ERROR;. U/ G1 q1 N" g% H; ]' G4 L  w
  19. }
复制代码

4 W9 k: I6 i& h0 n3 l其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。9 g; K) X' v& u$ F. {! N
' e/ P) A  k8 O# d  i* v
需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。: P# h7 {- O! h& t& M2 h2 h

' y  y3 Q4 c% }  KHAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:& B4 W6 @8 Z5 d) a5 K
3 s# U7 w7 i! K) @; d
  1. /**- p1 I+ s; K. c  j5 h' h* T
  2.   * @brief  Erase a word in data memory.
    & c8 q6 V9 o' s' \3 \
  3.   * @param  Address specifies the address to be erased.
    2 n, ]& f: f. F8 V4 K( s, r
  4.   * @note   To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function0 k8 ]/ b+ D. C1 x6 Y; h. |$ H
  5.   *         must be called before.3 f* m! l) m" q1 H1 s
  6.   *         Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access8 n: P# `  s: d; \3 u1 K) r
  7.   *         and Flash program erase control register access(recommended to protect ; D; Q! _& k* q
  8.   *         the DATA_EEPROM against possible unwanted operation).
    % c$ l- P; ?0 O: U/ u, t$ U
  9.   * @retval HAL_StatusTypeDef HAL Status6 z; |* T% a* @' t% d  e# i
  10.   */( }! t$ i$ N/ G$ Z, _7 k* C
  11. HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)
    # j0 l# Q' L. D. h& s7 @8 m
  12. {! j/ I" o# S0 ~6 v- {) G
  13.   HAL_StatusTypeDef status = HAL_OK;
    & O- o' w1 U5 j8 e

  14. ; z: E0 j9 `" s
  15.   /* Check the parameters */+ n4 i# g1 w$ R( j: D" q
  16.   assert_param(IS_FLASH_DATA_ADDRESS(Address));# e" U( h1 ^6 u3 L& @
  17. $ r9 L# \0 a3 j
  18.   /* Wait for last operation to be completed */
    6 I& C$ K' a# s& m% {9 S/ \+ N
  19.   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    ( g3 g( N5 i$ u, L8 S7 Z6 X0 B, j

  20. 2 ?. a, C8 G8 I( B
  21.   if(status == HAL_OK)2 s& q# x4 e5 w
  22.   {# I7 W# [; \( M1 A6 Q% G4 g- L
  23.     /* Clean the error context */0 |" Z# U0 S% m0 T! p
  24.     pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
    $ q; E, X) t) o( p8 n4 O% ]
  25. % t- x* a  F* `& l9 o; w
  26.       /* Write 00000000h to valid address in the data memory */
    & E1 h' Z. |, Q# [) a1 Z
  27.       *(__IO uint32_t *) Address = 0x00000000U;. ?4 d4 L; E, f0 ~

  28. 9 U/ e# Z" b. l$ y/ p# Y8 F% i5 J% n
  29.     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);; I- \' |  R1 Y) ?6 f
  30.   }* a5 @% b* S4 D7 Z( Q# `$ `

  31. 4 ~# w$ p+ A9 n; l9 i+ Y3 F% S2 {6 p& |
  32.   /* Return the erase status */
    / y, l0 Z6 W8 y- h( k3 k: |+ ^
  33.   return status;
    " e  q! @1 ^9 m; k; r, u) n! L
  34. }  
复制代码
- [4 e1 t" @# [" c6 e1 ?3 s
上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。6 K* w' x$ o2 U, Y. ?

& j( ?' \( W; z( `. o' ?$ i
8 ]: ]+ K/ Y& c" r/ E& n3 c( r
收藏 评论0 发布时间:2021-11-17 23:02

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版