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

【经验分享】STM32-Flash的原理与使用(模拟EEPRM)

[复制链接]
STMCU小助手 发布时间:2022-5-16 11:15
1、什么是Flash  y2 J/ C0 t% ^
FLASH闪存是属于内存器件的一种,其存储特性相当于硬盘,下图就能看出Flash扇区就等于电脑硬盘分区,但是对Flash进行写数据时必须先进行扇区擦除,然后才能再写入,否则会写入失败,MCU的Flash大小可参考数据手册
3 @# W, Y+ _& E: Y7 X2 q! N4 T! U" W' Y3 D
OH}MFCH87_[JWSD_]0OO{IY.png ( s4 ~; \  \3 }6 l0 U3 v" U6 ^1 z
, T+ e6 s, N/ S, h2 Z
2、闪存模块存储器组织
$ t% [! b. B' Q7 ^此为STM32F407ZGT6的FLASH大小为1024K0 \4 s; z3 V) n6 J. ?
6 P; F( ~4 X3 z' G7 A
56}KC[H$G1[P}14K3`%I8AE.png
. I3 M- k4 a( t: |/ z5 A3 I# t
' Y; i, [) {4 N8 t不同容量的STM32F4,拥有的扇区数不一样,比如我们的STM32F407ZGT6,则拥有全部12个扇区。从上图可以看出主存储器的起始地址就是0X08000000, B0、B1都接GND的时候,就是从0X08000000开始运行代码的。
! L; ?* N+ X1 A6 i8 {; m  @8 W+ {0 T* C$ o% ^7 a" v% X" l7 l
STM32F40x的闪存模块由:主存储器、系统存储器、OPT区域和选项字节等4部分组成:
6 j' u! [, K0 I% Q
# W' h$ g( ~" w+ l+ w3 ^# k2.1、主存储器* v6 B1 E: T+ o4 }
该部分用来存放代码和数据常数(如const类型的数据)。分为12个扇区,前4个扇区为16KB大小,然后扇区4是64KB大小,扇区5~11是128K大小。6 d( z. i2 V  y6 m/ H- k8 F
$ }9 X3 T" B+ X: g! ^4 D
2.2、系统存储器' P. [( H( Y' W) ^$ g2 h
主要用来存放STM32F4的bootloader代码,此代码是出厂的时候就固化在STM32F4里面了,专门来给主存储器下载代码的。当B0接V3.3,B1接GND的时候,从该存储器启动(即进入串口下载模式)。1 P6 L3 h/ ?9 c
! N0 ]7 |* z3 D0 x6 P
2.3、OTP区域( U. O; F: ~% `% U& {
即一次性可编程区域,共528字节,被分成两个部分,前面512字节(32字节为1块,分成16块),可以用来存储一些用户数据(一次性的,写完一次,永远不可以擦除!!),后面16字节,用于锁定对应块。
! y. {" x4 Q3 V. r& P
/ _1 L% y7 G( D' @5 g6 j2.4、选项字节
  S' P& D$ \: ]; q8 \用于配置读保护、BOR级别、软件/硬件看门狗以及器件处于待机或停止模式下的复位。
) {% F& q$ h) E9 C$ l, p: J7 x7 D  k# _7 n/ y1 ]4 Y$ K
3、STM32F4的闪存6个32位寄存器控制
7 }- H5 }6 z- `' N0 Y  y) R①访问控制寄存器(FLASH_ACR)* n: j" J5 q' K5 ~# j# X6 h

$ K7 @  u0 d# u6 B②密钥寄存器(FLASH_KEYR)/ C9 ~" l2 k1 B% D% Y

: K7 }* k1 i: o& [         其中FPEC 密钥总共有2个键值:9 [6 R" ?/ ]7 z9 T% {1 @; N- k
$ h) z, o2 X5 O1 O* G
20190911100028298.png . G5 a& x' |- B9 W; W' m9 y0 _

9 V1 @) B6 i& X- c& k③选项秘钥寄存器(FLASH_OPTKEYR)
, D% k5 {6 d  s8 V
# ^/ x; e9 x% a  M9 p0 l④状态寄存器(FLASH_SR)
: R8 e7 O" g* [# \" ^  H. d3 i3 V: g5 I: K# _# a. R: }
⑤控制寄存器(FLASH_CR)
. X( {  R& Q* C$ j( P) ^
2 y6 X8 }" v* x- a+ V+ {1 r) z⑥选项控制寄存器(FLASH_OPTCR)8 q! ?; J: Z) q, f# c7 o

9 p: K) B/ y! [0 K  q! q: I相关寄存器的操作可参考《STM32F4xx中文参考手册》的第3.8小节
! l, r" x) C0 W$ z& E* E
. z0 t/ ^0 U5 f0 X% [8 y" U7 W! l8 V4、Flash等待周期与CPU时钟频率间的关系5 w5 o& U# I9 A( a1 h
为了准确读取 Flash 数据,必须根据 CPU 时钟 (HCLK) 频率和器件电源电压在 Flash 存取控制寄存器 (FLASH_ACR) 中正确地设置等待周期数 (LATENCY)。当电源电压低于2.1V 时,必须关闭预取缓冲器。1 u. F3 b' T; l/ P9 z3 D% E
) h: R2 b5 n- a
6H1WV`GUWQ752AG0{WWF()A.png 6 W0 F: g% C& ]8 P
' }2 W! I' U% q4 B" D! J
我们供电电压一般是3.3V,所以,在我们设置168Mhz频率作为CPU时钟之前,必须先设置LATENCY为5,否则FLASH读写可能出错,导致死机。
% V: ~" z, h, [' Y# W' Z5 N" }7 c2 s
" ]( `: f/ L$ f0 w
5、FLASH的操作介绍
( v' t; D& q& h4 J5.1、读
, j4 g' ~' U3 E: ~/ J  Q
STM23F4的FLASH读取是很简单的。例如,我们要从地址addr,读取一个字(字节为8位,半字为16位,字为32位),可以通过如下的语句读取:
* E  {0 G  u) R
) P8 S) _0 A5 h9 Y  ?- O                                                                                        data=*(vu32*)addr;
' B- E. y: ^  t$ q, l6 |
. ?( M. \% S7 A# g3 I5 q将addr强制转换为vu32指针,然后取该指针所指向的地址的值,即得到了addr地址的值。类似的,将上面的vu32改vu16,即可读取指定地址的一个半字。
9 c+ j  H8 ?4 u7 [
; f. `+ v3 U, O, m: v" x5.2、写
$ ~7 h# w" W: Q* k在对 STM32F4的Flash执行写入或擦除操作期间,任何读取Flash的尝试都会导致总线阻塞。只有在完成编程操作后,才能正确处理读操作。这意味着,写/擦除操作进行期间不能从Flash中执行代码或数据获取操作。
9 d' p' @: Z$ `6 H
4 B5 i. L5 [7 Z0 U) U注意:
3 T3 _4 m2 z" g$ M8 h+ t; M4 ?- j: T) ~* B# N0 Q
编程前,要确保要写如地址的FLASH已经擦除。0 [4 _1 Z4 f* |4 K1 |  x
要先解锁(否则不能操作FLASH_CR)。. l: o8 l6 ?; z# X: i# S
编程操作对OPT区域也有效,方法一模一样。3 L7 O0 [  e# U3 d: r, o3 l
5.3、闪存擦除0 l' w& D% S/ G$ T
我们在STM32F4的FLASH编程的时候,先判断首地址是否被擦除了,STM32F4的闪存擦除分为两种:扇区擦除整片擦除。
2 r* ]" }; p, e+ K% ^2 K1 \; F. a+ k# q' Z+ K  \% J
5.3.1、扇区擦除步骤8 T0 d' m/ B, a6 `, {; U
①检查FLASH_CR的LOCK是否解锁,如果没有则先解锁) P" y/ q* \  H# E
9 H! |3 p+ B  k  S  j+ O' D( l
②检查FLASH_SR寄存器中的BSY 位,确保当前未执行任何FLASH操作
5 g" Q& {' ~$ S9 N9 A2 p. T2 r1 ^  [5 w6 Z# _, h
③将FLASH_CR控制寄存器的SER位置1,并从主存储块的12个扇区中选择要擦除的扇区 (SNB)8 K" s2 {3 ?2 w7 R
' J) A* C3 o0 p7 r5 Q
④将FLASH_CR寄存器中的STRT位置1,触发擦除操作
2 h3 E: }, K2 T
. }' ]- L% ?  G. j⑤等待BSY位清零
- `& S2 {! [* H+ o, ]# C* b6 a* K0 e7 ^1 l8 s( E* i9 J( P
经过以上五步,就可以擦除某个扇区。
7 w$ z* U# }, z! j6 x0 z# ^) [) b5 f0 F
5.3.2、批量/整片擦除步骤
7 Y/ u2 x1 P/ D: P9 F5 E①检查FLASH_SR寄存器中的BSY 位,确保当前未执行任何FLASH操作8 ]6 L4 ~( C! D1 U) p

9 }" J& A6 F* A- Q# C3 m. d+ W. V②在FLASH_CR寄存器中,将MER位置1 (STM32F407xx/405xx/43xxx)
/ o( q7 [9 R2 K: A2 t; d9 X  [$ ]5 u9 @. J+ h. b
③将FLASH_CR寄存器中的STRT位置1,触发擦除操作' F  f. l5 u5 Y- U9 J
( L  ~1 H: {# r/ z; j6 N
④等待BSY位清零( O1 Y) D# r( ~- S" e$ F1 [' G1 K
' [/ \! z1 s& W6 `- f8 [
经过以上四步,就可以批量擦除扇区。扇区擦除功能可以看《STM32F4xx中文参考手册》第3.5小节。
6 H: E; O; B+ K* \) M2 J
7 ^, z& _2 q/ k9 H% F6、STM32F4的标准编程步骤1 i, Q( o, ~- d# x& ~6 K8 H
①检查FLASH_SR中的BSY位,确保当前未执行任何FLASH操作。
1 Z" A# p- n; C
6 T/ J% a1 j% \6 e3 ^" [②将FLASH_CR寄存器中的PG位置1,激活FLASH编程。/ ~$ o: ~6 i( P* ?) M3 F/ s* ]

5 D# @+ j& e+ B1 y" Q③针对所需存储器地址(主存储器块或OTP区域内)执行数据写入操作:
" g& N. G( i5 [. `5 Q2 b, \$ y" \. B
        —并行位数为x8时按字节写入(PSIZE=00)
" `7 K7 `& `# r0 m) b+ C( T# k7 k2 V  d  [  N! u' r
        —并行位数为x16时按半字写入(PSIZE=01)
% S9 }' |- p5 f8 d1 n, d/ |7 e; t$ M" ?; Z9 Q0 n) J8 Y
        —并行位数为x32时按字写入(PSIZE=02)7 t$ B" M8 a, }2 F' o5 L
9 o: d6 @9 ~4 G" d
         —并行位数为x64时按双字写入(PSIZE=03)
' l$ j. i, c0 ~
! s* }" O( w2 W! K④等待BSY位清零,完成一次编程。
" M1 n: c0 z6 ]" Y# _, h3 f/ A3 r( {) ]5 ~( v0 ^
按以上四步操作,就可以完成一次FLASH编程。不过有几点要注意:+ M& o  `* ^1 o+ Q

4 e0 O& b3 Z) g5 k1、编程前,要确保要写如地址的FLASH已经擦除) o- a/ I7 v& J: S- X$ N: S8 d

* A6 m2 W5 i$ h: a/ ~4 o4 l2、要先解锁(否则不能操作FLASH_CR)( N  Z: }- Y' }. |- S7 l
8 Z! F" p6 o; L
3、编程操作对OPT区域也有效,方法一模一样' K4 _7 J; ~# c% F" M1 g5 I

! b+ x- Y6 u& O; d3 w4、Flash写数据时会把整个扇区擦除掉,所以原来的数据得不到保存,如果想要保存数据,需要分配一个扇区大小的内存去存储原来的数据,占用内存太大,不像SPI的W25Qxx那么方便" A# v& w7 }8 A& Z' H6 l/ F+ H' u5 L

% \+ s" W, ?8 `* W: ]7、代码的编写实现& A2 E- |* M/ g: y% a% b0 D
flash.c:
* K% k" J6 K+ \7 ?! S
, I, h5 B# k; U6 k
  1. #include "stmflash.h"
    ; u% d/ v8 s  e0 q% @
  2. #include "delay.h"
    0 i7 {" {% `' y2 `3 s- B% D! K
  3. 7 @6 }+ y+ d* K( r& \  R, ~

  4. ) h9 k0 J" t; L0 @# R
  5. //读取指定地址的半字(16位数据) 6 D- I( s; M3 h; E
  6. //faddr:读地址 / e6 s! b$ e& T1 j
  7. //返回值:对应数据.
    6 Z8 ?1 g, G/ a
  8. u32 STMFLASH_ReadWord(u32 faddr)/ u8 E2 N4 M# ?& B5 ?2 |- Q
  9. {
    , N; ~$ e" C; ?  w% F8 {
  10.         return *(vu32*)faddr;
    . f; E" p1 M6 f' B# H5 t
  11. }
    : T. M2 C1 n* ~) ~0 N% Q2 E" q
  12. ) a: Y: f0 M9 F
  13. //获取某个地址所在的flash扇区
    , _- s* s9 s- o% A9 t; _5 N2 o
  14. //addr:flash地址
    + T) b, K, F  B% {2 A$ ?
  15. //返回值:0~11,即addr所在的扇区% }; t4 ?. ?! r' P1 j, s7 z6 p- Z  k
  16. uint16_t STMFLASH_GetFlashSector(u32 addr): i7 @& P+ L) e( |' q
  17. {
    & p8 Q* K; R' ^( U) p4 ~
  18.         if(addr<ADDR_FLASH_SECTOR_1)return FLASH_Sector_0;  W7 r# Z* U6 D6 G2 r; _$ N; d
  19.         else if(addr<ADDR_FLASH_SECTOR_2)return FLASH_Sector_1;# L* W2 Z4 ]. r! t$ B! X7 W
  20.         else if(addr<ADDR_FLASH_SECTOR_3)return FLASH_Sector_2;
    3 B; M  F  |% t; A# ~5 X# z
  21.         else if(addr<ADDR_FLASH_SECTOR_4)return FLASH_Sector_3;4 L  n: H4 M) c" V+ b: v. V- A
  22.         else if(addr<ADDR_FLASH_SECTOR_5)return FLASH_Sector_4;
    + a- H2 H2 U9 W! r" R8 |" p
  23.         else if(addr<ADDR_FLASH_SECTOR_6)return FLASH_Sector_5;9 f  i. i  z! }! i
  24.         else if(addr<ADDR_FLASH_SECTOR_7)return FLASH_Sector_6;
    2 }/ U# s% n4 H4 v) u0 h
  25.         else if(addr<ADDR_FLASH_SECTOR_8)return FLASH_Sector_7;
    . w0 m1 P3 J3 ^$ v. L( l1 R
  26.         else if(addr<ADDR_FLASH_SECTOR_9)return FLASH_Sector_8;
    % t6 m/ j) k! I5 o7 Q5 ]
  27.         else if(addr<ADDR_FLASH_SECTOR_10)return FLASH_Sector_9;$ `" s  Q' N' N; ~) \4 f
  28.         else if(addr<ADDR_FLASH_SECTOR_11)return FLASH_Sector_10;
    $ ?& N# z1 y7 R9 b# ?0 R, e9 a
  29.         return FLASH_Sector_11;        $ V6 v2 d3 W. j8 C
  30. }
    4 e( \) J/ v0 @. h

  31. 6 j& Z6 M9 ]3 P- Q) K
  32. //从指定地址开始写入指定长度的数据
    0 X( c5 ~& p. [# V
  33. //特别注意:因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数6 w* ^: _& v: N0 f1 y; G
  34. //         写地址如果非0XFF,那么会先擦除整个扇区且不保存扇区数据.所以
    , v5 b: v# a, h) Y8 r: W  `
  35. //         写非0XFF的地址,将导致整个扇区数据丢失.建议写之前确保扇区里
    ) _+ o0 R4 o; o+ X3 X0 P
  36. //         没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写.
    - e7 e4 f& E7 @5 O! Q, B
  37. //该函数对OTP区域也有效!可以用来写OTP区!2 T  ~3 g# [3 d/ i* C
  38. //OTP区域地址范围:0X1FFF7800~0X1FFF7A0F
    - T2 _) o$ L$ _6 U7 _
  39. //WriteAddr:起始地址(此地址必须为4的倍数!!)
    % Z1 V5 w( c& F$ M1 M2 b, b
  40. //pBuffer:数据指针: T  b0 D- `0 n. e) R  A2 r8 [1 e/ m
  41. //NumToWrite:字(32位)数(就是要写入的32位数据的个数.) 3 X) a/ p, _6 \  ?
  42. void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)        
    ' q7 n* F* E& q  f
  43. {
    5 h1 c$ \- B9 U+ I$ @
  44.   FLASH_Status status = FLASH_COMPLETE;/ ], c5 M7 [" N, C) @
  45.         u32 addrx=0;
    , m0 S7 f' ?9 d2 Z
  46.         u32 endaddr=0;          t8 _1 C/ A* S# b3 L6 F
  47.   if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;        //非法地址
    9 S# t" j% i4 u" m: t
  48.         FLASH_Unlock();                                                                        //解锁 ①2 S) L! x8 d% m
  49.   FLASH_DataCacheCmd(DISABLE);//FLASH擦除期间,必须禁止数据缓存$ E6 S  U5 s# o- V! S! N3 ]
  50.                  
    % b. ?" p2 t; _8 l0 i) H* [
  51.         addrx=WriteAddr;                                //写入的起始地址: b: C+ P) G5 @) i5 ^
  52.         endaddr=WriteAddr+NumToWrite*4;        //写入的结束地址
    # X0 C) j' G/ w; s0 c1 |" a! z
  53.         if(addrx<0X1FFF0000)                        //只有主存储区,才需要执行擦除操作!!" R! C+ E, Z; [0 A' n2 m
  54.         {
    + A7 `/ f; ~( z) }" C
  55.                 while(addrx<endaddr)                //扫清一切障碍.(对非FFFFFFFF的地方,先擦除)# i/ t/ H# F) E; t
  56.                 {
    9 c7 n/ R% U1 R! \  ?+ \' \
  57.                         if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区 ③  ]3 k5 ^) N# [  g3 ]% B7 ~# G
  58.                         {   $ m: p! L1 `. e, ~' d
  59.                                 status=FLASH_EraseSector(STMFLASH_GetFlashSector(addrx),VoltageRange_3);//VCC=2.7~3.6V之间!!  H- p9 ~, R5 m5 a" J; h3 [
  60.                                 if(status!=FLASH_COMPLETE)break;        //发生错误了
    ( P9 V  H; }8 v& S) L
  61.                         }else addrx+=4;* R) u) ]. ~4 g
  62.                 }
    ' G0 ], E/ D8 ~1 m
  63.         }/ I3 ~: E; R  Z& a
  64.         if(status==FLASH_COMPLETE)9 |1 o  ]  a8 d$ A' A' p. J& z+ s
  65.         {- {/ O' q* o/ u+ r! N
  66.                 while(WriteAddr<endaddr)//写数据
    2 Z) _* o" E9 ]- O
  67.                 {
    ) \- ^/ t9 d. S# W; o' R4 ^2 u
  68.                         if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)//写入数据④+ f4 N; h! t3 D! d7 ]
  69.                         { + G7 P' V( z( X7 B3 m/ G
  70.                                 break;        //写入异常
    ( s+ z' O- u; _  ~4 d  j
  71.                         }+ h" E6 E1 y. |3 _, G
  72.                         WriteAddr+=4;' u  X" E3 \" A& Q
  73.                         pBuffer++;& p- ~( u; V: n- Q1 Q* i' c/ Y
  74.                 } . H; _' a6 ]& T
  75.         }
    . I' U6 A) z  L) U- |" D
  76.   FLASH_DataCacheCmd(ENABLE);        //FLASH擦除结束,开启数据缓存! x! t0 i. Q' w' ^+ J/ W' _$ _
  77.         FLASH_Lock();//上锁 ⑤/ K* A3 B  Z+ G" ?
  78. }
    ( Q9 [5 f. a/ i$ V! v& i% c

  79. 8 i% ]" S' T+ U3 V) s* K# T
  80. //从指定地址开始读出指定长度的数据
    0 l2 Q6 M% R$ i
  81. //ReadAddr:起始地址& b  q0 b" c8 ^1 z
  82. //pBuffer:数据指针. k& Y4 L. i2 G# I$ w- t9 I
  83. //NumToRead:字(4位)数: f, o# b/ y' {# s" H
  84. void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead)           
      i- \" H! `9 B8 V
  85. {
    1 s5 \- Z6 F/ [7 m5 X
  86.         u32 i;5 U3 S9 }, f+ N) G+ X2 V
  87.         for(i=0;i<NumToRead;i++)
    9 d" _1 w5 Q/ |/ ~! L, n- I) ~
  88.         {' o( F6 ~0 e. v" q2 j. s! ^8 j
  89.                 pBuffer<i>=STMFLASH_ReadWord(ReadAddr);//读取4个字节.
    ' I2 ~8 u/ y. O* @
  90.                 ReadAddr+=4;//偏移4个字节.        
    9 O2 k2 M- z1 e1 z& y6 L2 Z0 P5 ?
  91.         }$ i& r) a2 l0 K$ v$ @0 @
  92. }</i>
