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

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

[复制链接]
STMCU小助手 发布时间:2022-5-16 11:15
1、什么是Flash/ R* \# r3 h9 \6 P( G
FLASH闪存是属于内存器件的一种,其存储特性相当于硬盘,下图就能看出Flash扇区就等于电脑硬盘分区,但是对Flash进行写数据时必须先进行扇区擦除,然后才能再写入,否则会写入失败,MCU的Flash大小可参考数据手册, U! Z" ~; R# d

0 ?) x2 y; l5 T" y OH}MFCH87_[JWSD_]0OO{IY.png - c$ b# q- Q2 e& R/ D

' Y; T4 H, o" z6 }3 [5 n2、闪存模块存储器组织
7 a- ?. B% C9 b6 Z" A- J4 \, j此为STM32F407ZGT6的FLASH大小为1024K5 n6 |8 R% M) O' p
3 c+ N6 w- X- `
56}KC[H$G1[P}14K3`%I8AE.png - ?0 l! N% c4 @
( v& d, `- {4 y9 [4 F: l5 d
不同容量的STM32F4,拥有的扇区数不一样,比如我们的STM32F407ZGT6,则拥有全部12个扇区。从上图可以看出主存储器的起始地址就是0X08000000, B0、B1都接GND的时候,就是从0X08000000开始运行代码的。- r) z8 y- u9 q  ?) b5 ?; Y. [
( D+ [5 A- b  t) J, i1 X& ^1 l1 Y# t9 J
STM32F40x的闪存模块由:主存储器、系统存储器、OPT区域和选项字节等4部分组成:/ J9 f* S+ f6 p: ?5 a; P

; `% L  l2 g# V2.1、主存储器
( ^2 q0 P. X) C) j# y; z该部分用来存放代码和数据常数(如const类型的数据)。分为12个扇区,前4个扇区为16KB大小,然后扇区4是64KB大小,扇区5~11是128K大小。* P. U3 f' \  o% Y, p

$ f+ v6 M* f' k2 e$ p$ n2.2、系统存储器
( t  R: k; v+ H! F% b主要用来存放STM32F4的bootloader代码,此代码是出厂的时候就固化在STM32F4里面了,专门来给主存储器下载代码的。当B0接V3.3,B1接GND的时候,从该存储器启动(即进入串口下载模式)。
7 h! {1 O: V0 R/ h. u/ f! W
. `, X! _: d1 c2.3、OTP区域
5 o, B/ ^3 i$ x* ~5 k9 q. Z1 @+ \即一次性可编程区域,共528字节,被分成两个部分,前面512字节(32字节为1块,分成16块),可以用来存储一些用户数据(一次性的,写完一次,永远不可以擦除!!),后面16字节,用于锁定对应块。
% s2 o% p+ h- S$ j- u6 T
' Y- w1 b- `+ X% y; S# f# }2.4、选项字节2 S  L8 ~1 s3 s! \6 k
用于配置读保护、BOR级别、软件/硬件看门狗以及器件处于待机或停止模式下的复位。9 F( A4 Y2 Z  [5 X! i% G) J
) J) x/ p: \5 Z  M: U
3、STM32F4的闪存6个32位寄存器控制
& B% d- `1 |9 V6 z①访问控制寄存器(FLASH_ACR), K) P1 Z/ O2 b8 C2 l" E
* P; z, S" e* e, ?1 n' s
②密钥寄存器(FLASH_KEYR)
# X& O& C5 }! ~) ]2 ]
+ a6 O' d2 e/ k/ V% p         其中FPEC 密钥总共有2个键值:$ z, X" O) u' G3 T% j$ N9 z: S  Q
: w* v5 ^2 ~9 m# e! P2 _8 N; g
20190911100028298.png # \+ l" w8 ^& i

) M9 f/ u. @6 ]; `" g* j1 l* ]. w③选项秘钥寄存器(FLASH_OPTKEYR)
, h3 f$ F9 ?3 n% k) p4 N1 \$ k1 H
④状态寄存器(FLASH_SR)
: @4 H% Z% G4 r! S
1 E/ V6 L" p( i! ~) h7 O- K⑤控制寄存器(FLASH_CR)( }& b7 X7 h" M6 l# {* F

