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

【经验分享】STM32掉电时存数据到FLASH

[复制链接]
STMCU小助手 发布时间:2022-1-30 01:00
一、STM32FLASH简介
  不同的STM32它的FLASH大小也是不一样的,分为大、中、小容量,容量由16K到1024K不等。这次实验用的开发板FLASH容量大小为128K。
  STM32的闪存模块由:主存储器、信息块和闪存存储器接口寄存器三部分组成。
  主存储器:该部分主要是用来存放代码和数据常数,被划分为128页,每页1K字节(小容量产品也是每页1K字节,大容量为每页2K字节)。主存储器的起始地址就是0X08000000, B0、B1都接GND的时候,就是从0X08000000开始运行代码的。
  信息块:该部分分为2个小部分,其中启动程序代码,是用来存储ST自带的启动程序,用于串口下载代码,当B0接V3.3,B1接GND的时候,运行的就是这部分代码。用户选择字节,则一般用于配置写保护、读保护等功能。
  闪存存储器接口寄存器:该部分用于控制闪存读写等,是整个闪存模块的控制机构。 
  对主存储器和信息块的写入由内嵌的闪存编程/擦除控制器(FPEC)管理;编程与擦除的高电压由内部产生。
  在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后读操作才能正确地进行;既在进行写或擦除操作时,不能进行代码或数据的读取操作
闪存的读取
  内置闪存模块可以在通用地址空间直接寻址,任何32位数据的读操作都能访问闪存模块的内容并得到相应的数据。读接口在闪存端包含一个读控制器,还包含一个AHB接口与CPU衔接。这个接口的主要工作是产生读闪存的控制信号并预取CPU要求的指令块,预取指令块仅用于在I-Code总线上的取指操作,数据常量是通过D-Code总线访问的。这两条总线的访问目标是相同的闪存模块,访问D-Code将比预取指令优先级高。
  这里要特别留意一个闪存等待时间,因为CPU运行速度比FLASH快得多,STM32F103的FLASH最快访问速度≤24Mhz,如果CPU频率超过这个速度,那么必须加入等待时间,比如我们一般使用72Mhz的主频,那么FLASH等待周期就必须设置为2,该设置通过FLASH_ACR寄存器设置。
闪存的编程和擦除
  编程过程:
  ·检查FLASH_CR的LOCK是否解锁,如果没有则先解锁
  ·检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的编程操作
  ·设置FLASH_CR寄存器的PG位为’1’
  ·在指定的地址写入要编程的半字
  ·等待BSY位变为’0’
  ·读出写入的地址并验证数据
  擦除过程(页擦除)
  ·检查FLASH_CR的LOCK是否解锁,如果没有则先解锁
  ·检查FLASH_SR寄存器的BSY位,以确认没有其他正在进行的闪存操作
  ·设置FLASH_CR寄存器的PER位为’1’
  ·用FLASH_AR寄存器选择要擦除的页
  ·设置FLASH_CR寄存器的STRT位为’1’
  ·等待BSY位变为’0’
  ·读出被擦除的页并做验证
