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

STM32CUBEIDE(15)----移植兆易创新SPI Nor Flash之GD25Q64Flash

[复制链接]
STMCU小助手 发布时间:2022-10-20 19:14
spi概述7 {+ C$ @* p7 U* J0 A
SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议,比如 EEPROM,FLASH,实时时钟,AD转换器。
9 l( n' _+ P$ y2 [( k, OW25Q64 是一款SPI接口的Flash芯片,其存储空间为 64Mbit,相当于8M字节。W25Q64可以支持 SPI 的模式 0 和模式 3,也就是 CPOL=0/CPHA=0 和CPOL=1/CPHA=1 这两种模式。2 b8 Y! H4 k& {. d) N9 s$ \

" z* `8 m9 |8 E* c生成例程
3 E; c. W3 T( _, m, c- D
使用STM32CUBEMX生成例程,这里使用NUCLEO-F103RB开发板
) W3 k$ K* F8 A8 Z2 l. s0 {- R2 U! X  L5 I- X# h: }, R* ^
839757b637ee4ab69623fce326742df6.png & O- L. c" A" J. y# ~( q; u) L
: R) w8 A5 Z  _  ~2 C& ]
配置时钟树,配置时钟为64M。0 A; Q* F% y  ]2 K' h
9 J5 U( G, P: a$ u- j- q8 e( g
360005becba24788aee6f547baae5b52.png ' b) m5 {6 O( z7 x
5 |8 t1 N) v) n" V1 U6 _( n, u
查看原理图,PA2和PA3设置为开发板的串口。

, @0 g" n! o! @4 K  t
6 z  Y$ R" l# i3 u  y7 ^3 c
4c2181dbda8946e7b90c9e404d7fe75e.png 1 q6 q) h0 ^8 F6 R* }* a8 |/ |
! b! z5 ?+ _8 H5 N3 [
配置串口。
" e: A8 E$ H. W+ C% ], k6 A9 x$ Q/ C0 y
6fa28172f063490c9f66b66f1808ef96.png ( B' Z3 J* A8 w7 o
- F7 N1 U) j: \5 S4 q! N
由于需要输入数据,开启DMA进行接收。
. i2 M( U* h% Q* }/ t
. L7 y' U$ R1 E. D0 G" o8 t9 }  ^
f412f32d11f4428ab1f21fac63759508.png
1 `3 _0 Q( w! O/ E7 M& y  M. H5 l- T4 r- M6 ]7 P- I
中断。. [7 {4 N) O0 h  S! r4 `

. I: T2 p2 y$ c3 [
31ebe8f4bd604fec9bfa0b087220b3e0.png 4 s- p' N8 x& n4 k7 X5 M" i- ]: |' W
4 }0 E9 ?+ u' K3 E
SPI配置
" ^+ A1 _& l* G* x) \在开发板中有arduino接口,配置这几个接口为spi。

" P) ~- \3 W5 j" x8 }/ V2 S5 j$ s+ {

% \* K. y6 v) u# B. a$ l4 {. a 72bdb04b993d4c71900160ab38f4822d.png & V" a+ {; Z9 X0 N! @9 }( e

6 J9 \$ [) d) b. ]5 f$ s2 R本次实验使用的SPI与Flash通信,配置如下。
( _3 r9 w+ b/ X8 b; ]0 p- S: I7 ySPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。
% W% H9 M9 R6 i6 {8 a(1)MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;) [0 h" T% ?* X) U$ S$ Q5 [6 r
(2)MOSI– Master Output Slave Input,主设备数据输出,从设备数据输入;
( Y/ S; |' O. V4 m2 O8 z(3)SCLK – Serial Clock,时钟信号,由主设备产生;
' f3 W* ~5 v6 |1 O& V; g(4)CS – Chip Select,从设备使能信号,由主设备控制。
0 ~/ T( v& l$ D2 S1 I
0 U. U5 x! C3 }8 V( v
e066bc13ff35431789a0f629dc56c583.png
; E; m9 n4 C$ r, Z2 |  n; m" D
9 k+ A7 }/ e: c7 m' k0 h. _% P负责通讯的3根线了。通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCLK时钟线存在的原因,由SCLK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。因此,至少需要8次时钟信号的改变(上沿和下沿为一次),才能完成8位数据的传输。
8 J7 r3 Z& i8 {3 h2 ]时钟信号线SCLK只能由主设备控制,从设备不能控制。同样,在一个基于SPI的设备中,至少有一个主设备。这样的传输方式有一个优点,在数据位的传输过程中可以暂停,也就是时钟的周期可以为不等宽,因为时钟线由主设备控制,当没有时钟跳变时,从设备不采集或传送数据。SPI还是一个数据交换协议:因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。芯片集成的SPI串行同步时钟极性和相位可以通过寄存器配置,IO模拟的SPI串行同步时钟需要根据从设备支持的时钟极性和相位来通讯。
* S  r7 ^# M( F/ X3 ]* @, n最后,SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据。
) I2 T  }# M' l+ T4 }/ E+ k
) t7 r% E+ f' ~2 b
0518bf0da3df42a79291d95c298f9fed.png
9 k+ [- h( A( \! `- ?' E+ `# h' x& @; d
7 F/ I* A! G. _4 o其中,CS是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个SPI设备成为可能。
" I7 D! h4 v% w* u0 Y1 p7 I& }随便配置一个端口为CS片选,并且命名为CS。  G5 c: {5 R# J0 O5 x$ e
' c* _$ [! _* o+ y3 m% g
baaf5e9bdae84d68a8599ed26c05f5f4.png
- L- F7 j/ r; Q' g& x4 h* x$ I4 P& J1 x4 T7 l+ E/ O$ I$ O8 F2 C
NOR Flash/ D2 \2 O; ]4 Z) v# }4 U
NOR Flash是一种非易失闪存技术,是Intel在1988年创建。是市场上两种主要的非易失闪存技术之一。  ]7 D. I- D7 i$ _
以GD25Q64E为例,该 Flash为64M-bit大小,即8192K-Byte。

8 j% L) H5 p+ V9 y; A! h3 _
  |5 k; \3 K- V" w2 D3 X0 M( P

) ]. J$ A3 o; E5 W5 R' E0 Z 2558b1096ae9468b92039c513af4bf4a.png 0 V$ y9 R. X- }2 v  o# }
! m7 j/ c. w+ q8 o; M) k9 A
W25Q64将8M的容量分为127个块(Block),每个块大小为64K字节,每个块又分为16个扇区(Sector),每个扇区4K个字节。W25Q64的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。/ K5 C' H; {# [& ^: T! E+ i
即4K16128=8192K=8M
& [+ Y" X: u7 J' ]& R% B+ U/ ^, s; c- z
f95a474eaf814b508082a9605b54504a.png 8 u3 _8 ]  ^5 c
9 Q. K7 s& ]; Q2 s0 B# ?
W25Q64的原理及应用; h* P9 G# r, K* k8 S* g+ [3 n, C
复位初始化4 b% w" n" N8 }
对于复位,需要发送0x66和0x99. }2 R# P. w; I# A0 M* e

1 o. }8 ]  U; b
8b2131d6a7a74015becf6dc6ffe5e2c3.png / q* W% \2 z7 [; M+ l

! R0 a1 @3 {$ U6 S7 i; {& l5 a1 ^; ^代码中的初始化。
1 F1 L/ {* |& l# Z& O- _9 F" |+ i/ u0 R# i2 @
  1. /* Reset Operations */+ T8 p, l# s8 n7 h1 {4 _
  2. #define RESET_ENABLE_CMD                     0x66: k" E. c7 e+ x! i9 ~) B; b
  3. #define RESET_MEMORY_CMD                     0x99
    ) R& X4 A6 \" K1 s6 ^" l* f% \, l
  4. /**6 U7 f! x8 x6 c' `/ I5 E  L, X
  5.   * @brief  Initializes the W25Q128FV interface." g% _, K& W! ~, e! T
  6.   * @retval None
    ; C! R  i4 r5 c: z9 T  V
  7.   */  o& w+ M$ I% }
  8. uint8_t BSP_W25Qx_Init(void)3 {$ R: e, j! l2 F- B: K# l
  9. { + g0 y5 K0 l" C5 R
  10.         /* Reset W25Qxxx */! Y, l' z; I% b( A- V* u
  11.         BSP_W25Qx_Reset();& _+ H) ]% R( d9 Y) U9 w
  12.         
    . A# _- ]7 C! u' }. V2 ^
  13.         return BSP_W25Qx_GetStatus();% L2 L; C( }# y( f; B/ G7 E  y1 w
  14. }
    2 D1 s$ T, N. A- W+ K
  15. - }( @$ C, `7 B6 i0 L# S
  16. /**
    - _  N* A! i0 @6 [. z0 I
  17.   * @brief  This function reset the W25Qx.) C2 j3 u4 ?' J' X( M' S
  18.   * @retval None# {; q, k8 Y+ d
  19.   */9 F7 W8 [; f& A& b8 ?
  20. static void        BSP_W25Qx_Reset(void)& B( {* M4 e% F
  21. {
      [) ]9 |4 O+ \7 Y; |+ H; {; A
  22.         uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};
    7 j  [5 P# z* t8 m3 \; S
  23.         2 {: e, I" X+ r% \
  24.         W25Qx_Enable();% b# Q( a% q% n; F! @4 ]4 _
  25.         /* Send the reset command */& J( L  h/ n& i; U2 F, N4 h% ]& g! V
  26.         HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE);        4 L, ]) X" K2 B) z! f9 L
  27.         W25Qx_Disable();
    ' g7 ?4 l. w" D& w5 ]5 z. r

  28. 5 G! H: c" i* u) Q
  29. }
复制代码
9 V1 f4 m4 R8 A5 U
b6587dfc4fcd4f4a8ca0d58f32bd0f3a.png ; o3 s6 L5 s( w; a9 Z

* t/ E2 l- ]; Q- {5 eID
9 b) f" z/ s# w对于兆易创新W25Q64,主要有三种查询ID方式。5 F6 ^' V- }& Q& [
; f1 H$ I* ]7 Y4 }
a48ae7cccf1045c1ab70aa6ad37a32a1.png
- o4 |8 z  q  _% Z* X; I, X- A. \+ |/ s4 @! I1 z, H* r
可以使用90H查询设备ID,以判断是否是W25Q64设备。
% C+ @  H, _/ w* {- R# j# P8 m
; C* B! j7 p) p$ [+ x; T
1d515b4535034f138381e95e7dfaf268.png 1 H3 G  L  [' |0 p4 x+ Y2 D
  1. ; b) U' r) G4 ^3 C7 \9 c/ O
  2. /* Identification Operations */$ M- z7 {# k3 J' G5 j4 E3 k+ q
  3. #define READ_ID_CMD                          0x9F3 ?- i: u" C+ q5 z5 M4 o
  4. /**, I+ L* A- X6 o- D% ~/ R
  5.   * @brief  Read Manufacture/Device ID.
    8 ?- I% i3 W( T6 M! L2 \' a7 a
  6.         * @param  return value address9 K& |' H8 s+ y" G8 h: h
  7.   * @retval None* g! a5 [. W1 ]8 U/ ^- Y
  8.   */% {4 f- n7 O/ C
  9. void BSP_W25Qx_Read_ID(uint8_t *ID)
    0 [  @6 z/ O0 _- n
  10. {
      i, ?, d2 ^8 n) K) q
  11.         uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};( m0 v+ B/ y! F4 e& j
  12.         
    5 V# O6 Y3 Y' q4 l
  13.         W25Qx_Enable();! H# b9 b  ^5 h- F
  14.         /* Send the read ID command */" f8 _, E4 i5 f! t. Z
  15.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        
    4 M: H/ p$ V/ G) F" W
  16.         /* Reception of the data */* Q* y8 q, R5 g9 ^/ u  P$ d
  17.         HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE);
    * U/ S+ \6 Z& a
  18.         W25Qx_Disable();% b. M8 ^- D9 z: ]  ^
  19.                 # Z4 P! @2 G+ E, a2 k* S) f
  20. }
复制代码

* p! z+ e+ _6 I+ }# E

6 p$ ?8 _( a/ U! s5 x
e5f3e86b8a87496e942a4ea634b05f7c.png 0 K1 _4 T4 T7 K
- I# k( j, ^, f/ f
读取数据
/ `5 z! m$ ]2 A; w. f对于兆易创新W25Q64,读取数据使用0x03指令,后面添加需要读取的数据地址。
( n! ?+ Y! L4 r; g( L数据可以一直进行读取,当不需要读取数据时候将片选CS拉高,关闭时钟SCLK即可。
3 j$ i3 {# o2 @; ^2 B1 }' u9 X  I9 M. @2 ]$ P( l
b272600672cf45799b3e64f55e6aae0d.png 8 a% W6 {! y' q# v) T1 \2 H
7 E  v0 [" e7 [6 ~; ?# [
  1. #define READ_CMD                             0x039 p# c; m, I+ o
  2. 4 X: |9 i* }! d, L) s; P+ z
  3. /**9 i) T. u- }: l: h2 H
  4.   * @brief  Reads an amount of data from the QSPI memory.1 j, F% V+ Q+ I
  5.   * @param  pData: Pointer to data to be read/ Y9 e, i. \% q, N
  6.   * @param  ReadAddr: Read start address
    " r7 T7 O! w! M
  7.   * @param  Size: Size of data to read    $ d1 `8 `$ S- \& j& I
  8.   * @retval QSPI memory status( c' \' n& L/ _
  9.   */0 G6 ]6 }5 S- B6 ~3 W
  10. uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)5 p8 s2 G& a* n6 Y1 k
  11. {
    6 M+ l1 v7 |5 G$ g! F
  12.         uint8_t cmd[4];
    + Q/ E- p: w/ B! a' L% i
  13. ' Q1 x8 b+ {7 S# z6 I4 {
  14.         /* Configure the command */% v9 ?. z1 ^6 v+ k
  15.         cmd[0] = READ_CMD;
    , j6 k& m( b. V- h
  16.         cmd[1] = (uint8_t)(ReadAddr >> 16);3 [4 ^2 l! I3 b; Z5 \
  17.         cmd[2] = (uint8_t)(ReadAddr >> 8);
    % d' u5 q4 j8 [0 [" t) W
  18.         cmd[3] = (uint8_t)(ReadAddr);2 H6 t. O/ D( B7 c
  19.         2 U9 }& w$ S' h! O
  20.         W25Qx_Enable();
    / o  A7 r/ ~1 p4 k6 `# ~7 }' ]
  21.         /* Send the read ID command */1 @& I* f9 q7 S0 Y" n
  22.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        ! F4 g' w, f; B( d. F8 ]' `; R
  23.         /* Reception of the data */
    5 u" n; j/ e" j' r5 I/ H
  24.         if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)
    " B1 K2 f/ I. `
  25.   {8 O5 r4 r3 I/ A& B7 H
  26.     return W25Qx_ERROR;
    / U( X( N* B! {- x$ U' d; a4 ~( }! M
  27.   }+ o4 k4 x* d& \! P- W9 P* r  C4 O
  28.         W25Qx_Disable();
    2 a/ `7 z0 z  L8 \
  29.         return W25Qx_OK;: G: y2 t! C& m
  30. }9 r- ?9 M: y! P4 M% s
复制代码

# r  g' Z- F% H9 e* h' D# w" B, y以读取10个数据为例子,波形如下所示。
0 w$ U1 p3 W) W: Y+ y! x7 S1 ~# c" n$ H$ t/ N: `4 l, C- t
  1. BSP_W25Qx_Read(rData2,0x1000,0x00a);   
复制代码
   
/ J3 Q. Z' v! C8 i- X
c3d6f7aad1d44480af9c864c7ac99306.png
; E$ s0 u& w# ^8 x0 s, V) V- z9 Y  E; b7 g! C7 _/ n, y9 ]
擦除扇区
# \! R# z' j* ?+ C最小的擦除单位是扇区,擦除指令为0x20和3字节的地址。
! s2 L8 `+ V. p5 h5 ?1 b$ o8 d  O0 a) h6 b* @
3d02dfd6d21f45bb83426a95008cdbed.png
  w6 K/ O$ y" M7 K) n, H
  B+ \8 _: o# J" Y: M
  1. #define SECTOR_ERASE_CMD                     0x20& X4 ?% w5 P' `2 O% J9 Z0 i
  2. uint8_t BSP_W25Qx_Erase_Block(uint32_t Address)/ P( X' x  ]8 \
  3. {3 r4 O/ M4 h6 B- w) H) P% t
  4.         uint8_t cmd[4];4 z6 b% {* t7 b: q2 G( q
  5.         uint32_t tickstart = HAL_GetTick();; _4 n' K8 i0 {, c
  6.         cmd[0] = SECTOR_ERASE_CMD;2 `5 _& P5 N. n, p  ]
  7.         cmd[1] = (uint8_t)(Address >> 16);" `! [6 ~5 l# K/ B: J5 H
  8.         cmd[2] = (uint8_t)(Address >> 8);
    1 A/ ]9 W6 ~$ m. J
  9.         cmd[3] = (uint8_t)(Address);3 a% m7 O* \  N) |) Z% h1 a, J: V  }
  10.         
    6 W0 S; z2 V2 L: u7 n+ e
  11.         /* Enable write operations */: t. w/ W6 |$ @7 J
  12.         BSP_W25Qx_WriteEnable();
    / y- l: e4 s) y" @
  13.         
    # w7 V. m" r' S: g2 @' t# r$ q$ w
  14.         /*Select the FLASH: Chip Select low */
    9 R% T8 c4 D" v' a* _
  15.         W25Qx_Enable();* \3 Z. {+ [) y; D; B/ w5 h0 ]5 u* L
  16.         /* Send the read ID command */
    : M7 p5 Z9 p, G7 b. r
  17.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        ) }8 |7 j& ?3 B5 u5 R% j5 r0 r
  18.         /*Deselect the FLASH: Chip Select high */
    0 {# D% A, o0 \) b/ V# M
  19.         W25Qx_Disable();
    - Q: ]* g& J8 ?7 p3 S  w/ `& O1 S
  20.         7 ]% E( w3 ?: R1 K3 I
  21.         /* Wait the end of Flash writing */' ~9 x& z* X: W) }9 r4 t1 S
  22.         while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);+ I9 S( d% Y. [6 {! m
  23.         {1 S! O) \( k# l7 t! `! F1 ?; a" Q
  24.                 /* Check for the Timeout */  z# d0 e3 a+ Z9 _+ Q8 B; v
  25.     if((HAL_GetTick() - tickstart) > W25Q128FV_SECTOR_ERASE_MAX_TIME)- A5 n, Z5 l0 i% ?& N
  26.     {        : b6 U. Q" t0 u: v/ ]& ?5 [0 [
  27.                         return W25Qx_TIMEOUT;) d, T$ i! Z& @/ }
  28.     }+ S6 R7 ^" W6 z% `% ~
  29.         }" Z" E9 h6 m  h0 H; ?
  30.         return W25Qx_OK;6 z5 x8 q# c2 Z" L
  31. }