% W8 l7 |/ c5 {  q+ ?* C8 C0 I⑥选项控制寄存器(FLASH_OPTCR)
1 g! Z$ w9 }2 _* l- O& I3 j  @" }' o+ f
相关寄存器的操作可参考《STM32F4xx中文参考手册》的第3.8小节9 q& p! X1 ~2 z& C! n7 V
$ z4 @- B. j$ ?8 n, q0 s
4、Flash等待周期与CPU时钟频率间的关系2 K9 K  G: U; Z; R4 r
为了准确读取 Flash 数据,必须根据 CPU 时钟 (HCLK) 频率和器件电源电压在 Flash 存取控制寄存器 (FLASH_ACR) 中正确地设置等待周期数 (LATENCY)。当电源电压低于2.1V 时,必须关闭预取缓冲器。4 m1 d8 p) J. ]8 F4 ]6 B
0 c. U5 u/ A1 s* N
6H1WV`GUWQ752AG0{WWF()A.png / o7 h  w, C* ]" I* h

8 c' K" }: D0 s我们供电电压一般是3.3V,所以,在我们设置168Mhz频率作为CPU时钟之前,必须先设置LATENCY为5,否则FLASH读写可能出错,导致死机。# b5 T0 b2 M# R" b

+ p1 g2 P- S# |4 N
5、FLASH的操作介绍
1 X9 q4 D) j% u1 z6 e; ]( z4 a1 Y5.1、读

& k8 x4 n% S6 \" xSTM23F4的FLASH读取是很简单的。例如,我们要从地址addr,读取一个字(字节为8位,半字为16位,字为32位),可以通过如下的语句读取:) n0 B/ W) z5 l9 ~
0 x/ ~. Z: N+ _' @. b" N
                                                                                        data=*(vu32*)addr;5 O% @/ c* r& N) k2 L: V' H
2 k  r& ?% n* A8 |7 j
将addr强制转换为vu32指针,然后取该指针所指向的地址的值,即得到了addr地址的值。类似的,将上面的vu32改vu16,即可读取指定地址的一个半字。
- `5 w" z' ?. L. W' i: ?5 G
+ ~9 ?1 L  p+ e. T+ T  o5.2、写6 n) s2 c' I- G7 ^
在对 STM32F4的Flash执行写入或擦除操作期间,任何读取Flash的尝试都会导致总线阻塞。只有在完成编程操作后,才能正确处理读操作。这意味着,写/擦除操作进行期间不能从Flash中执行代码或数据获取操作。7 q. h! b( }$ N