二、软件实现
  flash.c文件
  1. #include "flash.h"
    6 q$ m$ b, F( M' y+ T/ z( U
  2. #include "delay.h"2 Q8 \) r9 r* K6 O* s& y2 R, [
  3. #include "usart.h"3 D# x) x- a* s+ A1 ^
  4. ) T% @1 _3 A, k9 O
  5. /***flash解锁*****/
    ( V* x* X) n. F& ^, S1 N3 D
  6. void STMFLASH_Unlock(void)
    $ R: H2 j! y/ e- {1 A8 p6 D
  7. {3 |4 Y7 k8 U0 o1 U1 j: U% S2 p) P" ~
  8.   FLASH->KEYR=FLASH_KEY1;                                        //写入解锁序列
      }; k  p* C/ \% U' H5 _
  9.   FLASH->KEYR=FLASH_KEY2;
    % W) M  Q1 W) n& C: I: s/ F
  10. }9 @6 y3 I. i: ~/ c2 [

  11.   x6 v; y) M, D/ f# d1 n, w! P
  12. //flash上锁0 K- Q; ?$ E3 ~# B# s
  13. void STMFLASH_Lock(void)' h+ o6 n6 D- ^! {! `* U6 x  i0 M
  14. {
    1 `9 a% m: f0 _, q
  15.   FLASH->CR|=1<<7;                                              //上锁9 C; ?* d+ W5 |" O6 H6 w
  16. }: A( d5 v1 A* M. @

  17.   M0 _* H/ \: m  z5 u" N
  18. //得到FLASH状态
      }; q( U" Z  t( R, R
  19. u8 STMFLASH_GetStatus(void)8 F5 Q; R. }+ |4 v5 U
  20. {    2 @. C/ Q* t- i2 I+ S4 Y; _
  21.    u32 res;         # M+ |! r8 a' j/ Y, r7 i
  22. 8 H. @7 w( w/ j8 X2 ^6 L
  23.    res=FLASH->SR;' l% S- H: _9 ^4 d" g% J
  24.    if(res&(1<<0))return 1;                                          //忙6 J2 V) l7 R+ U4 C# O% b6 n
  25.    else if(res&(1<<2))return 2;                                     //编程错误
    6 K/ z; k) l& u3 ^% e% e
  26.    else if(res&(1<<4))return 3;                                     //写保护错误
    " }3 p- f; D% v
  27.    return 0;                                                        //操作完成
    & G! Q- i. D# D  v
  28. }
    ) T% W2 n1 ?( n$ G" U# L9 _
  29. ) v. V2 {% U$ r' c" _" \3 d
  30. //等待操作完成
    , O- U( L% J* t" g8 V
  31. //time:延时长短; u2 _6 ~- M- c- M( A( Z  x
  32. //返回值:状态.
    ) C" F. J2 D1 m' @6 M. p
  33. u8 STMFLASH_WaitDone(u16 time)
    * f4 u3 e, z$ ^1 [/ A" n
  34. {, w3 u' V) v. q. I" Q
  35.    u8 res;
    - c. L8 s$ H" m

  36. 7 P/ Q  }" {8 E% }
  37.    do: h  K7 ^8 f3 o/ q& l
  38.    {
    , v& b0 _6 b* x; v; F, y
  39.       res=STMFLASH_GetStatus();# `4 X- P! [- e2 w7 ?
  40.       if(res!=1)break;                                            //非忙,无需等待,直接退出.
    / Q$ H9 H: ~# ]5 k* B( [! I
  41.       Delay_us(1); time--;             , u5 K  H3 @7 M4 c
  42.     }while(time);
    . z4 u+ b5 S) B5 b/ s
  43.     if(time==0)res=0xff;                                           //TIMEOUT
    ( \0 ?0 S. m! \7 ]4 O
  44.     return res;
    1 G* j4 N0 c6 T" Y, S5 |
  45. }/ ^0 Q* I, s+ h3 d) y! x& i& `9 R
  46. + O* b2 T6 J5 F; e, ?
  47. //擦除页' B/ [& P0 v% s% a% }. _$ m
  48. //paddr:页地址6 y3 k5 l. ?+ k, M! T
  49. //返回值:执行情况
    8 i. Z, ], H! j! r
  50. u8 STMFLASH_ErasePage(u32 paddr)
    # A2 u$ G0 p8 K# K$ @- E
  51. 7 R$ u( l1 w, G3 i' _; ~. ?( D
  52. {
    . n# `- E$ p1 e9 o
  53.        u8 res=0;9 L; t  ]# J5 W" `- T  g

  54. - ]& `2 T( [( l* B# w/ _) i
  55.        res=STMFLASH_WaitDone(0X5FFF);                              //等待上次操作结束,>20ms   
    9 A' z! F! A5 Y2 K* Y5 d! r
  56.        if(res==0)/ Z" I$ l5 j5 b1 o- M
  57.        {( h# s5 M+ Z/ _1 [
  58.               FLASH->CR|=1<<1;                                      //页擦除7 R6 k: J' ]2 k7 a9 ?
  59.               FLASH->AR=paddr;                                      //设置页地址
    8 I! E! O' N+ t$ v- [0 F
  60.               FLASH->CR|=1<<6;                                      //开始擦除             Y9 q" j4 j/ m6 I
  61.               res=STMFLASH_WaitDone(0X5FFF);                       //等待操作结束,>20ms * z; \' n$ I" R$ t& f
  62.               if(res!=1)                                             //非忙
    : N8 H5 v9 a( K5 j  W& O1 k. x7 t7 ~
  63.               {
    # V% O2 D- d5 Z  J& |; [' N% D
  64.                      FLASH->CR&=~(1<<1);                           //清除页擦除标志.
    % V' W* P: ~% }( [" {( o
  65.               }
    * ~& ]3 c$ A) D4 M
  66.        }5 ]+ m- P) I# b: {( e, h! j( ?
  67.        return res;
    5 ?; l2 m2 w1 v
  68. }
    ( G# [, `6 r% W2 m

  69. " `, U' d" l. d& g8 [
  70. //读出指定地址的半字(16位数据)9 ?- \0 w& ~$ W. v% S
  71. //faddr:读地址(此地址必须为2的倍数!!). P0 T& y+ a2 M" B  X( @
  72. //返回值:对应数据.4 d- G0 c# g* P" @' b
  73. u16 STMFLASH_ReadHalfWord(u32 faddr), [* g* [; k8 P5 d1 ^
  74. {' H' i* q3 o( y/ u' ^) ?2 ]
  75.     return *(vu16*)faddr; . X- k+ R5 p! L! f  }, S; j7 i
  76. }, i+ I! W0 I/ o$ d. T
  77. #if STM32_FLASH_WREN                                               //如果使能了写   
    # H3 ^+ l4 o3 f' S9 _
  78. //不检查的写入
    1 G  E( O, r* w1 W  ^1 }
  79. //WriteAddr:起始地址, n5 v% d8 ?$ E- t2 j( d
  80. //pBuffer:数据指针
    + e, U" _/ `( B+ ]6 S) B1 o: L
  81. //NumToWrite:半字(16位)数   8 l  m5 ]4 Q  }. @. Q" M6 W1 {
  82. void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)   
    1 A2 x6 b& K! t: Q+ C& y
  83. {                       ) G9 s1 p, O. o5 t% e) ]: Z6 V$ B
  84.     u16 i;. ?5 g% i, M' b& b3 `* v
  85.     for(i=0;i<NumToWrite;i++)
    / r: n4 b- y- @6 \! J
  86.     {
    # e( y7 y: b( y
  87.         FLASH_ProgramHalfWord(WriteAddr,pBuffer[i]);
    " |" Q/ W# \8 Y0 F5 ?. _: ^
  88.         WriteAddr+=2;                                           //地址增加2.+ d$ X5 M) \% T% h4 h
  89.     }  
    ' t/ p: |" Z& I6 }& i! L
  90. } ; k/ n0 F" K' y/ H1 f
  91. //从指定地址开始写入指定长度的数据
    & w: A! @2 i: B- k& z1 J
  92. //WriteAddr:起始地址(此地址必须为2的倍数!!)
    - ~6 D" c6 i5 h, z5 L" e
  93. //pBuffer:数据指针
    % X  e6 n1 _' j& I! a
  94. //NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
    4 d6 G7 q9 c3 m5 v+ M$ H) _+ t
  95. #if STM32_FLASH_SIZE<256
    # Q# M9 e+ j, i% r& c
  96. #define STM_SECTOR_SIZE 1024                                       //字节
    + x) L  U/ N. h. |' w9 g0 i# Y
  97. #else
    9 ^$ B6 `  S- R' T* ]( V1 L
  98. #define STM_SECTOR_SIZE    2048% j1 c# g1 R- o' H
  99. #endif           x. @; P9 k4 Z$ M% U" i& p
  100. u16 STMFLASH_BUF[STM_SECTOR_SIZE/2];                               //最多是2K字节
    " M# y! a! ?2 z' r4 F* o
  101. ( d- U2 U* W" t# F
  102. void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)
    : X+ ~9 i; ?, @, x4 j
  103. {
    9 s0 g; k4 ~5 O& v6 T2 j9 D- v! j
  104.     u32 secpos;                                                     //扇区地址
    ; J" K! I$ X' H
  105.     u16 secoff;                                                     //扇区内偏移地址(16位字计算)( w9 n4 f$ M% \, ]/ C5 ~
  106.     u16 secremain;                                                  //扇区内剩余地址(16位字计算)       5 f; L: S# Y3 A
  107.      u16 i;      N" g  a1 J- R4 ]% p
  108.     u32 offaddr;                                                    //去掉0X08000000后的地址
    " |, y5 _1 d# J8 V  _
  109.     ) V+ w/ E: n8 B) z2 g7 M1 b* g
  110.     if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址
    & k/ r1 a. z. F  B2 n( D
  111.     FLASH_Unlock();                                                 //解锁
    9 v8 r2 N6 n' j3 t8 s7 O
  112.     offaddr=WriteAddr-STM32_FLASH_BASE;                             //实际偏移地址.: C  @- A- i2 f# D5 P- [
  113.     secpos=offaddr/STM_SECTOR_SIZE;                                 //扇区地址  0~127 for STM32F103RBT6
    ; P6 s6 S  E0 a8 T) e( D
  114.     secoff=(offaddr%STM_SECTOR_SIZE)/2;                             //在扇区内的偏移(2个字节为基本单位.)  {; W8 p5 q( z$ q  Y
  115.     secremain=STM_SECTOR_SIZE/2-secoff;                             //扇区剩余空间大小  
    ! I8 R, @. N" y' n# E! g2 O  N
  116.     if(NumToWrite<=secremain)secremain=NumToWrite;                 //不大于该扇区范围
    - X+ P$ a9 e* C$ `
  117.     while(1)
    8 n" i0 ], f$ ?
  118.     {   
    2 y* N( I7 }* ~8 C
  119.         STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整个扇区的内容
    % S2 `" P# @1 j9 d) m# ^
  120.         for(i=0;i<secremain;i++)                                   //校验数据5 }5 P) A/ |7 U- T$ a3 ^% V2 q
  121.         {
    ' b7 b+ ^8 H- g( ^1 q5 c8 Y
  122.             if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;              //需要擦除      . j$ s) x0 s8 w6 t2 J
  123.         }
    9 c. @! `5 ]1 H
  124.         if(i<secremain)                                            //需要擦除
    , Q: n8 n" w- C9 N& D% K0 I* [
  125.         {
    ' j/ Q7 \% ?' {4 N: @" R  M
  126.             FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);               //擦除这个扇区1 L! z) `$ F8 g$ ~8 h
  127.             for(i=0;i<secremain;i++)                              //复制) N: o3 `$ k9 r& T! W- X; U- \# }* ~
  128.             {
    " W7 Y  U9 m- {! S5 ~3 ~* j
  129.                 STMFLASH_BUF[i+secoff]=pBuffer[i];      
    . `; o# y/ i9 x: k8 `: u. n  Z
  130.             }, v6 L% \. w& h& @3 |) i# h5 p0 u
  131.             STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//写入整个扇区
    4 g' N: I8 F% t+ D
  132.         }else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain); //写已经擦除了的,直接写入扇区剩余区间.                    
    5 i8 l  R9 C4 @3 ~* E: z
  133.         if(NumToWrite==secremain)break;                            //写入结束了
    * R7 c) d" Y0 V# L
  134.         else                                                       //写入未结束, b+ G4 ^8 ^+ G9 f+ E( ^6 j$ G
  135.         {4 f! @8 `% _& v' T8 ]3 G
  136.             secpos++;                                              //扇区地址增1
      f5 l$ b+ E- f: E3 n! o6 A
  137.             secoff=0;                                              //偏移位置为0      . R& Y/ v3 j. r+ w1 m) S  E+ s
  138.                pBuffer+=secremain;                                 //指针偏移
    # A9 T# G  f5 N) F
  139.             WriteAddr+=secremain;                                  //写地址偏移      
    , S; C1 V6 w3 y$ j8 k
  140.                NumToWrite-=secremain;                              //字节(16位)数递减0 o# C+ A; ]" I$ w* k3 w
  141.             if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一个扇区还是写不完( L  o' G# g/ `! f
  142.             else secremain=NumToWrite;                             //下一个扇区可以写完了" Q: R3 m( Q0 M9 O/ ^! r+ E
  143.         }     * I9 T9 ^) a0 l
  144.     };    5 |2 n+ C1 v5 J5 z+ N$ Y5 t7 J' k1 n
  145.     FLASH_Lock();                                                  //上锁0 q, Q- q( Z, @% q5 d$ A
  146. }2 ~8 ]% Z' E0 G' y- u
  147. #endif1 z) C" r1 l4 c. A0 G; ^
  148. - O, v" r2 }1 l
  149. //从指定地址开始读取指定长度的数据
    & w1 X# T+ w; ~3 n/ w
  150. //ReadAddr:起始地址
    ( Q0 F  Q- U3 u, O1 T* Z1 f
  151. //pBuffer:数据指针( [+ h9 [$ M" D; Q
  152. //NumToWrite:半字(16位)数
    0 `& P# b* W/ ^" i) c. Y* `
  153. void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)
    + p& b( l/ r& l4 n( E
  154. {; `" G5 ?, d  [" U
  155.     u16 i;8 w( t) P' L6 w/ X; x, A) H
  156.     for(i=0;i<NumToRead;i++)
    % x* A# V: F. U7 Z* c
  157.     {
    ( w$ K- [9 e; x
  158.         pBuffer[i]=STMFLASH_ReadHalfWord(ReadAddr);               //读取2个字节.- Z' ~& h( F5 {8 A0 m
  159.         ReadAddr+=2;                                              //偏移2个字节
    5 E3 W+ y/ R  u  L' r7 r
  160.     }
    4 B% w5 t1 R; S2 R4 o4 I
  161. }
    0 w( i3 T. m- q6 s6 s" B
  162. $ V2 j1 h6 g0 y* J
  163. //////////////////////////////////////////////////////////////////////////////////////////////////////  @- A# ]7 Y. |3 t4 i
  164. //WriteAddr:起始地址
    / q1 D: h. v/ l; [- p) t# J
  165. //WriteData:要写入的数据
    6 e5 i. k; P8 h# d5 C
  166. void Test_Write(u32 WriteAddr,u16 WriteData)      
    . o: O8 u; ?+ w' E6 {: }$ |% I, _
  167. {% u- e3 u' T1 n. `& r
  168.     STMFLASH_Write(WriteAddr,&WriteData,1);                       //写入一个字
    ) b* F- K7 ~2 r1 T2 S4 A
  169. }
复制代码
0 R: T5 w8 M6 ^7 s" k+ T
  flash.h文件
  1. #ifndef __FLASH_H__- V% [" b' [5 v' _& i$ U; b4 o
  2. #define __FLASH_H__) t2 h- Q' h8 f
  3. #include <stm32f10x.h># Q1 o$ E/ ]5 k0 U* }

  4. * l  w' ~& D: F$ ~
  5. #define FLASH_KEY1               0X45670123- ?  V% a  z& G: j5 T, I6 \
  6. #define FLASH_KEY2               0XCDEF89AB0 G' j, n* u  J( I' G" t/ e
  7. - }2 h+ ]; K  w# m! X/ E" G
  8. #define STM32_FLASH_SIZE 128                                 //所选STM32的FLASH容量大小(单位为K)
    ; B- K/ q& C  M/ s" h
  9. #define STM32_FLASH_WREN 1                                       //使能FLASH写入(0,不使能;1,使能)
    ) S. r+ w' F2 m* p" M3 R: c
  10. //////////////////////////////////////////////////////////////////////////////////////////////////////2 u9 Q& w0 E) t

  11. 2 i! X  u* C# z) Y. V1 o" C
  12. //FLASH起始地址
    ( q6 k; L8 ~% u! I1 I0 {% t- K: j
  13. #define STM32_FLASH_BASE 0x08000000                         //STM32 FLASH的起始地址  I% i& O2 q) M" I, L1 ]

  14. ! F. c/ {  o8 N# y4 {

  15. % `/ p4 _8 L" I  ?7 P) P8 ]
  16. void STMFLASH_Unlock(void);                                        //解锁) S- a. u- x0 ~1 Q+ L
  17. void STMFLASH_Lock(void);                                       //上锁5 \6 X- }9 m! E8 Y9 {0 O: C/ r: A) N
  18. u8 STMFLASH_GetStatus(void);                                       //获得状态  k  w5 ?8 ~0 s4 `; x6 u8 ~
  19. u8 STMFLASH_WaitDone(u16 time);                                  //等待操作结束/ B) l' X* l7 Q% t: m
  20. u8 STMFLASH_ErasePage(u32 paddr);                                  //擦除页
    0 {/ z( F& p# y! D2 k
  21. u16 STMFLASH_ReadHalfWord(u32 faddr);                               //读出半字  
    + T; b# T7 L1 o/ x
  22. void STMFLASH_WriteLenByte(u32 WriteAddr,u32 DataToWrite,u16 Len);       //指定地址开始写入指定长度的数据
    " n$ R3 j5 I. `; c
  23. u32 STMFLASH_ReadLenByte(u32 ReadAddr,u16 Len);                       //指定地址开始读取指定长度的数据: V% |* i1 V; L/ t/ E' ?& I1 E
  24. void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite);          //从指定地址开始写入指定长度的数据& e! L0 |, Q5 o% O# x
  25. void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead);             //从指定地址开始读取指定长度的数据
    2 r1 j, w+ H: q2 |
  26. % h# z9 Z( @9 B, P0 ~: H+ j$ f( I/ U
  27. //测试写入
    0 B# B$ j( T) `" c" s$ ^6 N, }
  28. void Test_Write(u32 WriteAddr,u16 WriteData);                                   8 z6 A4 l: U7 J) _$ u3 S! o) v$ X7 N! Q
  29. #endif
复制代码
# Y* F, M$ M7 ]5 K* G. p0 e" P
+ o" r) ]- X/ Y, l* c8 B
  main.c文件
  1. #include "flash.h"4 b$ i' s1 @" O9 ^

  2. 5 _) X6 c% x0 _9 h" I; w9 s
  3. #define SIZE sizeof(TEXT_Buffer)                  ///数组长度2 u$ E/ g; V; F8 }) f& E- T5 F
  4. #define FLASH_SAVE_ADDR  0X08070000   //设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000)
    + v2 _& i/ x0 Y8 O

  5. * a0 W. i  D; I/ _
  6. const u8 TEXT_Buffer[]={"STM32 FLASH TEST"};$ s6 {. |, E7 E8 f
  7. u8 datatemp[SIZE];& h* |8 M/ A$ b& d# P

  8. 9 _4 n- c3 [' F2 M+ g( ?, W, Q9 m
  9. int main(void)  g7 ?( c) ]/ ~1 _+ \- A# B0 ^0 t
  10. {. r% A3 U/ G) ]
  11.      while(1)
    4 H3 r. w! }1 m0 o; Y" Q% y
  12.     {# ^  _5 o( }& Y% `0 F* x2 `
  13.         if(掉电)* z6 h# ^9 u* p0 T# J
  14.      {
    9 v: v+ w2 \+ E7 T6 T. |
  15.           STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)TEXT_Buffer,SIZE);//flash写函数
    2 e2 U+ D0 J$ Y  J+ N+ L
  16.      }  
    2 X6 R. Y# H0 \1 q* l) {2 }- [
  17.            STMFLASH_Read(FLASH_SAVE_ADDR,(u16*)datatemp,SIZE);     //flash读函数   7 A+ Z" P/ f. M6 M  k5 Z
  18.    }  l$ C1 [, y7 `9 P. K1 f% m
  19. }
复制代码

  _, {3 n. i; P! z% y$ F0 z  ~5 `. C9 x% H
  以上就是flash在掉电的时候进行读写的程序,项目用到了就记录一下,方便以后查阅学习。其中的大部分代码在库函数中都能够找到参考。
, M1 o, A' c0 V" d5 M/ Y! f
收藏 评论0 发布时间:2022-1-30 01:00

举报

0个回答

所属标签

相似分享

官网相关资源

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