复制代码

* W( K1 j$ {+ O! J

1 {/ l1 ]! h& Z1 R& A
834c52348abb435c80e75aa7c084fe7d.png ) B4 ?: e/ R/ p5 f% b' M7 @& Q

) h% t3 x' \* Z, I+ H: J写数据: C1 `) e4 ?. A& C
对于写数据到flash中,使用0x02指令进行写数据,后面还需要指定24位地址,才能进行写数据。
8 K/ a3 _% ^4 C7 v; i# W' b1 O( U9 J2 H# P# f/ Y2 i! J& Q; \
08573995dfeb42a9afffabdeefe38f2b.png
3 q& x; V* Y# a$ L/ l: R& q" G0 T. R  i- ^
  1. #define PAGE_PROG_CMD                        0x02
    : f/ X4 Q$ I/ D, B: C' }
  2. /**
    $ s  U/ J7 s7 o5 D, i  Y3 z2 E0 n, g
  3.   * @brief  Writes an amount of data to the QSPI memory.& [& i7 X3 G( H# k* i
  4.   * @param  pData: Pointer to data to be written$ G, g# K( w2 Z, l% `) ]  P
  5.   * @param  WriteAddr: Write start address1 W, F+ X, I& U* }% J7 k6 `
  6.   * @param  Size: Size of data to write,No more than 256byte.   
    5 P0 I+ d+ T3 H* g* |' J9 u) ]% a
  7.   * @retval QSPI memory status
    6 q4 }% l( v! }, U
  8.   */' H: C5 q. p5 s$ _/ z7 P( k" v. L
  9. uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
    ) r2 q- N$ x, O0 G
  10. {
    # r1 n3 f1 [2 l1 E
  11.         uint8_t cmd[4];/ J: \* o- ]$ ]- k
  12.         uint32_t end_addr, current_size, current_addr;
    & U! V# c! s4 {! ?
  13.         uint32_t tickstart = HAL_GetTick();
    , ~7 d% A3 t6 d' {
  14.         7 l$ q9 G6 @8 @. t- r/ y6 k1 `  j
  15.         /* Calculation of the size between the write address and the end of the page */) b6 y! a) D4 U% p  F1 b
  16.   current_addr = 0;+ P! x4 _- p& m) D; N8 g& `
  17. * K3 D4 f' Z# Z3 K$ [9 S. X
  18.   while (current_addr <= WriteAddr)//判断地址属于哪一扇区开始- F& {7 k! _1 n% {" S+ n
  19.   {: ^) e2 ~9 P" x$ o  U
  20.     current_addr += W25Q128FV_PAGE_SIZE;//0x100-> 256 bytes$ f/ R- p: C$ _5 `  v% `6 M' l
  21.   }. V& o1 o9 s9 h
  22.   current_size = current_addr - WriteAddr;
    % c' j$ G1 B) n' a8 X

  23. 7 p' ~$ B* w+ T/ H! B
  24.   /* Check if the size of the data is less than the remaining place in the page */8 A0 o9 l- i2 x# a
  25.   if (current_size > Size)
    % A# K+ u5 X0 P+ m0 m
  26.   {# N. A! [. U, A  ^% E& P: Q- e' p
  27.     current_size = Size;
    1 s" i- T5 f  |: X1 ]' m/ @$ a) D* Q
  28.   }+ d8 q  H/ h5 l, h0 U

  29. ; Y- F, P5 j, I$ J) |
  30.   /* Initialize the adress variables *///写入地址大小范围
    $ B3 i- U# V/ F
  31.   current_addr = WriteAddr;, c) I  @4 O, v& U2 C4 L
  32.   end_addr = WriteAddr + Size;/ K8 p9 n; c) F4 i! `  Z: c/ Q
  33.         
    - X, L1 X4 d( [) Q8 m# c/ p
  34.   /* Perform the write page by page */4 z8 y6 b2 R# ?6 @6 ~/ a; o
  35.   do" Z+ Z* s% c5 k: Q$ ]5 r& H
  36.   {
    4 A, j1 Z" ^) _  E, J% E
  37.                 /* Configure the command */
    + {# [& M6 M! i& w) R2 L% [
  38.                 cmd[0] = PAGE_PROG_CMD;
    1 v" G3 ?! m4 _( o* r: z& r
  39.                 cmd[1] = (uint8_t)(current_addr >> 16);( \9 c1 E- S) \5 i) V7 o
  40.                 cmd[2] = (uint8_t)(current_addr >> 8);# K1 [* U1 }, s2 a
  41.                 cmd[3] = (uint8_t)(current_addr);
    # W' N) ^& P7 Y0 }1 d. F1 A+ I

  42. ) |7 E; A+ l6 S9 M
  43.                 /* Enable write operations */
    2 F# O" U4 F& p* F2 g
  44.                 BSP_W25Qx_WriteEnable();) S3 c7 ^! x# V: j& A
  45.         : W, B& ]: A  j0 [$ N. p
  46.                 W25Qx_Enable();; o0 L1 P0 s' w2 j! N' _6 g* D& m# s4 `
  47.     /* Send the command */
    ' [% s) q+ R# g+ w/ U7 V
  48.     if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK); m* Q, m  {3 W5 N; u( V
  49.     {, v4 o9 B- R9 X4 f
  50.       return W25Qx_ERROR;
    ' a; F: t0 w5 I* c+ V# ~  y
  51.     }  T3 A$ @6 C" T" ^/ e

  52. + c$ T$ U" U+ s+ v! U/ T
  53.     /* Transmission of the data */' l9 C2 N4 V6 r+ i9 v
  54.     if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)
    5 ~0 l9 W. n3 g1 ^% Z+ y
  55.     {
    4 r  y( S$ o) g! B& V
  56.       return W25Qx_ERROR;  ?: l6 y) L- s5 m# f
  57.     }+ D8 o' W" |* V; f5 f
  58.                         W25Qx_Disable();
    4 V% o- ?# N& C1 {& b( C6 E
  59.             /* Wait the end of Flash writing */, Q- L8 F4 b4 [4 I3 N
  60.                 while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
    ( h8 v7 ~4 j# Q. U5 a* P' c2 q
  61.                 {
    ) l  D1 V, F) [% ~2 h6 o; H
  62.                         /* Check for the Timeout */
    8 ]* ?. R' |: H+ ]: R: e& e9 h
  63.                         if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)
    8 W9 l6 e% a0 k& y" S  d. o8 u7 f
  64.                         {        7 r6 C6 G; ~  R7 }
  65.                                 return W25Qx_TIMEOUT;6 Q0 e6 |8 |& m  Y9 ]
  66.                         }
      |9 Z9 M/ q- Q+ T
  67.                 }  \8 l. L$ h# m

  68. ' S6 S; I3 i! w: D
  69.     /* Update the address and size variables for next page programming *// L  l: e$ u0 t& j% B& q4 J8 l  E
  70.     current_addr += current_size;, p% K! \2 I0 w" D% N4 o& z
  71.     pData += current_size;
    5 {( B9 R8 F3 x, p; ^1 U' P0 r/ n
  72.     current_size = ((current_addr + W25Q128FV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128FV_PAGE_SIZE;
    + h: u0 c: o! E$ _) T
  73.   } while (current_addr < end_addr);
      m& V0 r" X" }
  74. ; M/ U' o- V& |$ y
  75.         
    . I4 n( U* e6 g
  76.         return W25Qx_OK;: N! `6 l7 v- r( h
  77. }
复制代码
( o" q( _# R) l- R4 |+ Y0 H
对flash的0x1000地址进行写数据,指令如下。. F0 W& K# l0 v7 P( @

' D/ d3 d( o) {7 {' v
  1. BSP_W25Qx_Write(wData2,0x1000,0x000a);
复制代码

! A  D/ V$ G0 ~& A6 i" @波形如下所示。
% g+ z) w; ~/ z/ t; R& x7 U: _6 X0 q
394ce62c94db47a2875ff0cec94ffbda.png * B2 N8 o+ F4 ~* ~, E1 g

2 A& Y7 @. Q; x8 h5 \+ \W25Qx.c9 ~6 t! x$ X" P7 {( k# l6 ]
  1. /*********************************************************************************************************
    . m9 K. H, s& F: {
  2. *
    . j( N" E  U4 B. n1 o
  3. * File                : ws_W25Qx.c( b  X4 b  T. u1 g/ Z6 M
  4. * Hardware Environment:
    ; u" _4 t: u# c7 B- G/ g* `
  5. * Build Environment   : RealView MDK-ARM  Version: 4.203 L1 Z: t! R* h, c* |
  6. * Version             : V1.0
    # |  O8 [6 J9 o3 \
  7. * By                  :
    6 f3 ^/ [. ?7 H( q5 |% m+ s
  8. *2 u% X* s0 T7 j! N
  9. *                                  (c) Copyright 2005-2011, WaveShare
    ' |. }- q( [% m4 _
  10. *                                       <a href="http://www.waveshare.net" target="_blank">http://www.waveshare.net</a>- q; V- k& K& c6 g
  11. *                                          All Rights Reserved+ j3 Y! W4 C( Q  M7 {
  12. *, d: t& p9 }, A8 k* |
  13. *********************************************************************************************************/8 Y' @7 Q7 A8 ~: o7 J
  14. / X) j- J! m+ \; {
  15. #include "W25Qx.h"4 \2 z& o9 y/ Q( L+ y% H. l: ~

  16. - B# C; n3 @6 p$ Z' S' v* Q
  17. /**. K! [, ?: K# B: w/ N1 |
  18.   * @brief  Initializes the W25Q128FV interface.
    & T! }9 u& b0 L" N+ W' J
  19.   * @retval None
    / y$ D  X) ?; }/ L3 i5 ]/ `
  20.   */" N% {+ O& [. B9 c1 x3 }  X
  21. uint8_t BSP_W25Qx_Init(void)
    0 B; H. U  b7 c/ K: v) i
  22. {
    7 x; J( [. s' c) I  g& W3 x
  23.         /* Reset W25Qxxx */
    9 k- Z& i( b3 z- h( ^/ D
  24.         BSP_W25Qx_Reset();
    7 x& c+ G4 P; ^
  25.         
      E7 x4 O, ]' n0 J( F# ~
  26.         return BSP_W25Qx_GetStatus();- W# u, W7 x) t: Y$ ^& I
  27. }" y4 T& \8 r0 t

  28. * p; k5 S; S9 C% f9 \
  29. /**2 Z/ P0 N0 V: k  o
  30.   * @brief  This function reset the W25Qx.
    ) l1 z2 X, H' a( |5 M2 A  ^3 \
  31.   * @retval None0 X& {8 A" o1 n) n9 w( A
  32.   */
    4 g4 j1 x9 _9 g3 H
  33. static void        BSP_W25Qx_Reset(void)
    3 T! j6 F, j1 M# f7 V" W! G
  34. {- M; ?% P$ e2 p7 N7 _5 o
  35.         uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};
    8 b; @) F2 d) u5 @
  36.         ; Z3 h$ i8 E5 u2 u0 q( v% S3 Z& G% H, H
  37.         W25Qx_Enable();
    % F; S8 @1 @( m. x2 s. ]
  38.         /* Send the reset command */" ?  c3 a; C5 i3 T% q9 h% k
  39.         HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE);          R. r1 \. f' D2 B& l- ]9 L* ~
  40.         W25Qx_Disable();
    $ m7 }3 a& u; W, @1 {

  41. , Z" h" T' O5 u
  42. }- H( q  L3 v+ L' I1 y5 |
  43. , K0 ^/ ]6 d3 l
  44. /**
    1 K5 i' X, g) o1 a# W7 K8 D0 _  l
  45.   * @brief  Reads current status of the W25Q128FV., ^3 ^; d! w5 ^* z1 L+ P% G& s
  46.   * @retval W25Q128FV memory status: D4 g# A- c0 ^4 Z* c% u
  47.   */* x# g3 T" A5 N& q& Q' L4 F
  48. static uint8_t BSP_W25Qx_GetStatus(void)" O8 W, {% @% U$ e! N  b3 N; u
  49. {; P5 C+ l8 l- R, m3 A3 j
  50.         uint8_t cmd[] = {READ_STATUS_REG1_CMD};
    " Y( q: _/ |3 U- B7 y# I2 [! y' [6 f
  51.         uint8_t status;
    / r1 S6 C: x" U
  52.         
    ; U* \3 D1 q2 o- g: |8 Z0 m
  53.         W25Qx_Enable();: l# q0 i: _! x6 i; s3 l9 u
  54.         /* Send the read status command */5 `, X6 }% ~6 A# _
  55.         HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);        
    7 G% i* C$ j# f6 F) Q
  56.         /* Reception of the data */: m% h/ ~- F! Z( a, ]
  57.         HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE);4 w" S0 M" H/ G' t& q5 I- `1 X
  58.         W25Qx_Disable();8 y0 J4 T. y- n; o$ k
  59.         
    - o- ?  A- K# r( z% g
  60.         /* Check the value of the register */
    ( N& ]/ h+ c) O
  61.   if((status & W25Q128FV_FSR_BUSY) != 0)
    7 s- E; j3 a. ?7 B$ M
  62.   {
    0 X/ \( L+ |2 a' s. l/ b7 C
  63.     return W25Qx_BUSY;- I! x- O9 M& \& t
  64.   }' t9 t+ V# v9 b/ M+ Z5 r
  65.         else
    : W! i# R" p" m" L. |$ w9 P
  66.         {& T9 I+ e7 N; k/ S2 S
  67.                 return W25Qx_OK;# v& t/ v7 c) k' \3 ]  @" I0 @
  68.         }                4 w0 o2 k( s( H& m* T: [
  69. }
    + {8 y* a% h6 H% ?6 V( ?
  70. 6 O% {* S; s% h5 y
  71. /**
    ; P, q1 ^; r% h( Y
  72.   * @brief  This function send a Write Enable and wait it is effective.
    + b2 W( Q2 l8 e1 o' v
  73.   * @retval None
    % y$ z$ z* A# V# q( [- ?
  74.   */
    & Y. O) ^; X( n" z2 r9 K3 p( h
  75. uint8_t BSP_W25Qx_WriteEnable(void)$ U, b3 f2 r+ Z3 B& v! }3 M
  76. {
    ( Y& C4 a- Z$ x5 i6 `* y
  77.         uint8_t cmd[] = {WRITE_ENABLE_CMD};
    . F& W; O# ?6 [0 U7 B6 b( _/ X
  78.         uint32_t tickstart = HAL_GetTick();
      X- i; p' [  a+ S& V. w! \
  79. 3 T- ]; }- Q3 b
  80.         /*Select the FLASH: Chip Select low */
    2 M3 S4 d1 D: B4 [7 N& Y
  81.         W25Qx_Enable();
    2 u0 H. s# h; P4 x: M" ]2 k1 k
  82.         /* Send the read ID command */
    " S1 z! H. W# I( @: k# H
  83.         HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);        
    / L1 l# T3 G" x
  84.         /*Deselect the FLASH: Chip Select high */' ^6 }$ J2 P; H7 S7 C" P1 |
  85.         W25Qx_Disable();# X" n9 k9 Z  X9 x- ~: n' p2 B+ I
  86.         % v! h2 Y' t% ^+ O: o
  87.         /* Wait the end of Flash writing */* }4 }4 f$ M% d2 P: h& `8 M
  88.         while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
    ; ~  {+ f5 g9 z1 W  c
  89.         {; k! h  U0 C1 e% G5 ^; B
  90.                 /* Check for the Timeout */
    $ X& }% J2 i9 N3 X* i
  91.     if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)$ R5 ]6 n& g5 T9 n3 d  e
  92.     {        9 |4 e2 ?% c* v$ N. X6 @
  93.                         return W25Qx_TIMEOUT;' w7 P  F. @: K+ y, v
  94.     }# R9 V- ^+ H: \  R; [- z5 h6 @
  95.         }6 w1 s8 k( o* m6 Q$ q
  96.         $ T. w' w6 H1 c( p" S6 ?; b
  97.         return W25Qx_OK;
    ' j! Z6 r0 D: O5 \: `
  98. }
    / T# M2 h" ^0 j8 E. j( l& z8 i/ c

  99. 6 p+ t3 L8 {$ d
  100. /**; i, o* f  l- K: y
  101.   * @brief  Read Manufacture/Device ID.  e6 a" L5 k3 |: c, c
  102.         * @param  return value address
    8 P, J1 }" U; w6 V0 y4 r
  103.   * @retval None
    2 j3 S6 P6 e' m" Z) G% D5 B
  104.   */
    & k- C+ }4 W: d  {3 r+ c, S6 ^8 }
  105. void BSP_W25Qx_Read_ID(uint8_t *ID)
      D- ?1 u( S* P' n4 E: v0 n
  106. {
    2 h2 o, u7 ^. H! ^* m1 X! E
  107.         uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};
    : o+ Q( }1 L$ G7 }# g% u; I# }
  108.         
    1 C! A/ b: k6 ?& }
  109.         W25Qx_Enable();$ w" h  t: a/ c; U+ U4 w5 l$ ?) f/ z
  110.         /* Send the read ID command */
    ! S/ F- j7 x# o- ^! N% g! I
  111.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        
    ' U4 @1 Y" \- w, ^0 s  |& P2 c
  112.         /* Reception of the data */" G2 Y$ \& i1 {" \0 q0 P
  113.         HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE);! ~9 {7 c  ?# w0 t
  114.         W25Qx_Disable();$ ^+ ?+ F: Q8 H7 ]% v' y9 d
  115.                 ! v9 c  K4 T2 f
  116. }+ q" p2 L, {# b
  117. 4 ]+ b$ {$ ~6 I8 \
  118. /**) p* F; c& ]$ j& J
  119.   * @brief  Reads an amount of data from the QSPI memory.! H* s* y4 Q* k7 {
  120.   * @param  pData: Pointer to data to be read( w5 ]* \4 L4 t4 Q- [
  121.   * @param  ReadAddr: Read start address
    - V7 B0 p$ d9 D! N: r2 ]
  122.   * @param  Size: Size of data to read   
      u9 Z5 X- `5 u4 u, O
  123.   * @retval QSPI memory status9 h7 S+ D; T/ _( [
  124.   */
    ; e- V2 e! ?- F( L
  125. uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)- w: n& w- a, J
  126. {
    4 j4 {& @  N( |
  127.         uint8_t cmd[4];0 u9 F/ P& w& _3 k& D" ~3 ?- V' i! J
  128. 1 ~7 L2 R) ~# F$ y6 R' F5 e
  129.         /* Configure the command */
    , i& e, y: N9 t
  130.         cmd[0] = READ_CMD;
    ! e& Q' R5 y! `3 Y; Q9 J- a
  131.         cmd[1] = (uint8_t)(ReadAddr >> 16);
    $ ?! Y7 c  p2 r# h) r" Q3 G
  132.         cmd[2] = (uint8_t)(ReadAddr >> 8);
    8 ?, Z! U* D' T! i
  133.         cmd[3] = (uint8_t)(ReadAddr);5 L  u+ Z2 A- m  p0 @6 m
  134.         
    5 W, q: _. v, s
  135.         W25Qx_Enable();) j; J8 M5 B. l" z' P. ~
  136.         /* Send the read ID command */
    0 J* q) \7 o7 y' |8 {4 }! q
  137.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        
    6 @6 v, t; b5 t, V3 c. K
  138.         /* Reception of the data */
    - Y7 Z/ M- Z, r! K* T# C; N0 O
  139.         if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)$ e9 F! e. W; p) u. c& m3 L' D
  140.   {- c2 P: r1 S1 [$ M8 G, q- W
  141.     return W25Qx_ERROR;6 H3 o9 d! ^& {% k% k5 A, V: N
  142.   }6 y. R7 @/ P( D" t/ c
  143.         W25Qx_Disable();
      y( z& o& M0 J0 G7 r0 t
  144.         return W25Qx_OK;5 l3 c3 t# U7 \1 }. d. _: Z7 u  v. s
  145. }* y- K1 z. f) r4 a

  146. 3 U2 G6 v2 x% Y* y% ~+ |( y
  147. /**
    8 L  }" K+ {, Y# Y# O" m
  148.   * @brief  Writes an amount of data to the QSPI memory.; d& e# \: U4 P) z
  149.   * @param  pData: Pointer to data to be written
    5 ~2 p& V/ v9 Z9 x1 e, \- e
  150.   * @param  WriteAddr: Write start address
    1 V% b" E, V0 R8 e
  151.   * @param  Size: Size of data to write,No more than 256byte.   
    ! ]- \3 _; L: ~$ t  g/ A
  152.   * @retval QSPI memory status. w! i6 d3 x, `- E% A; O
  153.   */
    $ n- [' ]6 C* b) v- v) |  U1 @- i$ Z
  154. uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
    ; n5 ]9 ~0 m7 C% d' _
  155. {$ g/ m$ D" D- l
  156.         uint8_t cmd[4];
    ) r' X- i, ^: n
  157.         uint32_t end_addr, current_size, current_addr;# ?' `2 K& |6 N
  158.         uint32_t tickstart = HAL_GetTick();
      z* P" D: T& [4 O' _
  159.         % g* z- b# Y: K5 R4 \
  160.         /* Calculation of the size between the write address and the end of the page */
    + p5 R! q* N" a4 F, d' W1 F" O
  161.   current_addr = 0;
    9 ?' W' I6 h( U5 z6 p, I! C4 N
  162. " F$ g, Z- s) V8 S0 s
  163.   while (current_addr <= WriteAddr)//判断地址属于哪一扇区开始/ L/ ^* T$ W7 V0 _! b
  164.   {
    7 o, X0 [) \4 J) }( N
  165.     current_addr += W25Q128FV_PAGE_SIZE;//0x100-> 256 bytes1 p# r6 F8 G6 X  j  h
  166.   }
    7 J. R: c/ I- x8 ]$ X
  167.   current_size = current_addr - WriteAddr;( J8 F% m: }8 I+ O+ z1 b5 A

  168. & D$ \0 F) r- u
  169.   /* Check if the size of the data is less than the remaining place in the page */
    $ x% k/ d( Y- {
  170.   if (current_size > Size)0 L4 b2 `, l) m7 k1 Q
  171.   {
      K8 z, H" M( q# Q$ L5 a  d- d. o' s
  172.     current_size = Size;
    ; N3 X3 J$ M" m5 D
  173.   }
    " w& L( W" U( L) ]& n
  174. & n, V/ t0 z" i  R
  175.   /* Initialize the adress variables *///写入地址大小范围
    4 y. L1 q3 `: t1 i" d  _
  176.   current_addr = WriteAddr;8 v6 P" E9 a+ z
  177.   end_addr = WriteAddr + Size;
    ( Q5 o2 n  i2 }! Z
  178.         
    * [, t0 Y, F5 \, M$ [' _
  179.   /* Perform the write page by page */7 c4 r7 K* G$ y" S, }
  180.   do2 K3 ^! ?# h) p+ V) G, ?3 \
  181.   {# w: U7 o) y( E, q4 b3 S$ M
  182.                 /* Configure the command */
    9 O5 D  K' T! ?" I$ u( G  Z1 `5 x: M3 U
  183.                 cmd[0] = PAGE_PROG_CMD;
    ) ~* E/ @9 |( ?  X! c7 k6 q
  184.                 cmd[1] = (uint8_t)(current_addr >> 16);1 Y0 A7 ]( a* n6 m- N, u
  185.                 cmd[2] = (uint8_t)(current_addr >> 8);
    0 ]& F& ]6 a* R/ ^9 x1 S4 M
  186.                 cmd[3] = (uint8_t)(current_addr);
    8 _% O- D/ O3 a1 m2 Y/ [6 y
  187. ! ^! b& Q2 N& ^4 O
  188.                 /* Enable write operations */
    ' Z% U+ u$ J# [3 x0 o
  189.                 BSP_W25Qx_WriteEnable();% _* x; ]7 h) W
  190.         
    1 D7 N; h$ L: P/ \
  191.                 W25Qx_Enable();6 e+ ~+ w$ R" F9 k% H
  192.     /* Send the command */3 `! V9 [- M0 J
  193.     if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK)7 Z1 ?) @3 @# a" H
  194.     {
    ; A6 [& W- N# l; d
  195.       return W25Qx_ERROR;
    1 [3 m4 H5 `* w, a
  196.     }
    . Y; C/ Z7 P, F

  197. ' f: g) s: `2 j
  198.     /* Transmission of the data */
    % Z7 B/ y6 d8 y. t) r+ t, G% N* z+ q: @
  199.     if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)& Y' Q4 l1 g% Y' F8 f' D! q
  200.     {
    0 O$ {: a( k' j; n- H1 T- \
  201.       return W25Qx_ERROR;
    " H% X% m9 y/ X
  202.     }( `. k$ t; D! P9 ^, u7 r- I" Z
  203.                         W25Qx_Disable();% \! e5 Q' V4 ?) K6 ]
  204.             /* Wait the end of Flash writing */
    , v; h# K6 B; ]' @, r0 y. M/ M+ _' J* m
  205.                 while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);( G' x* M: p' c1 z; j" ], h/ M
  206.                 {( l: Q3 K* V4 ?3 W9 J9 I
  207.                         /* Check for the Timeout */) T6 o8 N. ~2 n; f- w( O8 S
  208.                         if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)8 t6 {6 w, x* p/ `- o1 n" u* o. ~
  209.                         {        
    8 x2 x8 w, H8 Q3 }  b
  210.                                 return W25Qx_TIMEOUT;  k0 d8 i! R* g$ ]  K; m
  211.                         }* U1 ^  \* v! V) D5 m9 {" ?
  212.                 }. z& |+ X4 F8 F1 F* q/ `8 J4 R
  213. % y6 G9 h7 Z  t
  214.     /* Update the address and size variables for next page programming */
    4 y* ^, \3 S5 b* j: l
  215.     current_addr += current_size;
    ) w5 p4 o& M; S# k4 u4 B7 S
  216.     pData += current_size;
    * I+ o6 ?1 ^  V6 O; T
  217.     current_size = ((current_addr + W25Q128FV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128FV_PAGE_SIZE;
    & Z8 G& `/ b. O: p: _
  218.   } while (current_addr < end_addr);
    * C; ~8 r3 y& `* X1 j
  219. 9 p9 `% A% j& B8 N! Z) ]
  220.         
    * b9 O0 s+ V* l. T' ~6 e: J! ^
  221.         return W25Qx_OK;. o* b  K* x6 V+ c" }. g* v1 G8 P
  222. }5 n9 l3 {7 ^/ J/ r3 n4 r1 {1 w( B

  223. ; d* @& K3 d* ]" F+ Z; `
  224. /**
    " v2 {0 `6 W/ [4 M/ r
  225.   * @brief  Erases the specified block of the QSPI memory.
    & v! O; b; e$ W1 _; r
  226.   * @param  BlockAddress: Block address to erase  
    0 O: l* K; e1 ^* r! H. x
  227.   * @retval QSPI memory status
    , T' ~% i2 c2 z8 T
  228.   */
    & \/ E' Y/ S7 Z; n3 U% [
  229. uint8_t BSP_W25Qx_Erase_Block(uint32_t Address), U/ B" S0 X$ M: I
  230. {: N( ^8 L' d; {: ^
  231.         uint8_t cmd[4];( V2 X5 Q. i# ?7 p
  232.         uint32_t tickstart = HAL_GetTick();% _8 o' K; R5 M
  233.         cmd[0] = SECTOR_ERASE_CMD;- b8 v$ w# @. Y2 Z
  234.         cmd[1] = (uint8_t)(Address >> 16);
    + O3 N! L8 ~; O+ p, C; I0 c
  235.         cmd[2] = (uint8_t)(Address >> 8);
    : O3 i# u: l$ e- l
  236.         cmd[3] = (uint8_t)(Address);7 G7 b1 K: c. d% C* U
  237.         $ ^" g! o# Y7 X+ M4 ~9 Z5 y
  238.         /* Enable write operations *// l9 h7 }( p7 h5 y+ S, m
  239. //        BSP_W25Qx_WriteEnable();2 a8 r2 _) j* Q8 [1 c% J; ?( D
  240.         
    * s" A  _7 `' N0 j' c* Q
  241.         /*Select the FLASH: Chip Select low */
    + g# o# Q' u! {7 T" g
  242.         W25Qx_Enable();
    7 q3 S' m* o1 [; q- T! T! R& Z+ Q
  243.         /* Send the read ID command */$ s+ X0 `6 Z1 ]( l' s2 U
  244.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        * E# C0 k+ O5 Q1 {8 a; J
  245.         /*Deselect the FLASH: Chip Select high */
    ! q& S# a1 U7 C+ }9 l
  246.         W25Qx_Disable();7 F0 \. W! v/ ]; Q/ L+ c
  247.         
    4 w6 t* U  s" p. }6 [/ B
  248.         /* Wait the end of Flash writing */3 Y4 T: K6 g/ ^
  249.         while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
    7 V0 ~! I3 c# v5 C1 s9 i4 A# }" f
  250.         {
    ! ]) X8 Z* ^5 z# g+ X3 [: U! f
  251.                 /* Check for the Timeout */
    " a: t) b9 L+ v% B9 V& I$ j, a
  252.     if((HAL_GetTick() - tickstart) > W25Q128FV_SECTOR_ERASE_MAX_TIME)6 v' t. t0 v5 ]5 C; b
  253.     {        
    7 j2 S) n9 }- c- U; N! F  j& x
  254.                         return W25Qx_TIMEOUT;4 b5 M/ [: f+ U& s
  255.     }7 b; A" H" R3 d( J: A+ F
  256.         }, z% {; d4 q- N8 Y* x2 j. n
  257.         return W25Qx_OK;+ t! p' X7 q" Z5 a
  258. }: ^% E  ?2 P% w6 Q7 x! t/ z" [
  259. - p- q/ @* b! L8 I1 ^
  260. /**. s* z( J- F' q/ o3 F
  261.   * @brief  Erases the entire QSPI memory.This function will take a very long time.
    5 ~% h$ @/ H! N3 ], ^( h
  262.   * @retval QSPI memory status
    " P3 T) {: P, d0 a. g; {
  263.   */+ H5 m7 a" @, H  S% s& G" R
  264. uint8_t BSP_W25Qx_Erase_Chip(void)
    . k7 S# a& Q( @1 F. V% {
  265. {
    5 s4 Y. V4 ]' l- o. v3 @6 |" {
  266.         uint8_t cmd[4];, K5 `/ i7 d- J: Z! D7 p6 L
  267.         uint32_t tickstart = HAL_GetTick();
    ! W3 t( q" l' d' n1 B6 l& I
  268.         cmd[0] = SECTOR_ERASE_CMD;
    , f% ~$ b1 q6 [3 G! f2 g, K
  269.         
    ; R* V' q2 s- P2 M6 q8 A
  270.         /* Enable write operations */
    7 [* a$ t% I6 G
  271.         BSP_W25Qx_WriteEnable();2 W2 e. a8 j& S- J/ x7 l5 J
  272.         
    ! H/ T0 {3 s- H$ K+ v
  273.         /*Select the FLASH: Chip Select low */
    / j  S  U1 f$ D; M! i
  274.         W25Qx_Enable();
    7 S. R  E: ?* t1 S5 O
  275.         /* Send the read ID command */
    $ E$ A' ^0 R, h' {
  276.         HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);        2 K* F8 j3 P) y! m& i3 G
  277.         /*Deselect the FLASH: Chip Select high */
    ) j6 B( f! h' V7 F; N- {0 M
  278.         W25Qx_Disable();
    ! j( y& P1 x$ n! f: S8 J* K
  279.         
    + X, v3 M' y% ]! P* J# d2 c
  280.         /* Wait the end of Flash writing */
    & u: h- F6 j' i! l# D# Q
  281.         while(BSP_W25Qx_GetStatus() != W25Qx_BUSY);
    ; p& C  L( n3 b# Q
  282.         {
    3 B$ X9 _, `  X5 V8 ~8 W  {
  283.                 /* Check for the Timeout *// Q3 n3 V. Q  @' r( G, R
  284.     if((HAL_GetTick() - tickstart) > W25Q128FV_BULK_ERASE_MAX_TIME)
    6 [* j) K3 ^5 ?; j0 W; k- @1 ?
  285.     {        ( m* g1 H2 r; c7 c
  286.                         return W25Qx_TIMEOUT;: G: g9 Q1 D/ G4 Y+ N1 T% h
  287.     }
    ; E' b6 w7 {$ Y4 p: o
  288.         }
    # L! c( B4 `! X5 Y2 i* `
  289.         return W25Qx_OK;4 w5 [6 E  R$ g& t% v; v
  290. }- v: S' _" Q8 X6 P
复制代码

& P8 d' ^: ?  F8 uW25Qx.h
# E! J4 @. E$ X. R4 [" D
  1. /*********************************************************************************************************
    ; F8 n' f7 x4 B% k0 X3 g0 }
  2. *
    5 q9 W& X+ O  `: ?4 W
  3. * File                : W25Qx.h* r0 b) F* q, r1 f1 d
  4. * Hardware Environment:
    : w! a; a6 h4 O% W/ l/ \
  5. * Build Environment   : RealView MDK-ARM  Version: 5.15$ h' M: I& F2 I+ B5 w7 L) ~
  6. * Version             : V1.0
    1 N' r  o/ \$ x7 o
  7. * By                  : ) d/ E1 N4 A2 _) ?. q
  8. *
    - v$ M( J4 |$ P3 ~, |% Y; ~  M
  9. *                                  (c) Copyright 2005-2015, WaveShare
    . v6 E/ t7 U. {4 @
  10. *                                       <a href="http://www.waveshare.net" target="_blank">http://www.waveshare.net</a>1 _  x. D  k! V
  11. *                                          All Rights Reserved
    1 U& J. H# C: N* P
  12. *
    # L, T9 y- t$ D- `6 m- H, C& t
  13. *********************************************************************************************************/! e7 d, p4 Z3 Y/ i' N9 @! Y2 T
  14. /* Define to prevent recursive inclusion -------------------------------------*/2 Z' P0 W3 D! X8 w
  15. #ifndef __W25Qx_H" s6 `- j- b, z' W5 E4 ?1 T; o! a
  16. #define __W25Qx_H
    # o; s& I2 d" e7 L

  17. 9 a# {9 w2 m8 @7 _" j
  18. #ifdef __cplusplus
    : |( F0 V6 J7 p" P; |2 h% k
  19. extern "C" {
    " i+ A4 M0 t+ d, [) ]
  20. #endif
    ) M, P& P3 x- h; W# N! Q' ^

  21. + t" H) C! J4 O) t+ W3 a. q
  22. /* Includes ------------------------------------------------------------------*/% E  @5 Z* B3 x& |- R. L
  23. #include "stm32f0xx.h"
    . }6 B: ~" e  j8 G; t( D7 ?, q2 r
  24. #include "spi.h"
    0 z. o4 s: e8 B( x
  25.          . U: ?, t3 |: ]0 q; Q! M; t0 p
  26. /** @addtogroup BSP
    3 z6 V) @8 [+ W& v
  27.   * @{
    * n5 r  I- j( ~# c* z9 X# C
  28.   */ # c- ]) t/ T- v

  29. 6 ~6 e9 _/ t* H1 _/ }$ ~; p/ e
  30. /** @addtogroup Components5 \/ g0 Z3 W1 i+ M* t$ s. p
  31.   * @{
    ; L! R  f! M' {$ ?2 d# s7 Q! m
  32.   */ ) K4 X6 m5 q# m% L5 P4 i
  33. 3 Q9 R) W4 A5 O9 [2 k# s
  34. /** @addtogroup W25Q128FV# D9 |  B# P" L" L
  35.   * @{
    8 B+ T) ~4 m( y( X
  36.   */- w8 D/ q4 c: w" t& [3 ~& o$ _/ K! ^/ A
  37. 3 j6 Y8 u. x9 V; a
  38. /** @defgroup W25Q128FV_Exported_Types
    . V/ u4 n  E, Z5 s& b) z: @. \
  39.   * @{: @4 R. q4 `3 K, V4 \
  40.   */: J& D5 [3 x- Y+ ^- |, @
  41. # Q/ x  h6 V+ S) @
  42. /**
    $ l0 t" Z; y( C% g6 Q- ^
  43.   * @}  q8 [* e0 B- o, @/ ~8 i9 J
  44.   */   b" s2 M7 X4 J! Q
  45. : [9 {0 H  R' M2 C# [+ C
  46. /** @defgroup W25Q128FV_Exported_Constants: y5 B1 N$ p7 G& R4 [/ ?4 v
  47.   * @{) D  ?6 z( k  ]0 I8 D9 D9 w
  48.   */
    2 D5 c" S8 M: Y, E6 f
  49. , T; N# ^# U0 w" B
  50. /** # X$ M1 b- p8 A* e
  51.   * @brief  W25Q128FV Configuration  
    : {# T+ a! ?9 A( Z' r: J; L. S
  52.   */  
    ' C. _* `& K  \
  53. #define W25Q128FV_FLASH_SIZE                  0x1000000 /* 128 MBits => 16MBytes */, S0 m* V3 F" @
  54. #define W25Q128FV_SECTOR_SIZE                 0x10000   /* 256 sectors of 64KBytes */
    $ F6 _- Y: _  d* L7 h- m
  55. #define W25Q128FV_SUBSECTOR_SIZE              0x1000    /* 4096 subsectors of 4kBytes */
    : Z0 s& X" o9 p. I$ H) d8 `4 U7 u
  56. #define W25Q128FV_PAGE_SIZE                   0x100     /* 65536 pages of 256 bytes */
    ' ?. E$ k  d6 ^8 ?0 f
  57. ; H, A) |7 O' X; \
  58. #define W25Q128FV_DUMMY_CYCLES_READ           4) u) j3 `) t2 w: w0 L' V; g2 _% A* J
  59. #define W25Q128FV_DUMMY_CYCLES_READ_QUAD      103 B3 w& h# k0 v9 w
  60. , w+ ~$ t" m+ A/ w8 J
  61. #define W25Q128FV_BULK_ERASE_MAX_TIME         250000
    1 R8 d  x! m. B! F! M- R) O
  62. #define W25Q128FV_SECTOR_ERASE_MAX_TIME       3000  _& l, U' c3 o0 D3 b
  63. #define W25Q128FV_SUBSECTOR_ERASE_MAX_TIME    800! z) R  e( X( {/ M' ~3 \
  64. #define W25Qx_TIMEOUT_VALUE 1000: G" ~6 I9 l. s3 s* |- u
  65. ) m) `9 p! F/ Y4 d- d
  66. /** ! d' k8 d! m4 T4 N. {
  67.   * @brief  W25Q128FV Commands  
    3 c' ~# ^4 ]( _+ [
  68.   */  * d; q! t3 l% x* l6 \3 S* G7 Y: P
  69. /* Reset Operations */1 ~" K9 r9 I$ Z/ x8 H
  70. #define RESET_ENABLE_CMD                     0x666 ]# d2 G0 @2 T- T. V
  71. #define RESET_MEMORY_CMD                     0x99
      i7 g- R$ D3 c3 Y+ b" W
  72. 6 m/ p1 m2 b1 n- v5 ?, R
  73. #define ENTER_QPI_MODE_CMD                   0x38* j2 s- r# G3 Q; P$ N1 }0 Z
  74. #define EXIT_QPI_MODE_CMD                    0xFF
      S9 C8 }: N0 c+ U
  75. " Z- t' u1 y- K' g. s
  76. /* Identification Operations */' Q, T/ I5 d" Y) M
  77. #define READ_ID_CMD                          0x90
    6 n) a- S  J% `7 Z5 |4 ~( t
  78. #define DUAL_READ_ID_CMD                     0x92- S4 b) E0 R: A+ p! T# D
  79. #define QUAD_READ_ID_CMD                     0x949 `( G# @% [& @" `/ k
  80. #define READ_JEDEC_ID_CMD                    0x9F8 m5 ]5 l; v1 b3 i$ h
  81. : {1 i7 s2 L# W8 b+ t* g$ S
  82. /* Read Operations */) ?1 S4 u. G4 T5 I  u  O4 T
  83. #define READ_CMD                             0x03  v2 `0 g6 a% t/ j  b: K
  84. #define FAST_READ_CMD                        0x0B% v: O% c  b5 Q5 h, E+ v1 V
  85. #define DUAL_OUT_FAST_READ_CMD               0x3B  }( _3 C. o+ [4 C8 \' A' A  [
  86. #define DUAL_INOUT_FAST_READ_CMD             0xBB, v$ ^+ @( I+ e& _- x5 m
  87. #define QUAD_OUT_FAST_READ_CMD               0x6B
    ) Z# |# J7 H6 E) @/ s' s
  88. #define QUAD_INOUT_FAST_READ_CMD             0xEB
    - [  Y, x/ F5 D1 F- n

  89. 6 b7 I" Y5 P# ]! _/ r& @  S/ {
  90. /* Write Operations */
    / u4 T5 s" Q% J- |! _% W
  91. #define WRITE_ENABLE_CMD                     0x06) D. Z5 f$ r. Q/ n9 E) @3 i: Z
  92. #define WRITE_DISABLE_CMD                    0x04
    1 g3 w% b0 `; e/ Y& `+ T6 ?' H# a
  93. 5 d* m& e7 H. a8 U( D; s
  94. /* Register Operations */
    & Q! G9 O5 h6 e$ b! n7 R0 Y* b8 i
  95. #define READ_STATUS_REG1_CMD                  0x05
    : B# E6 J0 g5 J4 V' ]" Y% L
  96. #define READ_STATUS_REG2_CMD                  0x35, ~3 u2 q, _) F% ^& e
  97. #define READ_STATUS_REG3_CMD                  0x15) _$ r+ b. Y# D' u* K  n
  98. ) w3 u. e) i! B* q/ ~- t' U# {
  99. #define WRITE_STATUS_REG1_CMD                 0x01! `1 Q0 H. d8 s3 z/ x# B; I
  100. #define WRITE_STATUS_REG2_CMD                 0x310 z# d7 L: k, x# L
  101. #define WRITE_STATUS_REG3_CMD                 0x11
    2 K. P$ R) Q+ D! c* U  E
  102. , E9 F& I/ t+ ~& d5 X6 P
  103. 0 [1 R4 c$ r0 \! x) ?) j% U& g
  104. /* Program Operations */
    + f0 u/ M& X: j! f; @
  105. #define PAGE_PROG_CMD                        0x02
    ; P4 U+ |, a; o- \) K. g
  106. #define QUAD_INPUT_PAGE_PROG_CMD             0x32
    . G0 R! I. T+ @

  107. 7 L/ ]( |! T! C
  108. 8 T2 u: z, F) L. r5 R- z/ f8 `2 r- l
  109. /* Erase Operations */
    7 C( g- Q9 W2 l" o) a+ V
  110. #define SECTOR_ERASE_CMD                     0x209 Y7 o( H8 r: y4 o0 @5 T, L7 h
  111. #define CHIP_ERASE_CMD                       0xC7- {: K6 K; I9 v, _9 |+ j3 `$ Z
  112. ! m, E" K" o3 V7 x9 f: U4 ^
  113. #define PROG_ERASE_RESUME_CMD                0x7A* a! O3 p% Y2 J2 l. s) o$ u
  114. #define PROG_ERASE_SUSPEND_CMD               0x75
    ) q& A* ~% [; X) p- v) ~

  115. + L& i& e. D" d! D
  116. 3 \  l0 q/ f& q- @: q: C) c
  117. /* Flag Status Register */
    1 x" |- W3 }( y5 i" K4 @3 V/ {
  118. #define W25Q128FV_FSR_BUSY                    ((uint8_t)0x01)    /*!< busy */
    0 t* ^/ F4 K5 B" ^  y
  119. #define W25Q128FV_FSR_WREN                    ((uint8_t)0x02)    /*!< write enable *// x" \9 `! `% ]
  120. #define W25Q128FV_FSR_QE                      ((uint8_t)0x02)    /*!< quad enable */
    / `; w' }; l: k1 P

  121. . M, t/ z' X- v- ~! j) U
  122.   w$ H7 Z4 u2 S, c9 K& \
  123. #define W25Qx_Enable()                         HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET)
    ! i. C9 a5 v2 m8 c2 T; W
  124. #define W25Qx_Disable()                 HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET): p! Y% h3 x% P& |
  125. - l2 ]: Q# q& k( R, t- H0 ~0 G. |
  126. #define W25Qx_OK            ((uint8_t)0x00)
    2 y1 P+ f3 ]  N3 Y, V6 Z0 B; w
  127. #define W25Qx_ERROR         ((uint8_t)0x01)
    # L3 j0 e2 G, E1 \4 J9 B
  128. #define W25Qx_BUSY          ((uint8_t)0x02)% \4 k, u& u, ?- ~) ?  g3 e6 Z
  129. #define W25Qx_TIMEOUT                                ((uint8_t)0x03)4 h) @* T1 f5 ?* h- ]
  130. $ D1 J3 ?& C+ v! s
  131. $ T1 g, d" r( g. l
  132. uint8_t BSP_W25Qx_Init(void);
    3 w3 |' r* x( d& P" @1 J
  133. static void        BSP_W25Qx_Reset(void);% y% o" \; Q; x+ y, _; ]- E) B% M! I
  134. static uint8_t BSP_W25Qx_GetStatus(void);" }% D5 A4 B' f, k
  135. uint8_t BSP_W25Qx_WriteEnable(void);/ L6 K, n+ Z6 Y6 G, `8 C5 `) m
  136. void BSP_W25Qx_Read_ID(uint8_t *ID);
    0 ^. b: [6 w7 U1 ?& x) x% G" T  I
  137. uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size);
      `; l2 _; R) m
  138. uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);+ a8 [4 d1 P+ H
  139. uint8_t BSP_W25Qx_Erase_Block(uint32_t Address);' b; B  l( [4 v. l7 ~% R
  140. uint8_t BSP_W25Qx_Erase_Chip(void);
    2 a% o, Z( q' w# w. u7 T/ i, ^7 G

  141. / C. D5 ?! |8 L, ~$ U3 w3 Y
  142. /**
    ( h  c6 L' m; U+ z* B  M( W$ m
  143.   * @}. }, b  I6 v; V8 s
  144.   */( @* \  Y) T" g: i. J

  145. ; r9 U/ m, g7 `) L9 E
  146. /** @defgroup W25Q128FV_Exported_Functions  O. H6 R8 T) u( d
  147.   * @{) _3 Z# Z. c$ s7 d9 p" m$ }+ }
  148.   */
    / s$ g$ K. r2 w8 A
  149. /**# w+ l3 v4 F4 P! F$ j3 O0 }& c. t
  150.   * @}
    , N9 o% o4 Z" ]: ^
  151.   */
    0 Z9 f* Q7 @/ J
  152. & V, _5 Z: o7 B5 D! g, a% T9 U- @
  153. /**
    - p# e, w$ ~0 ~, N' e* t$ z* s+ Z
  154.   * @}
    1 l8 ?- g+ }8 @1 {
  155.   */
      g8 v& @+ E! ]$ J& `  y

  156. ! K  b- i4 k9 S- A- X! E% Y1 L
  157. /**
    , U. F8 K5 |( m, x& _2 X1 D
  158.   * @}
    " |( x1 C7 N& b7 c
  159.   */ + ~  A$ }- g7 o- ]% R: ]$ B
  160. . n) @/ w. K  t
  161. /**7 L/ k% r- ^, ^. x% U( A/ t: I
  162.   * @}, f8 X; r/ H2 K+ n
  163.   */- `$ u6 c1 q( p- a! \! D; V- _& @
  164. / j% g& M: ~% j% g
  165. #ifdef __cplusplus
    0 z  j% v5 ^$ l4 U: c6 D' s& ~* x. P
  166. }
    7 |2 U0 }! E0 K5 @
  167. #endif- h, U- j7 l: X
  168. + e( V2 |2 ?6 R( ?. Y1 ~
  169. #endif /* __W25Qx_H */
复制代码
6 H! {9 X# }' F& d$ z0 y( L" V
案例
7 j* T1 G0 N1 _' `向0扇区(0块0扇区),17扇区(1块1扇区),34扇区(2块2扇区)分别写入0x200的数据。4 |# l; ]4 I4 \  U& ^; T$ h$ O3 g9 Z
/ I1 p: M1 y& k! L3 F: b4 e/ G
头文件定义% T9 ?& Q- ?3 @& e- ?
  1. /* USER CODE BEGIN Includes */8 a& f# H/ x- v3 R% h
  2. #include "stdio.h"
    3 r" k) O+ N+ F* K6 Q; u" F% B
  3. 6 E; {* {* _7 R6 I  F
  4. #include "W25Qx.h"! @" _- U  D6 k1 I. L. E
  5. /* USER CODE END Includes */
复制代码
. @2 t5 A8 t% y/ v0 }1 b, {4 Z6 {
串口接收和flash数组定义2 [% N1 f2 Q) a; P/ B
  1. /* USER CODE BEGIN PV */
    2 S0 J* k3 |+ |3 a# N9 ]8 L- [
  2. #define BUFFERSIZE 255           //可以接收的最大字符个数       & w! n6 c& L7 F" @
  3. uint8_t ReceiveBuff[BUFFERSIZE]; //接收缓冲区5 `# Y% G7 o7 a1 v# J
  4. uint8_t recv_end_flag = 0,Rx_len;//接收完成中断标志,接收到字符长度
    & |$ V1 d$ v( V% e
  5. - E6 b$ j6 Z  k0 P4 I" v
  6. uint8_t wData1[0x200];; X. y& z! a* a- V! ~
  7. uint8_t wData2[0x200];# o! c% w8 n1 k5 }
  8. uint8_t wData3[0x200];
    0 o  m+ ~: U0 D- s- y8 e
  9. - |7 n, l0 Y! I; X' R" g
  10. uint8_t rData1[0x200];
    8 I7 @8 z$ ]3 X. ^! U0 W) v
  11. uint8_t rData2[0x200];
    4 [0 |' H% @3 W9 y7 E9 T& S2 R+ T/ W
  12. uint8_t rData3[0x200];
    # n4 O" H0 R. ?( a2 K
  13. uint8_t ID[4];( J. F0 k# ~, Y2 x/ r
  14. uint32_t i;5 c+ {2 j: n; i' c( y1 {% Q; t. w; u

  15. 3 m) t$ m/ ?) ~& d
  16. uint8_t flag[1] ;3 N# |7 n7 E1 X
  17. int i_flag = 0;& `. T) {6 S7 u( u& v
  18. /* USER CODE END PV */
复制代码

: ~2 r2 K: R8 @5 j/ J* K2 K6 W串口重定向: g: N4 Z6 A3 k& z& y8 Y
  1. /* USER CODE BEGIN PFP */) P* r/ f; s9 Z  \6 D9 ?* _. z# e
  2. void uart2_data(void);8 A( B6 Z3 x  E" H4 ~8 [; v
  3. #ifdef __GNUC__                                                                        //串口重定向
    . @# A1 l6 n3 o1 i9 R) E+ z
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    $ y% i* R) U, M3 m4 ~9 F' k
  5. #else
    $ h2 M+ J" C0 y& S$ s' n' T9 Y9 N
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)6 W  G" K! C$ i/ C/ S
  7. #endif % |- }' y' [' d% d. [
  8. PUTCHAR_PROTOTYPE3 Z3 C0 d) d# `( q& G
  9. {4 S# o, J& u# Y; ~- a
  10.     HAL_UART_Transmit(&huart2 , (uint8_t *)&ch, 1, 0xFFFF);8 t; E* Q+ R# M% I5 T1 w# _  V  |
  11.     return ch;2 @3 n7 n: W2 w. C6 B$ B& \
  12. }
    " ^$ F. i0 c7 x# o- ~4 }8 ~
  13. /* USER CODE END PFP */
复制代码
0 p: j& |7 h6 M2 B' S& ]  O) M
串口中断设置
  g: P% P" i3 {6 \% |% K
  1. #include "stm32f1xx_it.c"文件中断外部变量引用:
    ; ?$ ~+ h7 Z1 b( ~

  2. ) c! d/ L6 v: `. z
  3. /* USER CODE BEGIN 0 */
    & E# g0 P6 \, [
  4. #define BUFFERSIZE 255        //可接收的最大数据量5 r3 ^6 }$ a1 E5 i) D- W9 {
  5. extern uint8_t recv_end_flag,Rx_len,bootfirst;
    + F) ]+ j5 [0 [
  6. /* USER CODE END 0 */
复制代码
2 i- a! F3 t+ }& x( }
串口2中断函数:& V, u/ z; q/ L; D+ X5 ^: n

& F' C9 X1 n: v1 t% ~
  1. /**
    ( u! y% A7 j) N  E( z6 ?6 T
  2.   * @brief This function handles USART2 global interrupt.
    ; p  u) a* P2 j+ r2 N4 h
  3.   */
    $ w5 v5 M# F* W) g, V$ c
  4. void USART2_IRQHandler(void)
    5 E6 A! m3 X3 n1 P& [9 [0 d
  5. {
    6 D1 q3 m, {. X6 L' [
  6.   /* USER CODE BEGIN USART2_IRQn 0 */
    # `2 j9 ]+ e& q8 z
  7. + d. ?' P* p9 y# [3 d$ o! C. N: d+ ]
  8.   /* USER CODE END USART2_IRQn 0 */$ v$ R. e' Z; j1 X6 x7 C
  9.   HAL_UART_IRQHandler(&huart2);
    7 E* s: K5 \& h# H* a& `
  10.   /* USER CODE BEGIN USART2_IRQn 1 */
    ! j* B1 ~. W$ d. _' U" k
  11.         uint32_t temp;
    ! a4 U' N0 t$ J( @2 V( D- z  y* }6 \
  12.         if(USART2 == huart2.Instance)//判断是否为串口2中断' z2 Q" `- Y; n* g2 w: O
  13. 6 n( b# @5 Y& e* U3 y" H
  14.         {      
    # C# m# Q5 e; k  _; U# _7 K
  15.                 if(RESET != __HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE))//如果为串口2
    3 u  v' e3 w8 ?0 s: l
  16.                 {
    + {6 {) ~) _3 w  k$ o4 \- n
  17.                         __HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除中断标志6 M+ f% p7 J# I2 m5 C9 `' P
  18.       HAL_UART_DMAStop(&huart2);//停止DMA接收
    # y3 G0 ?9 [5 @. q7 N0 E
  19.                      temp  = __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);//获取DMA当前还有多少未填充
    # T8 ]1 H% g& d* |5 m
  20.                       Rx_len =  BUFFERSIZE - temp; //计算串口接收到的数据个数4 F2 Z7 T8 v) X, v8 a6 W
  21.                       recv_end_flag = 1;" ]' A. H, G7 }, P# H" `3 D' m
  22.              }
    , S! ^" w+ K, v/ |5 U
  23.         }
    ! X* d: S& y* _" f; C% s- T( A

  24. % @2 D& R' }7 U8 W+ {# C
  25.   /* USER CODE END USART2_IRQn 1 */
    ' Y) k9 N  k" v. Q3 L0 [/ {5 w' A4 `
  26. }+ I1 _1 M+ S3 M" l
复制代码

  D* m. E) {; c主程序2 a5 V: a& b8 R& \* m  [
读取ID和flash数据及擦除。" W1 j# j% {3 [* m4 q9 Q( w8 _

: f. d2 n) a) I
  1.   /* USER CODE BEGIN 2 */
    - z. p4 Z! Z$ L) j
  2.         printf("GD Nor Flash案例\n");, B' J& @& c: B
  3.          __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);//使能串口1 IDLE中断
    5 w; O6 ]1 X  \  T+ P
  4.         
    6 b5 ?0 o7 L* Q; }2 A8 e) |
  5.         /*##-1- Read the device ID  ########################*/
    0 K( C; Y2 e# B2 |7 I0 ?2 V4 f
  6.         BSP_W25Qx_Init();//初始化W25Q128
    ' i4 Z9 f: g; o% D. B7 e' A
  7.         BSP_W25Qx_Read_ID(ID);//读取ID/ o( n; k/ ]7 i  `+ q' I$ W7 o
  8. $ k- _8 @1 L5 q. t  J9 k  L
  9.         if((ID[0] != 0xC8) | (ID[1] != 0x16))) |4 D5 b% p6 Z! s9 @1 m
  10.         {
    - E1 {1 N0 V; l+ p
  11.                 Error_Handler();//如果 ID不对打印错误
    3 S! A0 x" K  r
  12.         }8 w* N% u% V5 m* w1 W  o7 _
  13.         else//ID正确,打印ID
    ) C3 `& N, ?$ H$ g: {0 L& h/ o
  14.         {) Y- B; e% ^. x/ D
  15.                 printf("W25Q64 ID : ");& B1 G2 M$ G! P, o  e5 O7 T
  16.                 for(i=0;i<2;i++)8 m: t1 f2 a7 c4 u1 [
  17.                 {: e' a' K3 Q1 P& p' e, L9 \2 e
  18.                         printf("0x%02X ",ID);0 O& r) i4 n: [) j& s
  19.                 }3 N5 Q% e9 ?3 l; D$ [
  20.                 printf("\r\n\r\n");
    4 \" I, e$ c% X6 H! b
  21.         }
    $ f& Q/ ]% l- I3 O: G) k/ o
  22. : e% _; t* T% y9 p2 h0 b

  23. ' \  ^9 ^& I- m, }2 x' A
  24. /**************************读取第0扇区数据**************************************************************/1 r6 ^% H$ Y; W1 f9 z* W# L# T: }4 J% h

  25. / k" A$ [" P. f& A+ J
  26.         /*##-3- Read the flash     ########################*/   G0 H% ~! L5 ]- I- W+ P6 T
  27.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/
    0 Q; m% w5 i: y) z: b  d' o0 e+ e
  28.         if(BSP_W25Qx_Read(rData1,0x0,0x200)== W25Qx_OK)' d3 L/ K. v4 z5 o7 b, r
  29.                 printf("读取原始的0个扇区数据成功!\n");
    & t4 B% R9 f- l% ^1 J
  30.         else" \# f2 v4 W5 S$ Z4 m
  31.                 Error_Handler();" j  H9 m  R! _2 X
  32.         /*打印数据*/        
    , [. ?3 K5 x" `6 d# L
  33.         printf("读取原始的0个扇区数据为: \r\n");# q! K& k# w6 u; @
  34.         
    ) _5 D1 R! d: B" R
  35.         for(i =0;i<0x200;i++)
    * @, P% x* I4 u; [/ z
  36.         {+ W( [" m" v4 Q9 j
  37.                 if(i%20==0)
    2 h+ h, K- Z' Y9 H5 x! r
  38.                         printf("\n0扇区第%d到%d的数据为:\r\n",i,i+19);' t/ Q) w. n7 ?# T2 X; |" K. f" ~
  39.                                 printf("0x%02X  ",rData1);
    4 M' _  n+ [- m# `
  40.         }2 E) D  o9 P, M+ P, v+ t# L+ S

  41. " m0 N/ K- i7 z/ t" Y
  42.         printf("\n");
    ) Z- R- g: u8 B1 K: B' O" g  h5 I  k' a
  43. 3 i% k4 y0 S. s- k4 f) r
  44.         # w3 K5 ]- Q8 Z+ X
  45. /**************************读取第17扇区数据**************************************************************/
    2 d5 X. Q# n; q1 p3 U
  46.         
    - n/ M% |) `, X$ F7 Z( S" J
  47.         /*##-3- Read the flash     ########################*/ 0 D8 l0 O  k; b2 c
  48.         /*读取数据,rData读取数据的指针,起始地址0x1000,读取数据长度0x200*/
    4 X" E- v. h" r" n8 b, O: e
  49.         if(BSP_W25Qx_Read(rData2,0x11000,0x200)== W25Qx_OK)" q2 @) h/ p7 V: |/ V
  50.                 printf("读取原始的17个扇区数据成功!\n");
    ( j) z, k+ h* o' ^
  51.         else$ z' W: s) j1 X$ a0 S
  52.                 Error_Handler();6 k3 K! x# X8 U; x0 ]! R& G
  53.         /*打印数据*/        
    0 o: l0 q; ]/ B% M, s
  54.         printf("读取原始的2个扇区数据为:");% q' E. X, z; {- L5 Y. D
  55.         6 v4 c- S: r; G# ]" P& c
  56.         for(i =0;i<0x200;i++)
    " H9 Y% _( @' a0 P
  57.         {0 c2 R  H3 l% P! Y
  58.                 if(i%20==0); ]3 U  Z" J/ `) b* h# ^
  59.                         printf("\n17扇区第%d到%d的数据为:\r\n",i,i+19);6 L+ a6 i9 g& s' W' O
  60.                                 printf("0x%02X  ",rData2);. l% ^* e: B) q7 E# y8 I
  61.         }4 j4 L5 n  D' a6 o' {2 l8 ?
  62. % r& C; o, Q; P' \) R! R
  63.         printf("\n");        : b2 ^9 e3 v$ f  i" B
  64.         4 `7 ^% c5 C; h
  65.         
    : J3 ?) v4 v8 S, N; }! U
  66. /**************************读取第34扇区数据**************************************************************/- S2 T/ I2 `; b/ N' Z6 a3 R
  67.         * v" p/ ]: H: A/ m/ D
  68.         /*##-3- Read the flash     ########################*/
    & L( a3 ~( f2 u8 T* _7 S6 p- i
  69.         /*读取数据,rData读取数据的指针,起始地址0x2000,读取数据长度0x200*/
    * s1 N5 C* F" W7 D) ]
  70.         if(BSP_W25Qx_Read(rData3,0x22000,0x200)== W25Qx_OK)
    0 x* N" p* B  v& ^$ h* ~
  71.                 printf("读取原始的34个扇区数据成功!\n");
    2 Y  g$ J# K2 {9 a: x
  72.         else3 W8 D, ~; {9 n. P2 m! h
  73.                 Error_Handler();9 a6 b) U$ c9 k/ `3 k4 i# N
  74.         /*打印数据*/        4 T+ P* A, ?% j' A1 M
  75.         printf("读取原始的34个扇区数据为: ");
    3 v! ~* n4 ]+ u7 g# w" N8 U
  76.         & Y: j- ~+ \2 l* g
  77.         for(i =0;i<0x200;i++)3 U5 b8 q! q, S& ~
  78.         {
    0 Z& v9 ?: Q* d+ @
  79.                 if(i%20==0)( H' T# y& R6 P% w
  80.                         printf("\n34扇区第%d到%d的数据为:\r\n",i,i+19);/ U2 g' l4 p2 ]% B! u
  81.                                 printf("0x%02X  ",rData3);
    ' P& Z; C1 _7 W8 W( y
  82.         }6 T/ ]* \3 O2 j, i2 y. W/ Z% s

  83. ' l: n( u- t+ l% D) m6 n
  84.         printf("\n");        ( H# M. X% N+ o2 B& }
  85.         
    + P1 h) r, j* {8 {& S0 ^2 |8 M
  86.         
    & p2 t: ~/ f9 F4 P2 U# i
  87. % b" J  K+ \, }  V% A2 z
  88. /**************************清除第0扇区数据为0**************************************************************/$ P1 j9 z; M9 O
  89. / Z- M( z# r0 y% W. l5 s

  90. . \2 P% b% P3 E+ x9 v) K; y* \  N
  91.         $ d& j+ |/ _# w* ~$ X+ t5 R# S
  92.         /*##-2- Erase Block ##################################*/
    " X( b$ e) \0 p8 W/ A
  93.         if(BSP_W25Qx_Erase_Block(0) == W25Qx_OK)
    , }8 y3 Z# C* L# q: Q
  94.                 printf(" QSPI Erase Block ok\r\n");' q( c5 H- N( H% v
  95.         else, w+ Q: E/ ]4 g0 f" {4 m! j4 E+ ^$ y
  96.                 Error_Handler();
    # j/ U( o( p  z9 q
  97.         
    ! Y7 X( Y- [/ q+ Y  j$ U0 i8 E
  98.         /*##-2- Written to the flash ########################*/
    3 t  l  K1 A" M6 d! |( K
  99.         /* fill buffer *// f6 g$ z) L" d1 C: S0 k, ?
  100.         printf(" 初始化数据,清零第0扇区前0x200的数据!\r\n");
    : M( V' n% ~# [+ e* x# T0 v
  101.         for(i =0;i<0x200;i ++)
    2 _- X4 C# T; i. w, N- |: I3 D5 G
  102.         {
    - U& z( l2 z& H5 _
  103.                         wData1 = 0;  P/ [, a0 W% X4 T) R3 k! `7 Y" t: R
  104.                   rData1 = 0;( o. r% E. _2 l  }4 @; x
  105.         }
    ( o+ x1 D% M, A$ Y$ ]8 H$ W% E
  106.         /*写入数据,wData写入数据的指针,起始地址0x00,写入数据长度0x200*/
    , M! p. h6 F( H7 B; M3 P/ u3 _
  107.         if(BSP_W25Qx_Write(wData1,0x00,0x200)== W25Qx_OK)- J* d8 Q1 u4 A
  108.                 printf("清零第0扇区前0x200的数据成功!\r\n");
    " i$ p8 P; e- N
  109.         else
    - C% I8 G, ~6 v; W8 Y  A
  110.                 Error_Handler();
    : Q6 G, c4 G4 B$ w* o

  111. 4 h2 _( v' L, [8 F" W
  112.         % Z) u* P  W$ ~
  113.         
    ; n7 l- E' o- }' j# a/ }' l
  114.         3 a0 Y9 |+ {3 ?  z
  115.         /*##-3- Read the flash     ########################*/
    ( x# V; K! I9 |# V) j/ I
  116.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/+ C( q: U* J+ Q$ J- q
  117.         if(BSP_W25Qx_Read(rData1,0x00,0x200)== W25Qx_OK)  g1 D3 e2 X$ u  B$ ~/ q
  118.                 printf("读取第0扇区前0x200数据成功!\r\n\r\n");
    9 s. G5 p! t" }8 r4 o  t0 P% w
  119.         else
    # ?" m0 y' c  W2 f1 e* O
  120.                 Error_Handler();4 a' Y1 A" T4 v
  121.         /*打印数据*/          J; U$ G, Z' ]  ]
  122.         printf("读取第0扇区前0x200数据为: \r\n");, H4 j1 z% V1 T
  123.         
    + y/ b/ D9 R6 B
  124.         for(i =0;i<0x200;i++)' x5 b3 Z( T2 ~. r0 t5 h* V
  125.         {
    : l; W$ p, j, D1 R2 [
  126.                 if(i%20==0)
    ) l6 V3 O" v* K( h
  127.                         printf("\n第%d到%d的数据为:\r\n",i,i+19);
    8 p3 d& Z( ^6 U% t8 z% J
  128.                                 printf("0x%02X  ",rData1);
    - F' U( A$ b# N9 f! G
  129.         }( Q9 C% b: U- q  C; M

  130. 9 n$ _) i( T: a' N  Y3 ]4 v
  131.         printf("\n");
    - c% G$ k% u, \2 p7 ~* N* L
  132. $ p* }0 D: F# A% W; p
  133. / ^* A  g- n  R" R. {7 d
  134. /**************************清除第17扇区数据为0**************************************************************/
    . i5 ?: ^, y; z" q# g
  135. 8 v7 I% g7 e+ t5 u
  136. 5 w0 m, h6 k# U- {# t3 H
  137.         
    $ E  U0 a, K; K8 k& I
  138.         /*##-2- Erase Block ##################################*/
    1 @4 Q5 g( B2 \6 m2 r
  139.         if(BSP_W25Qx_Erase_Block(0x11000) == W25Qx_OK)
    : ~, a* M! z% S- l" I) S
  140.                 printf(" QSPI Erase Block ok\r\n");$ @# I6 z# i6 e8 _; I+ Y
  141.         else
    0 R* l$ F* }7 n9 ~
  142.                 Error_Handler();! V/ Z' u3 F4 G" Q- j8 n
  143.         
    , X# ], Q# M$ ]" F" \
  144.         /*##-2- Written to the flash ########################*/ " K5 d/ L, W& Y' h" v5 N6 p
  145.         /* fill buffer */
    4 ]) W1 ]$ Z7 ~* C; ?
  146.         printf(" 初始化数据,清零第17扇区前0x200的数据!\r\n");: H( l7 Z3 k3 f& p8 @$ h; Y5 {4 N+ R
  147.         for(i =0;i<0x200;i ++)$ N6 q+ Z8 Q; \: r( @# g
  148.         {
    ; g. u: N% [# {, z5 s, U
  149.                         wData2 = 0;0 ~" G, ?; J  h, u* x# o; u
  150.                   rData2 = 0;  \5 v+ ^9 H( j' C6 ]9 F
  151.         }  N0 l' C2 H' u$ u7 F0 O
  152.         /*写入数据,wData写入数据的指针,起始地址0x1000,写入数据长度0x200*/0 a8 C/ B/ ^; ~; `
  153.         if(BSP_W25Qx_Write(wData2,0x11000,0x200)== W25Qx_OK)
    ; n; ^: l! X  n
  154.                 printf("清零第2扇区前0x200的数据成功!\r\n");
    $ H7 D. F4 |3 @# L' q* n2 l( Q) `4 _
  155.         else
    % W9 X8 I* ?8 [- N$ u- f( \
  156.                 Error_Handler();
    % [- r6 H  B1 s9 V
  157. . x- d$ G% _6 n* x/ d
  158.         5 ]1 f* V& h* v! V- i* I! l
  159.         
    : }% g6 r0 C. p6 n# C/ B7 z
  160.         
    2 o% l, T' z. ~) j1 P  w
  161.         /*##-3- Read the flash     ########################*/
    $ v: Q- ]; o; {5 ^- D1 k1 I9 V
  162.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/
    / ^: X) D! t% t3 p; X2 }
  163.         if(BSP_W25Qx_Read(rData2,0x11000,0x200)== W25Qx_OK)
    1 U" |5 L: c. G. f* S  c
  164.                 printf("读取第17扇区前0x200数据成功!\r\n\r\n");
    : l9 e5 }* |3 i2 V
  165.         else
      W- A1 w3 f2 z9 m$ c# {' [* A7 h
  166.                 Error_Handler();$ W* G. E. ?5 A: U
  167.         /*打印数据*/        
    6 c' _3 [6 Z' \# N; ^4 b- Y
  168.         printf("读取第17扇区前0x200数据为: \r\n");
    & e8 u' Z8 y' H) |$ z9 p0 H
  169.         9 q& ~) [. p- D, V2 A: g
  170.         for(i =0;i<0x200;i++)
    8 F4 m+ B( ?/ ?
  171.         {$ X! O. H7 w5 T5 ]8 {
  172.                 if(i%20==0)
    3 P. ^' w0 y) Y0 @3 M8 t( f# e2 ]
  173.                         printf("\n第%d到%d的数据为:\r\n",i,i+19);6 ?8 s0 f) G3 w3 k0 x2 m
  174.                                 printf("0x%02X  ",rData2);: z, |* V9 @% D9 R8 ?" `: a$ R4 o# }
  175.         }7 E7 z: a; }6 U( E, @

  176. # }6 o# H3 ?5 U% S, f: s6 U
  177.         printf("\n");- q7 u0 \+ Q- M1 C% `4 l
  178. * D3 V' p% P/ Y3 K" Z# i* Z6 o
  179. : X  ?# x$ I9 z3 Q& N) D1 I
  180. /**************************清除第34扇区数据为0**************************************************************/
    6 Z5 \! M, G* ?& q) Z

  181. ' U, f: S6 n% k0 s

  182. % i( n8 g4 b  D2 O$ [
  183.         
    8 s6 Q( c6 B7 T0 i5 I" V
  184.         /*##-2- Erase Block ##################################*/ 3 V" g: g! p8 s' i$ F
  185.         if(BSP_W25Qx_Erase_Block(0x22000) == W25Qx_OK)- i2 O& I% z* Q/ d
  186.                 printf(" QSPI Erase Block ok\r\n");/ b* R. {  j4 B' B5 ^
  187.         else
    : |0 w% Y) g! L; o- n* r$ g8 K1 b
  188.                 Error_Handler();( Y! T* k! b! b% ^
  189.         % ?$ x; o: Z) G9 U3 q
  190.         /*##-2- Written to the flash ########################*/
    8 r* A- O" Z" L7 @  k, v# c1 X
  191.         /* fill buffer */, w3 P1 l' {# U
  192.         printf(" 初始化数据,清零第34扇区前0x200的数据!\r\n");% u1 }! ]* K8 J6 ^1 u
  193.         for(i =0;i<0x200;i ++)( i. k% Y/ U9 n  J, t+ n4 P
  194.         {
    3 m2 h- y7 K" q$ Z$ b
  195.                         wData3 = 0;5 q2 {1 Z  O9 [
  196.                   rData3 = 0;
    ( J$ \0 S" w9 N7 g$ X, `
  197.         }
    " M7 _& Z7 n6 W9 a2 D" F; [
  198.         /*写入数据,wData写入数据的指针,起始地址0x22000,写入数据长度0x200*/# y9 G# o8 v- k, X' l, K9 r4 ~, w7 Q
  199.         if(BSP_W25Qx_Write(wData3,0x22000,0x200)== W25Qx_OK)
    ( b9 T: \! [, O/ w5 j" D' G, {
  200.                 printf("清零第34扇区前0x200的数据成功!\r\n");
    0 S- M9 [% n$ c$ C9 M
  201.         else4 Y- o( J2 m2 H: {5 R
  202.                 Error_Handler();: P8 I& x" e4 o$ @; }

  203. 8 y1 L- t, R$ c6 M
  204.         . G( ], A- ]) W+ A
  205.         1 o. }4 Z- J: e
  206.         " p. C: q! d  o9 j
  207.         /*##-3- Read the flash     ########################*/ ' I: d! k! b" ?$ G, P
  208.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/! {0 S) ~( l' z1 g. q9 S1 |6 y
  209.         if(BSP_W25Qx_Read(rData3,0x22000,0x200)== W25Qx_OK): V9 {' Y! @" t2 t$ U0 J% r9 V
  210.                 printf("读取第34扇区前0x200数据成功!\r\n\r\n");
    # _( W0 [+ a8 \$ Y6 g
  211.         else
    % @, X3 q* r% \
  212.                 Error_Handler();
    5 L, Z) v  u1 E) i/ k3 d
  213.         /*打印数据*/        ( ^, V1 b& J0 d: o" b/ q- U
  214.         printf("读取第34扇区前0x200数据为: \r\n");
    - f0 G3 q8 \: R1 \; I$ G
  215.         9 s6 E+ O# G5 \6 l8 l- d9 r
  216.         for(i =0;i<0x200;i++)8 J8 A# M+ |  M7 A7 M5 t' |7 j/ I
  217.         {9 B1 g' [2 \9 w/ W: ?
  218.                 if(i%20==0)$ L% p" ^+ D" J6 Z1 J: [
  219.                         printf("\n第%d到%d的数据为:\r\n",i,i+19);
    3 O0 K  W& c$ z: j& D0 d; e
  220.                                 printf("0x%02X  ",rData3);6 j& K% j: `, s# r  s' ~
  221.         }+ j' o& e9 z1 X8 e) M
  222. 5 N; `# e% d& Y
  223.         printf("\n");
    3 Q& h7 v& Y& E
  224. ' m6 S# B+ x3 \+ p! M8 y  k

  225. & H: G6 x" w: y/ w  ^
  226.   /* USER CODE END 2 */
复制代码

) j, f0 r; J$ a主程序。8 K" h. o9 a* Q

9 y/ w: B# U7 f+ H1 O; w" P, I! K
  1.   /* Infinite loop */
    & [! M' e$ a5 p' h
  2.   /* USER CODE BEGIN WHILE */# n0 ~; }6 ^8 Q+ _; q0 g- J" ^
  3.   while (1)* p& W% x3 @. `+ V" ~
  4.   {
    7 w# B% [2 }$ l# ]' U
  5.     /* USER CODE END WHILE */
    0 k; ]5 M2 X1 U; p# i% t

  6. % S# S7 V) Z$ G
  7.     /* USER CODE BEGIN 3 */
    4 ]) @( N0 _0 X  }" b8 ^
  8.                 uart2_data();
    9 Q' V1 H3 ]3 ~) @* F
  9.                 HAL_Delay(100);$ J% T/ Q9 U4 f0 p# w' f* h) ?' O
  10.                 : l$ U4 x* R8 ~" \- K" Q3 L
  11.   }" k, y. L& N6 d
  12.   /* USER CODE END 3 */
复制代码

, [/ ]8 ^" Y0 z数据处理
# ^8 C1 G5 }3 G% N: ]2 A- Z
  1. /* USER CODE BEGIN 4 */
    5 c4 `  O5 ], W
  2. void uart2_data(void)! j, C8 F( ~1 j# X6 P* ~
  3. {
    + g7 K8 |( r5 s
  4.         if(recv_end_flag ==1)//接收完成标志/ Q/ |& v5 h8 L  M# ^4 T
  5.         {* c" b' L, O9 G3 U9 u9 S' n3 h
  6.         
    " T! M* R9 X7 k" P  p1 t
  7. ! u3 J2 N$ l: P0 V
  8. if(ReceiveBuff[0]==0x00)
    . o$ W4 W0 e. }! o9 e+ r" B
  9.                 {
    1 q) A" N2 |. a
  10.                         printf("写入数据长度:%d\n",Rx_len-2);
    1 h, V4 W( v; C
  11.                         for(int i =0;i<Rx_len-2;i++)
    ' D4 F  Q7 ~; \2 h+ r
  12.                         {
    7 z7 k' M5 Q) y1 X
  13.                                 wData1[ (i+ReceiveBuff[1]) ] = ReceiveBuff[i+2];9 |5 }2 _& c1 Y8 i

  14. ) V. b7 X  U4 ~- @$ \) x, x! {7 t" r
  15.                         }3 K! J- ]9 i/ |. g! h. e" q5 p7 d3 O
  16.                                 
    3 H1 Q, Z0 V1 x9 A/ q6 C7 _! f; E* Y
  17. / Y  O2 i' W4 k; u0 D
  18.                 /*##-2- Erase Block ##################################*/ 0 {# `5 B3 K8 _$ i; l; Q
  19.                 if(BSP_W25Qx_Erase_Block(0) == W25Qx_OK)
    . Z# B% r4 ~& l/ k+ T) R# l
  20.                         printf(" QSPI Erase Block ok\r\n");8 @. r) G* b+ m6 b6 g$ p1 J
  21.                 else
    " O: s# k4 p3 y, W# f8 B  L
  22.                         Error_Handler();
    & c2 d6 D3 \" W& O+ U+ u' _

  23. 6 t0 U1 y+ |! a( P8 w) N) l
  24.                
    5 I% \' ]1 _5 n; G* @! Z6 b, i
  25.                 /*写入数据,wData写入数据的指针,起始地址0x00,写入数据长度0x200*/
    2 {& t2 J/ M- b0 \( W; i' ^6 R2 Z
  26.                 if(BSP_W25Qx_Write(wData1,0x00,0x200)== W25Qx_OK)) E" d- s/ P, w) l% L  u- M9 d
  27.                         
    / R5 V, t' l- M
  28.                         printf("扇区0数据成功~~~~~~~~~~~~~~~~~~~~~~~~~~!\r\n");1 |) [6 K8 }3 B! c6 J- ?1 I
  29.                 else
    * C3 G$ m' T. Q+ S1 ?
  30.                         Error_Handler();
    ! {4 o8 ?0 I3 K- \6 |9 ^; n
  31.                         
    # @9 Q0 d# p+ x1 K3 q; }
  32.                 if(BSP_W25Qx_Read(rData1,0x00,0x200)== W25Qx_OK)( t  {- N* ?9 h' p6 Z1 k
  33.                         printf("读取扇区0前0x200数据成功!\r\n\r\n");  h% P, R# r* \3 B+ Q
  34.                 else. B6 L' O( |) `; a
  35.                         Error_Handler();
    ) O5 I+ M$ l. i$ t4 e0 e# w
  36.                 /*打印数据*/        
    . j7 m" i& \* Q
  37.                 printf("读取扇区0前0x200数据为: \r\n");2 h, u: n6 F1 D! o
  38.         8 a, L1 Z$ d# V/ x; V8 V) U2 ^
  39.                 for(i =0;i<0x200;i++)
    " Y( u) D$ y  T: E7 P) T2 G
  40.                 {9 j: j. A2 n7 l: P3 s( G* t
  41.                         if(i%20==0)9 ]2 _' m  d5 j7 A
  42.                                 printf("\n第%d到%d的数据为:\r\n",i,i+19);: z, r* |/ Q+ v; I: F% c5 ~; ?
  43.                                         printf("0x%02X  ",wData1);) x3 y, y6 p$ h$ B4 j
  44.                 }
    + F6 \5 ]' N# [7 j
  45. 6 A, g  A& M/ m3 R! M7 {( g: A
  46.                 printf("\n");
    5 F  s" j& a- A- B; j0 x6 k4 g
  47.                
    & d6 N$ E# V7 ?- n
  48.         }
    . j7 d* j8 U$ e9 J8 I- u4 D
  49.                
    ) _/ V: O  l2 P+ D1 ^/ W
  50.         ' p5 Z0 s& F) d
  51.         
    % T+ e; C2 g" |" o) H
  52.         else if(ReceiveBuff[0]==0x17)7 }2 k  A( z$ `+ {# r0 ~
  53.         {/ j! R% T, z7 z2 p2 S' A# ]
  54.                         printf("写入数据长度:%d\n",Rx_len-2);+ [, c! C; d( |) l8 i3 F
  55.                         for(int i =0;i<Rx_len-2;i++)
    2 J. s) a5 A( b; ?$ X! {* ^: L
  56.                         {" N, Y" K- H& N2 c
  57. //                                Data=ReceiveBuff[i+2];
    9 d/ w1 o- m" k! ]9 N1 {& G
  58.                                 wData2[ (i+ReceiveBuff[1]) ] = ReceiveBuff[i+2];
    4 B# l) p$ `- Q3 _& k
  59.                         }
    , Z8 [9 q5 ~& q7 c0 r
  60.                                 
    ( A# z; b( n3 V) [3 I: D% D0 K

  61. - T4 G$ a! R6 v% V* S
  62.                 /*##-17- Erase Block ##################################*/ ( @7 h0 |* Y/ G/ t9 A# W: P4 ~( C
  63.                 if(BSP_W25Qx_Erase_Block(0x11000) == W25Qx_OK)* h7 Z  v8 {$ f  S
  64.                         printf(" QSPI Erase Block ok\r\n");4 S& B! Z# v. }
  65.                 else' q4 j6 f, x" J* E) k6 y& e
  66.                         Error_Handler();1 F' d8 \1 d  B' d3 W3 V
  67. 8 {/ t' `3 [( Y; f+ Y4 H" M
  68.                
    " e/ W3 z/ a# t2 S; n8 R( m
  69.                 /*写入数据,wData写入数据的指针,起始地址0x11000,写入数据长度0x200*/
    & x7 |7 I9 S7 y7 ~* l. i
  70.                 if(BSP_W25Qx_Write(wData2,0x11000,0x200)== W25Qx_OK)3 G  T9 e) t% E6 H  l; M! e
  71.                         " Z! \* u  P7 c5 K
  72.                         printf("扇区17数据成功~~~~~~~~~~~~~~~~~~~~~~~~~~!\r\n");
    " h+ K7 M; A1 a: Y0 H
  73.                 else% O! |; @5 O5 ]: K) D
  74.                         Error_Handler();4 c; p- h+ {9 I7 h2 t- @
  75.                         ' U  B) k9 g- o
  76.                 if(BSP_W25Qx_Read(rData2,0x11000,0x200)== W25Qx_OK)
    8 e4 o) @7 t: Z
  77.                         printf("读取扇区17前0x200数据成功!\r\n\r\n");2 B, u/ u& _4 [/ P) q, G" I
  78.                 else/ Z. A: L2 V, l
  79.                         Error_Handler();
    1 ^$ ~/ B* b2 o  U" P4 e
  80.                 /*打印数据*/        
    9 K& F9 w: v! I- p
  81.                 printf("读取扇区17前0x200数据为: \r\n");3 s( T$ {3 Q3 n. N4 ^8 [3 S! v/ t
  82.         7 }8 D/ Q# h0 x  Q
  83.                 for(i =0;i<0x200;i++)
    0 n( j, _9 ^, q0 K) f3 j
  84.                 {
    2 O. O9 X1 f# N- U
  85.                         if(i%20==0)" R$ H! s( }6 U% S1 c  H
  86.                                 printf("\n第%d到%d的数据为:\r\n",i,i+19);7 o2 l& n" [; Z! P( D- M$ B
  87.                                         printf("0x%02X  ",rData2);! {# h1 Q8 _; b2 i$ X5 x- X6 p
  88.                 }# j2 r! d. Y) m) y9 }: B/ y9 [
  89. ) x2 n9 j0 ?* z1 D: r
  90.                 printf("\n");
    3 n" R. A2 P  u; c! T1 |
  91.                
    ! @2 P) _8 F0 c4 M! ^4 w% R8 i
  92.         }               
    ) Y* ]5 S& c, y# i

  93. % f; D0 k+ F( J2 Z+ r2 p
  94. 7 J. a: }7 D9 ^- z% f% V% K
  95. 9 l9 b8 \1 _0 k, j1 C: K% _. E
  96.         else if(ReceiveBuff[0]==0x34)$ L8 E5 l" F1 k5 r+ Z9 i) U
  97.         {
      T& o: l/ C8 Q$ L& S( a& }
  98.                         printf("写入数据长度:%d\n",Rx_len-2);
      G+ f. J0 |8 o% S9 f2 h# o7 g1 k6 N
  99.                         for(int i =0;i<Rx_len-2;i++)' X# G' H: _  n4 N! ]/ u* J
  100.                         {' Q" W9 r3 N2 p, }
  101. //                                Data=ReceiveBuff[i+2];  L* s0 p& T5 s" F
  102.                                 wData3[ (i+ReceiveBuff[1]) ] = ReceiveBuff[i+2];
    3 s6 Y  q/ j* V
  103.                         }
    5 ^% m& G% `- Y' V/ j
  104.                                 , C- p7 }4 ]$ \

  105. ! a, I1 D5 C3 a2 ^
  106.                 /*##-22- Erase Block ##################################*/
    ( G: F2 q% u0 X5 i4 o
  107.                 if(BSP_W25Qx_Erase_Block(0x22000) == W25Qx_OK)  {& f" e1 N, K7 j+ G; |9 G' ?7 h; d
  108.                         printf(" QSPI Erase Block ok\r\n");
    9 ^3 \: C+ \" ^8 |9 p( A2 P8 ^
  109.                 else# u( u7 h3 v  k/ x9 O
  110.                         Error_Handler();: l% K1 G6 [; ?9 r* L

  111. . v  E: e! w+ ~* R( Y, X% r5 w+ O& F) p
  112.                
    : o8 j5 v6 ?6 F  a8 r0 _
  113.                 /*写入数据,wData写入数据的指针,起始地址0x22000,写入数据长度0x200*/0 p  [; p9 @! K! v1 K
  114.                 if(BSP_W25Qx_Write(wData3,0x22000,0x200)== W25Qx_OK)0 \- M0 j/ |- x! k
  115.                         7 \6 x: v. e( X1 k: o4 R
  116.                         printf("扇区34数据成功~~~~~~~~~~~~~~~~~~~~~~~~~~!\r\n");3 R: I* z5 H2 {, I+ O  D
  117.                 else
    8 c! R. C: Y& `, `- I
  118.                         Error_Handler();( Y8 [% J7 l7 _
  119.                         . l3 [0 }9 i( H6 X) n  k7 Q
  120.                 if(BSP_W25Qx_Read(rData3,0x22000,0x200)== W25Qx_OK), o! \/ y4 X" c
  121.                         printf("读取扇区34前0x200数据成功!\r\n\r\n");) M6 h% x$ Y4 m$ G9 K( {5 O
  122.                 else
    * Y( u" p7 ~, B1 e
  123.                         Error_Handler();) C6 d3 Q' O# L9 N7 k
  124.                 /*打印数据*/        7 d) Y% y: D# R/ g) |( M3 r
  125.                 printf("读取扇区34前0x200数据为: \r\n");
    - q# }$ J, W- \0 y
  126.         
    - g: i! W& k$ Y9 r; J2 k, U" t
  127.                 for(i =0;i<0x200;i++)
    ; g+ J/ Q+ a$ a
  128.                 {4 [2 @' `8 r' P& b6 ?1 ^
  129.                         if(i%20==0)6 q3 w( [6 o" v: H$ ?
  130.                                 printf("\n第%d到%d的数据为:\r\n",i,i+19);$ Q! q2 p$ j- d! }  I
  131.                                         printf("0x%02X  ",rData3);
    " _2 L) Z) g" ^  y3 N( L( Z! X
  132.                 }
    8 m  |2 K0 c$ G) g% A" B- A5 L
  133. ! q  P0 k, Z* N" Q. Z. \  f3 n& d
  134.                 printf("\n");  C- z6 H- C- d5 A7 {
  135.                
    $ k- j3 F+ P, ]: H; t8 ]0 h
  136.         }        9 M% l! ]( L% g3 h* v

  137. 3 c4 b7 {/ q3 s/ Y. u* e$ u& Y- w

  138. " K3 q  M  M" [7 W
  139. 6 l7 a+ O7 {' d1 P7 d* V
  140.                
    7 s) |! h5 |, F) o. f$ X
  141.                 else
    ! p, ~2 `! Z( ?$ k' f  e& Y9 k8 V
  142.                         printf("输入错误!");
      z' `7 \2 f$ N, m7 P( r$ X3 {7 b

  143. # ?0 D. k3 d7 O4 ~
  144.     for(int i = 0; i < Rx_len ; i++) //清空接收缓存区( ^; _6 {2 k) |; ]; K; b3 w4 M) ~
  145.     ReceiveBuff=0;//置0! l5 S( W$ P, Z* ~1 j
  146.     Rx_len=0;//接收数据长度清零* D7 J7 `; B5 F5 t7 W. c
  147.     recv_end_flag=0;//接收标志位清零% Q& A' r  y2 `% W  r5 |% {6 |0 B' v
  148.                 //开启下一次接收
    7 X. Q- ]& U* T+ a1 Z
  149.     HAL_UART_Receive_DMA(&huart2,(uint8_t*)ReceiveBuff,BUFFERSIZE);
    2 Y  V2 O" z* O1 D1 {' S6 g1 s
  150.     }% Z/ s! K1 A' S% j! z

  151. ( T; M" y; H* H* D: d: i
  152. }: c0 O. ]# ^! D) y

  153. " w6 B3 \4 v) U; k
  154. /* USER CODE END 4 */
复制代码

! E& s: H3 a) l* U0 S* N演示
- a1 u/ N3 z# v1 T2 n( `W25Q64芯片型号的ID为0XEF17,下方读取为0XC816,所以读取成功。
9 c5 \) C4 x) s0 j5 Z
* r- e2 h9 a  e- _5 d8 E/ {
724107be5c7743688035f34171618ec0.png 4 S9 J8 w4 {# k, o
7 P3 \9 W# K/ a2 ]6 L
开机会打印出0,17,34扇区的前0x200个数据。
% c4 c/ j" e# F4 j" D/ S) }& e5 i
1 F. v$ x. k+ }0 D3 y9 `- j
23708128edc5478382c20fa961eff4e8.png
( i2 A- Y5 Q4 V, E# L# l9 v# X4 k* [3 z
4 x% ]; r7 w3 u' X! F* L3 n打印完原始数据之后将数据全部清零,清零完成如下图所示。
6 X# g' ?3 t0 G5 R4 r% t8 U* K6 {
0ac9a59d0a6f4138bbc3ea3e3e3c612f.png
6 u: Z4 }  ?" K0 P0 Y6 K' I5 s, T  b1 q1 e0 H% \0 @
串口定义了ReceiveBuff[0]的数据为写入什么扇区,ReceiveBuff[0]为1写入扇区1,ReceiveBuff[0]为2写入扇区2,ReceiveBuff[0]为3写入扇区3,若为其他数据,则打印输入错误;ReceiveBuff[1]则为写入的位置。
6 [/ B+ `$ ?2 \2 r$ l/ \9 b# N  F% b2 F输入:00 05 01 02 03 04
7 z8 T  t  |/ ^5 L% \向扇区0的的05号位置开始写入数据01 02 03 04。. }5 r) \6 U$ J) B% w