复制代码
8 p& c  x# {* g, R' |
flash.h
/ S2 M; F" @  y( S  K% [
+ z. j, j9 S: j4 L) G5 m/ Z7 H
  1. <i>#ifndef __STMFLASH_H__</i>
    , e( L! L  O7 E9 @# L' R5 u8 m
  2. <i>#define __STMFLASH_H__</i>
    2 c. e0 w& Y: X' y
  3. <i>#include "sys.h"   </i>: n' j2 E# W; V1 ]1 }0 i6 i
  4. 1 F! X; y& b5 X* C- |- E# v1 d: q
  5. <i>//FLASH起始地址</i>/ o$ n% [1 v  G& b" A- B
  6. <i>#define STM32_FLASH_BASE 0x08000000         //STM32 FLASH的起始地址</i>
    1 y1 c# `& g+ E
  7. + A5 ^; ]3 m8 [; W4 Y+ t- ^1 z: s
  8. <i>//FLASH 扇区的起始地址</i>! m6 D  V! M. e* t
  9. <i>#define ADDR_FLASH_SECTOR_0     ((u32)0x08000000)         //扇区0起始地址, 16 Kbytes  </i>- w% ?3 P, K" W4 b& W+ O3 L
  10. <i>#define ADDR_FLASH_SECTOR_1     ((u32)0x08004000)         //扇区1起始地址, 16 Kbytes  </i>
    6 }; x4 g  c! e% M) V: }* W
  11. <i>#define ADDR_FLASH_SECTOR_2     ((u32)0x08008000)         //扇区2起始地址, 16 Kbytes  </i>
    7 i: P6 b0 _: @% i1 k: W/ w) e
  12. <i>#define ADDR_FLASH_SECTOR_3     ((u32)0x0800C000)         //扇区3起始地址, 16 Kbytes  </i>
    4 q, L, s" K# }4 e+ ~
  13. <i>#define ADDR_FLASH_SECTOR_4     ((u32)0x08010000)         //扇区4起始地址, 64 Kbytes  </i>
    9 S/ v4 M6 P; Z- C+ X9 e8 w: t* \' m
  14. <i>#define ADDR_FLASH_SECTOR_5     ((u32)0x08020000)         //扇区5起始地址, 128 Kbytes  </i>( p  D" n' P) I
  15. <i>#define ADDR_FLASH_SECTOR_6     ((u32)0x08040000)         //扇区6起始地址, 128 Kbytes  </i>8 B' z) B5 d5 N! E& R
  16. <i>#define ADDR_FLASH_SECTOR_7     ((u32)0x08060000)         //扇区7起始地址, 128 Kbytes  </i>5 Q4 c& i1 o+ u$ L8 [8 T$ {( y
  17. <i>#define ADDR_FLASH_SECTOR_8     ((u32)0x08080000)         //扇区8起始地址, 128 Kbytes  </i>7 d; o$ Z% A: d! G1 F
  18. <i>#define ADDR_FLASH_SECTOR_9     ((u32)0x080A0000)         //扇区9起始地址, 128 Kbytes  </i>
    . U3 T7 \3 ]4 I% {0 ]( q
  19. <i>#define ADDR_FLASH_SECTOR_10    ((u32)0x080C0000)         //扇区10起始地址,128 Kbytes  </i>
    9 w; j9 M6 J1 S9 z! t
  20. <i>#define ADDR_FLASH_SECTOR_11    ((u32)0x080E0000)         //扇区11起始地址,128 Kbytes  </i>4 {) u( {9 ^% ]6 M5 L4 r& [* c$ `

  21. , `3 i, u- H' \$ G4 H. u
  22. <i>u32 STMFLASH_ReadWord(u32 faddr);                          //读出字  </i>" _" p' Y0 s! X1 V
  23. <i>void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite);                //从指定地址开始写入指定长度的数据</i>
    + S' c8 j* Q& d# p
  24. <i>void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead);                   //从指定地址开始读出指定长度的数据</i>
    8 h" F+ V7 ]7 K" L- c  f: U
  25. <i>                                                   </i>
      K0 e% [& k2 ]" E* Z) p
  26. <i>#endif</i>7 b! I5 a# s, k

  27. # [' w) q  G+ [5 t3 m- g7 q% F

  28. , J7 v% ?' i, k
复制代码
: e7 V7 ?1 V7 T* ?" o! O2 @

5 C+ @% p2 k3 t$ ]
收藏 评论0 发布时间:2022-5-16 11:15

举报

0个回答

所属标签

相似分享

官网相关资源

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