+ D& `3 x* m2 _, ~3 M注意:/ W% U* ^$ D: W+ j6 G+ `2 g9 J% H
$ c% O8 W' I! d. ]9 Q' q: D3 R
编程前,要确保要写如地址的FLASH已经擦除。
; q4 ^+ X2 R: Z/ ?$ V/ K2 H要先解锁(否则不能操作FLASH_CR)。
! A7 y9 H- n0 f  Z 编程操作对OPT区域也有效,方法一模一样。' V8 n3 ~* `* H; Y0 A
5.3、闪存擦除+ T( H. b5 {/ _) K& k/ r
我们在STM32F4的FLASH编程的时候,先判断首地址是否被擦除了,STM32F4的闪存擦除分为两种:扇区擦除整片擦除。
4 n; o; S5 n; [+ @# q1 l- I
4 W# i; T7 r. l- ^! n- U5.3.1、扇区擦除步骤
% `1 H& P- k, L0 L①检查FLASH_CR的LOCK是否解锁,如果没有则先解锁
# J5 |7 J+ \6 X# y
1 W) C* \5 ^' O$ Y/ h②检查FLASH_SR寄存器中的BSY 位,确保当前未执行任何FLASH操作
  [: \. Z. I5 V
# X2 [8 ?: s+ r. k  W6 x5 m③将FLASH_CR控制寄存器的SER位置1,并从主存储块的12个扇区中选择要擦除的扇区 (SNB)7 L6 h% s3 D1 m- w7 E6 F0 T

. R2 ~/ ]- u4 B2 q: U! t④将FLASH_CR寄存器中的STRT位置1,触发擦除操作! ^; @- v4 t1 G( f. |  ^
! ^) [, E' A+ y/ y) L/ z3 ~
⑤等待BSY位清零
8 o( a& v( q0 c  g7 Z0 [  k5 L
- d! I9 y( M' t+ W" V经过以上五步,就可以擦除某个扇区。
2 t9 X6 v# \8 w2 {. d
" s) J9 |/ e. y) h4 S. b/ ~5.3.2、批量/整片擦除步骤+ ?/ o- T' X! G4 p2 J
①检查FLASH_SR寄存器中的BSY 位,确保当前未执行任何FLASH操作
1 b0 I( C" }: s7 j5 }
7 R, G& G5 y) u5 a+ B②在FLASH_CR寄存器中,将MER位置1 (STM32F407xx/405xx/43xxx)' R6 x. s- T  |/ ^  |; L2 f

; U1 ]+ J: Y- U3 G& Y) Q③将FLASH_CR寄存器中的STRT位置1,触发擦除操作# p3 Q3 u" E- h! ]4 T. K6 S

4 f8 t! u! R) L2 i5 M4 n④等待BSY位清零
3 j+ t, _4 P8 {  n( f/ n8 C! r- Y: S# G6 G: W# V
经过以上四步,就可以批量擦除扇区。扇区擦除功能可以看《STM32F4xx中文参考手册》第3.5小节。% O# g+ I. s) D9 q  u5 B1 n/ Y- V
( @* E8 G+ {8 n4 m
6、STM32F4的标准编程步骤  ]5 d5 J0 t8 T5 c: i
①检查FLASH_SR中的BSY位,确保当前未执行任何FLASH操作。/ L6 f& i0 s" h
' h, C+ m) c" o& v( ^5 J2 O
②将FLASH_CR寄存器中的PG位置1,激活FLASH编程。$ Y1 H# P2 q$ U) l

7 _+ Y0 L: X; [4 `1 O' n; t③针对所需存储器地址(主存储器块或OTP区域内)执行数据写入操作:, ?5 O$ \" |9 Z
- t9 G9 w" d* p
        —并行位数为x8时按字节写入(PSIZE=00)4 O" k+ N) H- c# z# X, T: ?+ @
6 w6 x3 X1 H2 _4 ?7 L9 Z
        —并行位数为x16时按半字写入(PSIZE=01)
5 g; G1 [0 w4 k4 A$ V1 b4 @% s6 O' V  r5 t6 L; [& c7 m
        —并行位数为x32时按字写入(PSIZE=02)
- z: F9 ], W7 G8 u0 N
) [, a9 T0 ]( J- ]: ^8 E' y% X         —并行位数为x64时按双字写入(PSIZE=03)
# V7 G- M/ [, E2 O
# j! `* z  d$ |# D) c; c④等待BSY位清零,完成一次编程。
( l$ i/ c( u- y' C/ w2 w% E6 x) I' j, {% G/ O7 F
按以上四步操作,就可以完成一次FLASH编程。不过有几点要注意:6 V, X, f* A3 A9 x7 P

3 e" ?$ o" |. C1 r. W1、编程前,要确保要写如地址的FLASH已经擦除: J3 b9 E7 E) \8 @+ ?
  S0 c$ V- n4 [$ J
2、要先解锁(否则不能操作FLASH_CR)! F6 X) O$ R8 J
! L% Y4 P: @) s% F; J0 {- c& R' l
3、编程操作对OPT区域也有效,方法一模一样
& |# x: W* g( j# R: S- I0 s9 F/ ~$ h6 H
4、Flash写数据时会把整个扇区擦除掉,所以原来的数据得不到保存,如果想要保存数据,需要分配一个扇区大小的内存去存储原来的数据,占用内存太大,不像SPI的W25Qxx那么方便
/ E! ]1 L3 E4 n# F2 Q
' |( {+ c; _* X  N+ G9 T7 C0 ^1 h7、代码的编写实现
2 \: b, @) R& D8 V' L- Xflash.c:
2 q" X( A( s, Y6 e/ p
. F- F$ [0 r  P1 O& t* H  K$ t8 ]
  1. #include "stmflash.h"* i( A: K" L# e1 V1 @
  2. #include "delay.h"2 d7 K) E( f0 X5 k1 W

  3. , u/ R% k" f2 A! V

  4. ) @* A8 j( W5 r' s. ]# `! `
  5. //读取指定地址的半字(16位数据) 4 v7 P/ [2 w3 W/ \- d- G  f( g
  6. //faddr:读地址 5 E$ @0 j' p' m% ^4 w" n
  7. //返回值:对应数据.: x) y6 Q3 ^% e0 H5 V" p
  8. u32 STMFLASH_ReadWord(u32 faddr), S' T% C* f) i; V" h
  9. {
    , }- @. I# J: I4 V# G! P
  10.         return *(vu32*)faddr; ' E' a7 U) [+ G, Y' l9 p- @' S
  11. }
    1 k) P* O, Q4 x. V4 y' h
  12. , F& K2 t2 S- E; m, o% d; E
  13. //获取某个地址所在的flash扇区9 q* D9 \# T, U. V8 ^$ m- `' C
  14. //addr:flash地址' j  Q4 M& X* d
  15. //返回值:0~11,即addr所在的扇区+ K. D" R5 V9 x( x
  16. uint16_t STMFLASH_GetFlashSector(u32 addr)
    9 B9 Z8 [2 u0 B' F
  17. {
    + Y. s8 C4 E, Z$ o1 c
  18.         if(addr<ADDR_FLASH_SECTOR_1)return FLASH_Sector_0;
    + ~0 y9 \' V; g8 D* r
  19.         else if(addr<ADDR_FLASH_SECTOR_2)return FLASH_Sector_1;
    , x+ x1 |6 y# W. m5 k$ n$ L$ }9 `
  20.         else if(addr<ADDR_FLASH_SECTOR_3)return FLASH_Sector_2;
    ( H, }0 r- A6 y$ @' J- ]5 Z
  21.         else if(addr<ADDR_FLASH_SECTOR_4)return FLASH_Sector_3;
    : n. [( R* ]1 y5 P" u8 w
  22.         else if(addr<ADDR_FLASH_SECTOR_5)return FLASH_Sector_4;
    0 X$ Y3 x1 j+ P5 h
  23.         else if(addr<ADDR_FLASH_SECTOR_6)return FLASH_Sector_5;
    9 j! t+ w% z3 t! @+ Z  r& {
  24.         else if(addr<ADDR_FLASH_SECTOR_7)return FLASH_Sector_6;
    & f( b7 O/ h9 s5 B/ O
  25.         else if(addr<ADDR_FLASH_SECTOR_8)return FLASH_Sector_7;
    2 q& a) j: i/ H( y$ r
  26.         else if(addr<ADDR_FLASH_SECTOR_9)return FLASH_Sector_8;' A/ {; S* L+ D* C9 ]
  27.         else if(addr<ADDR_FLASH_SECTOR_10)return FLASH_Sector_9;
    5 Q1 H9 ?0 u  ^+ N5 V9 v- z
  28.         else if(addr<ADDR_FLASH_SECTOR_11)return FLASH_Sector_10;
    - \1 W1 ^2 d, P+ E& {
  29.         return FLASH_Sector_11;        5 P: B9 a5 e9 h% S5 e
  30. }: ?& Z! o) Q5 Q- F/ l. D
  31. 4 I  P: R, N. L) _) H; s
  32. //从指定地址开始写入指定长度的数据, Q% \4 D" H2 B& Y: `
  33. //特别注意:因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数
    $ K+ _5 y  D3 |' E# k& b
  34. //         写地址如果非0XFF,那么会先擦除整个扇区且不保存扇区数据.所以" T' f! {% N% s8 H7 @
  35. //         写非0XFF的地址,将导致整个扇区数据丢失.建议写之前确保扇区里
    ; l3 U6 F& i6 u" \" F9 g' h0 t
  36. //         没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写.
    0 l% m3 l* z8 a7 c' p$ O
  37. //该函数对OTP区域也有效!可以用来写OTP区!7 o. ?9 s( P/ r
  38. //OTP区域地址范围:0X1FFF7800~0X1FFF7A0F& e5 Y: p, O5 a) D. p( ~! R- u: r
  39. //WriteAddr:起始地址(此地址必须为4的倍数!!)
    8 }! }6 j& e( U$ _! k7 w
  40. //pBuffer:数据指针9 ~$ x( U5 T7 A* I9 n8 ?
  41. //NumToWrite:字(32位)数(就是要写入的32位数据的个数.) ! q( y0 d- ^5 ^- r4 x
  42. void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)        * b0 @/ y9 H- B
  43. {
    ) G# ^$ q* Y$ y- t5 q
  44.   FLASH_Status status = FLASH_COMPLETE;: V# `) Y4 d1 o( W0 f
  45.         u32 addrx=0;
    1 s& k* }$ [+ h
  46.         u32 endaddr=0;          g: ]9 ~5 D$ }$ x$ o) F. [5 r5 b
  47.   if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;        //非法地址: d* ?: }# G3 {  E, [. y( a
  48.         FLASH_Unlock();                                                                        //解锁 ①' z. b: c( \4 N; b9 Z5 M% r
  49.   FLASH_DataCacheCmd(DISABLE);//FLASH擦除期间,必须禁止数据缓存, P' t/ i: x6 y, x
  50.                  & a- g8 N3 J. T( C! t
  51.         addrx=WriteAddr;                                //写入的起始地址# ?! H* `6 u, |0 G
  52.         endaddr=WriteAddr+NumToWrite*4;        //写入的结束地址
    ( j  s( ]  K( N1 B
  53.         if(addrx<0X1FFF0000)                        //只有主存储区,才需要执行擦除操作!!
    , G1 r( S* f, b% R5 U/ U
  54.         {. k% g( d0 r. O1 y* G/ l
  55.                 while(addrx<endaddr)                //扫清一切障碍.(对非FFFFFFFF的地方,先擦除)( }+ D0 j* z5 l0 E( {
  56.                 {/ o. g8 T( @5 c. w; Q6 D
  57.                         if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区 ③7 [  o$ X: ?" q8 b/ q3 ~
  58.                         {   
    . @3 }9 [; e" }0 l& v
  59.                                 status=FLASH_EraseSector(STMFLASH_GetFlashSector(addrx),VoltageRange_3);//VCC=2.7~3.6V之间!!  t2 p  G' k( M* s5 [; f0 j
  60.                                 if(status!=FLASH_COMPLETE)break;        //发生错误了6 K& d" b& }4 S# f( i
  61.                         }else addrx+=4;+ S+ m# V, G2 H) U1 j( E$ J
  62.                 } & o( A7 u+ q' m% e+ S* G
  63.         }  a4 ^) e( C! i7 P$ t$ Q
  64.         if(status==FLASH_COMPLETE)0 I, N4 r: E% D
  65.         {% r' ^7 F& V5 k+ w( y
  66.                 while(WriteAddr<endaddr)//写数据
    1 V+ u: D  Q& D/ x
  67.                 {, K1 |. e. L5 \" s4 w
  68.                         if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)//写入数据④
    8 t, V0 k$ `; k
  69.                         {
    + t* _9 [' X$ u# X5 ~8 d
  70.                                 break;        //写入异常2 Z, D* {+ X' M
  71.                         }3 I$ z( n: a/ i& }) X  h
  72.                         WriteAddr+=4;
    4 j% T; r7 W3 H+ E
  73.                         pBuffer++;
    0 l" ^; _% s0 F' B: P/ H: a
  74.                 }
    6 ^7 g0 m; a4 p( f
  75.         }+ l2 ~" D! [6 W, t
  76.   FLASH_DataCacheCmd(ENABLE);        //FLASH擦除结束,开启数据缓存; B+ L: K# v+ G+ {! i0 ^$ E! y- \
  77.         FLASH_Lock();//上锁 ⑤
    * I$ W" b- u/ b( V/ j
  78. }
    / g! k3 W7 I1 |6 W2 s% o

  79. 2 T" g8 T/ n& I( _. `
  80. //从指定地址开始读出指定长度的数据1 O! U/ U( \& p; W
  81. //ReadAddr:起始地址
    3 g% m! @% P% Y6 U" Z4 q
  82. //pBuffer:数据指针
    ' h' _6 l  f% f- Y5 |0 G
  83. //NumToRead:字(4位)数
    ' G7 x$ z- T) b4 X/ D3 p! {% W
  84. void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead)           + ~! }2 E  A- X: v
  85. {
    ; A( I, }+ i% I3 s3 N: M* d
  86.         u32 i;
    / w3 w6 k! j3 H9 h9 t* Q
  87.         for(i=0;i<NumToRead;i++)0 O9 p. _! [. g3 E
  88.         {
    " L8 v% J4 Q; D7 J; H$ ?& k. j" d
  89.                 pBuffer<i>=STMFLASH_ReadWord(ReadAddr);//读取4个字节.
    3 v. t; I( F% z% a0 Z$ K
  90.                 ReadAddr+=4;//偏移4个字节.        & Z4 A  L* W3 |: P% g6 ~
  91.         }
    ; R* N1 D) z; h+ R; ^
  92. }</i>
复制代码
7 d* z4 P5 L+ O, J
flash.h
5 B5 r( b. x4 B6 d1 ~" d& i$ \; }
4 z, j) T0 T0 \, t# [) s% H) g6 [9 t
  1. <i>#ifndef __STMFLASH_H__</i>
    ) T; |7 X* {9 [9 E8 Y
  2. <i>#define __STMFLASH_H__</i>, [; n: ~4 t" H" h; k
  3. <i>#include "sys.h"   </i>
    ( P4 Q3 {3 a' \- m& U# W2 N: ]) w

  4. , \' H( V) _$ k% e9 J
  5. <i>//FLASH起始地址</i>
    5 N+ `; {8 p5 X$ Z1 f
  6. <i>#define STM32_FLASH_BASE 0x08000000         //STM32 FLASH的起始地址</i>, r0 @) {& l8 v$ c
  7. 6 V# l  O. ^- Z  H! d
  8. <i>//FLASH 扇区的起始地址</i>0 t' b0 ~" L) ]7 O4 y1 x4 a
  9. <i>#define ADDR_FLASH_SECTOR_0     ((u32)0x08000000)         //扇区0起始地址, 16 Kbytes  </i>
    4 q& U6 x+ x2 |$ K" U+ U
  10. <i>#define ADDR_FLASH_SECTOR_1     ((u32)0x08004000)         //扇区1起始地址, 16 Kbytes  </i>( S  Z0 E# y; o/ m! d
  11. <i>#define ADDR_FLASH_SECTOR_2     ((u32)0x08008000)         //扇区2起始地址, 16 Kbytes  </i># ~7 z9 L2 F1 v6 Z; l4 ?) \$ z
  12. <i>#define ADDR_FLASH_SECTOR_3     ((u32)0x0800C000)         //扇区3起始地址, 16 Kbytes  </i>
    + z! p1 @0 d  e+ Q2 U, f& [  I, ~
  13. <i>#define ADDR_FLASH_SECTOR_4     ((u32)0x08010000)         //扇区4起始地址, 64 Kbytes  </i>
    7 u/ |7 v* a1 z/ F; C
  14. <i>#define ADDR_FLASH_SECTOR_5     ((u32)0x08020000)         //扇区5起始地址, 128 Kbytes  </i>
    7 q. B: a2 T: g; V* p
  15. <i>#define ADDR_FLASH_SECTOR_6     ((u32)0x08040000)         //扇区6起始地址, 128 Kbytes  </i>7 Q2 B" o) ~* z
  16. <i>#define ADDR_FLASH_SECTOR_7     ((u32)0x08060000)         //扇区7起始地址, 128 Kbytes  </i># v: z' V) r4 }. i1 M( k; h3 w
  17. <i>#define ADDR_FLASH_SECTOR_8     ((u32)0x08080000)         //扇区8起始地址, 128 Kbytes  </i>
    - v* g$ \5 S7 j( d  K
  18. <i>#define ADDR_FLASH_SECTOR_9     ((u32)0x080A0000)         //扇区9起始地址, 128 Kbytes  </i>
    9 b/ D- M0 u  c/ K
  19. <i>#define ADDR_FLASH_SECTOR_10    ((u32)0x080C0000)         //扇区10起始地址,128 Kbytes  </i>
      n4 [; @% k' G  q  z
  20. <i>#define ADDR_FLASH_SECTOR_11    ((u32)0x080E0000)         //扇区11起始地址,128 Kbytes  </i>% N! w" Q' {6 a* g9 K

  21. - F0 y# p( i& L% w+ G
  22. <i>u32 STMFLASH_ReadWord(u32 faddr);                          //读出字  </i>3 y* `* C( v6 F5 G! G1 y* x8 n/ v
  23. <i>void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite);                //从指定地址开始写入指定长度的数据</i>9 e4 R- s) h; w
  24. <i>void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead);                   //从指定地址开始读出指定长度的数据</i>$ A. A8 D1 e8 j) p
  25. <i>                                                   </i>3 w7 Z$ ~1 q7 K) \0 Y+ D
  26. <i>#endif</i>8 l+ x6 O  ^5 _  y3 @& r* m

  27. 4 F, q& {  w. e$ `! L1 L
  28. 1 \: K$ P5 t% i! c5 E/ U$ z( q
复制代码

8 W& @2 `9 `# f2 T: l
& O' [/ v* A5 K' k' ^
收藏 评论0 发布时间:2022-5-16 11:15

举报

0个回答

所属标签

相似分享

官网相关资源

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