/ u  \5 U0 U( C- C4 g2 f
bc97fcddb01b4e3182345641d2fa28f2.png
7 X! Y9 j* \! a* z, O7 Z+ W8 i8 q' b: y! S) V
输入:00 28 11 12 13 14 15
9 I$ y) s* M% f- E向扇区0的的40(28是十六进制)号位置开始写入数据11 12 13 14 15。
' R; T% @7 g- @! q* _: ^" I' d5 j# k4 H, x% g+ d7 p- V# V
4770ed6a70c849228eba1429605c74a7.png
2 ~2 L+ _& k$ m9 N$ x% H" t. h; M" a' H
输入:17 10 aa bb
9 t( O2 K! ]: D7 n0 l9 e) s向扇区17的的16(10是十六进制)号位置开始写入数据aa bb。0 f  D1 A2 o- V7 v/ b

7 u& \, k3 q# h: g" s6 W/ z
a3cb95aa3c694c7f90bf8d8b85a3d321.png
# c/ x! j, Q2 f: U7 W$ k
- W- U# Z1 z" x4 t————————————————
+ {* {) b) t6 [版权声明:记帖% N- W5 g- h, X. o

) f3 h; n: n& i& i8 u1 u4 H
& b) z5 v% l& Y' n3 O1 l' `8 j/ s' ]6 G
' o2 ^9 |; f; A6 |$ _- @' D4 o5 z
赞 收藏 评论0 发布时间:2022-10-20 19:14

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版