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

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

[复制链接]
STMCU小助手 发布时间:2021-11-17 23:02
STM32L0 内部EEPROM写读
/ z$ D! ]  E* w说明
8 W5 H6 v' h( Z/ fSTM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。
& X! k' a& y$ u
6 n. Q+ _, U/ ~9 M基础写读函数
- E3 z7 F; [6 [( R' v! c( x定义内部EEPROM的地址空间:
* b7 X. |2 y/ V$ ?6 k
  1. //STM32L031K6T6
    , ]2 c5 M6 }4 \# y  Q
  2. #define EEPROM_BASE_ADDR        0x08080000
    + P8 O$ L; b$ b5 C; C3 J- ^
  3. #define EEPROM_BYTE_SIZE        0x03FF
复制代码

4 P  w" s: f% s" j# W# I; ]基础字节写函数) f* y: {, G( @. C5 H
  1. //Byte write& b% V, ?  @" q$ ?2 x1 t
  2. void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    / U* [  C& G4 Q6 z/ b; M
  3. {
    + i! e$ |+ j* S1 {/ n$ W+ {7 M  Z
  4.         uint16_t i;
    7 ?, h4 P% j' {
  5.         HAL_StatusTypeDef status = HAL_OK;: h) d  k' z3 G
  6. / A/ _( S8 u2 E$ [; H  j# `
  7.         HAL_FLASHEx_DATAEEPROM_Unlock();
    ! {" v$ Z6 I+ l
  8.         for(i=0;i<len;i++)6 ]9 ~2 m8 L+ I, ~+ ?
  9.         {
    8 t- @. r1 r  Q( g, D- {7 n+ ~
  10.                 status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
    , W2 D8 ~, D' Q' Z! Z9 r; b
  11.                 Data++;5 q- w( I0 S& c8 S
  12.         }
    ( r) W/ `8 h0 q4 R
  13.         HAL_FLASHEx_DATAEEPROM_Lock();
    - k9 A# F  d! W0 S
  14. }
复制代码
( M+ N0 b- y- [; L3 p' M
基础字节读函数6 G6 a, Z  q0 \8 d# l8 o
  1. <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read( X- o9 e' i9 P
  2. void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)
    , p5 t' G$ Q" F) k9 d- X+ k
  3. {) x* |1 k# e6 Y1 i, a
  4.         uint8_t *wAddr;& o' x. s( a) k- K1 t5 g
  5.         wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);
    - D: l! _. x: C/ F
  6.         while(Len--)
    . g& y% o/ O. M/ {5 L
  7.         {
    ) a  y& D! q5 h9 t$ r
  8.                 *Buffer++=*wAddr++;
    # Y5 b& P: l5 \8 t0 ]6 n* Z) a2 s
  9.         }
    5 ~: `4 p" ]1 Y; \/ o
  10. }
复制代码
. D3 T( z; t# U. }6 r6 J
带校验写读函数' Z6 n2 U+ `! f9 V1 V
如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。' E) L$ z, G( t2 j8 U
对于写过程,需要将写入的数据,读回做比较。
; l' w' ~# D) Q1 k& W对于读过程,需要将两次读回的数据,进行比较。# Y4 E) E& ?  f$ }7 G: X* [( F. y
如果比较正确,则操作完成。
' ]: i3 Y; c( m3 T如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。+ [# e3 b9 g' M3 \/ M5 I5 p" z4 L* ^

& t8 ~- Y- P" l- m设定重复校验次数
6 d: ?6 q! g$ j) w6 p& K6 K, d
  1. #include <string.h>  |! v. d( f$ {$ g. H3 U
  2. #define iEEPROM_CHECK_NUM 2
复制代码
. ~/ s( I$ i# y; a/ p
; A7 n  x7 d7 F* M* a. Q& ]0 Z
带操作校验的写函数
' b! ~2 Y$ i  O
  1. HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    + f4 y# P. F7 ~# K; K
  2. {
    5 s) q- K2 M* \" _& {: o  P3 K
  3.         uint8_t buff[len];/ U9 s% I4 m1 t9 o; _. z' Z# S0 B6 Y
  4.         uint16_t i;
    $ f# s7 O: P. u" N5 ^
  5.         for (i=0;i<iEEPROM_CHECK_NUM;i++): i- v1 i( t8 m; d
  6.         {& F0 _) l' q; C
  7.                 EEPROM_WRITE(BiasAddress, Data, len);
    % W. O4 }) C9 p8 J8 t" g) Q& U7 l
  8.                 EEPROM_READ(BiasAddress, buff, len);3 l+ o& |7 J. X9 j
  9.                 if (memcmp(Data, buff, len)==0)" L9 T1 Q7 C- M$ {
  10.                 {2 p: e% t0 a# S! W# ?( b7 Q
  11.                         return HAL_OK;
    3 `" R5 o% c& l/ ], ]
  12.                 }+ L1 r0 b$ ~6 v! Y" z5 J( ?
  13.         }
    ( k  m$ O+ p/ O7 {- q8 F: U7 h# Q

  14. 5 F7 g, n3 u' v; H7 {+ y1 C
  15.         return HAL_ERROR;
    ( P3 e$ g. T8 i* N
  16. }
复制代码

* H- I/ r( C8 X# w; \带操作校验的读函数
+ |) i+ v4 p4 l/ Q
  1. HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len): u) L5 U5 e8 {
  2. {$ m1 _) `8 R8 T
  3.         uint8_t buff0[len];
    0 O! P2 D! f9 `+ E6 B% @1 z
  4.         uint8_t buff1[len];( U; L$ U4 g  |! o5 F& j* N
  5.         uint16_t i;& J# U6 [1 `9 T" _% G6 t! ?
  6.         for (i=0;i<iEEPROM_CHECK_NUM;i++)
    0 h0 V, Z( D$ p: g% K4 g4 O1 r
  7.         {2 }9 {9 `- z, f" |' ~) i
  8.                 EEPROM_READ(BiasAddress, buff0, len);& G/ p6 h4 p. X2 ^2 i" X
  9.                 EEPROM_READ(BiasAddress, buff1, len);
    $ k0 D5 s5 _) t0 y1 [" I

  10. & ~5 c7 C* x, h) e0 {' J! |! M) ]
  11.                 if (memcmp(buff0, buff1, len)==0)7 ?6 E5 z3 r$ A( ?
  12.                 {/ Y. [$ A) I2 B& z
  13.                         memcpy(Data, buff0, len);
    5 T; B+ m  l# \+ |4 z3 f/ h' \
  14.                         return HAL_OK;. e7 A% h' j, x( d
  15.                 }
    5 e7 T% r3 c9 |( B  z# S
  16.         }* t$ y: [1 \  @1 U
  17. 0 n( B$ }; C# {- J' U$ R
  18.         return HAL_ERROR;
    ( b+ R/ G$ X. m4 Z; i
  19. }
复制代码

, c  I1 e0 N; ?3 \7 G' O' d其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。
' T! ^3 q2 \8 ~3 p: ]2 A/ \9 }, ~/ g$ ?) G0 Y% ~
需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。
* i  S! ], l+ _, }! F6 _; G# M1 |7 o6 n) `4 W
HAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:
. `$ K4 K8 r+ d' G0 t  }8 J- R* Z! V' p# P. B7 n/ r& Q- F
  1. /**
    6 p* E7 b0 Z4 {) E3 U
  2.   * @brief  Erase a word in data memory.
    8 I& x' ]; C% h
  3.   * @param  Address specifies the address to be erased.
    6 a4 k7 O, i& m+ j$ }5 J2 q
  4.   * @note   To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function
    % A( k( g  ?  m) t
  5.   *         must be called before.8 c5 z2 d+ {) q! K/ F8 Q& x
  6.   *         Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access% o9 p. i# I" ]  u
  7.   *         and Flash program erase control register access(recommended to protect
    * K& J4 G# H( I* y# I
  8.   *         the DATA_EEPROM against possible unwanted operation)., h7 g/ B+ [$ e+ K& ~
  9.   * @retval HAL_StatusTypeDef HAL Status. R! h- O+ M! [2 a! N" f3 s
  10.   */
    + ?, Z7 H" h3 ]7 Y( ?4 O9 Q
  11. HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address); D! H2 n3 g+ R, J
  12. {4 F# H% x% e6 n5 _" Q& S
  13.   HAL_StatusTypeDef status = HAL_OK;
    6 l  J% \) ^5 f* b  b* h/ ^

  14. " I1 q" @6 ?* ]7 U6 o$ i+ l
  15.   /* Check the parameters */* m$ F7 f7 D, }+ z) [7 M; G
  16.   assert_param(IS_FLASH_DATA_ADDRESS(Address));
    / O" W8 x" j6 t# @2 ]

  17. ; v5 K' @4 y6 V4 A5 j
  18.   /* Wait for last operation to be completed */  r6 t3 z$ V& k9 @. T; L
  19.   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    " }0 d- ]1 Z: P; v2 ]$ D9 v; h
  20. ' S2 Z  N! V0 q1 n% Y/ P& B7 i7 b
  21.   if(status == HAL_OK)
    # K: h4 r3 O3 `$ B5 {
  22.   {- W! U$ C( P' o0 j: M: C
  23.     /* Clean the error context */
    / @4 A# R- ~( ~1 d
  24.     pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
    ( @5 d0 K1 L2 _7 E8 [# _
  25. ' |' }5 ~5 |1 a$ W) T
  26.       /* Write 00000000h to valid address in the data memory */
    : [" _0 z7 l0 l/ a6 G3 i. U
  27.       *(__IO uint32_t *) Address = 0x00000000U;
    8 D9 j& h3 \& q% N. X
  28. 2 D6 g& z8 i5 `! O' z: u
  29.     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    * ]8 B) s4 f7 C6 j
  30.   }$ `# n; e  t- q3 [
  31. $ Z/ c" q; o0 }
  32.   /* Return the erase status */
    ) J8 r. d! Y6 T# P; M/ X4 x
  33.   return status;
    ( {, d7 p: L( a, ?% L
  34. }  
复制代码
' B3 }4 w. }1 d( t9 I, v- y
上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。1 [' K2 O) p. [2 e

! h' r5 Q( ~- t1 Q/ V# P8 j9 ?9 D
收藏 评论0 发布时间:2021-11-17 23:02

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版