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

【经验分享】STM32CUBEMX--SPI,W25Q128外部Flash移植

[复制链接]
STMCU小助手 发布时间:2022-4-29 23:31
概述
( g# {; S3 n0 vSPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议,比如 EEPROM,FLASH,实时时钟,AD转换器。
4 j- i6 I) o$ iW25Q128 是一款SPI接口的Flash芯片,其存储空间为 128Mbit,相当于16M字节。W25Q128可以支持 SPI 的模式 0 和模式 3,也就是 CPOL=0/CPHA=0 和CPOL=1/CPHA=1 这两种模式。
% i& [: k6 M! B4 T! `
& v9 Y$ g  r( n) C6 N( n" ?1 L硬件准备( b; W5 c# w# @9 I! ^
首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:
$ y8 V  Z: J/ R: h4 K* u6 K3 b8 f; f' H; I8 u
H0)1(DOD46`N0X`9J48V~LL.png ; y* d8 C7 V& V; L8 h6 S( I
2 t* ]+ y# }) r: }6 B9 S9 m$ ^
选择芯片型号3 |+ V) _; h3 t; E& F! u9 F
使用STM32CUBEMX选择芯片stm32f030r8,如下所示:
: f9 P+ m4 T3 u9 t$ B( n- N
! S: r6 v! ]7 z8 Y& B 20200604204408810.png 6 `! c6 e# _% I* e6 N
. _2 M- j9 l* r- C7 x5 G% O  J
配置时钟源
- C5 w; |& m: \% PHSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:
6 r: H7 f5 D" J! k8 D" B1 B
* ?' l( o9 Z- [( e 20200604204644344.png
$ s1 j  v" U# e3 Z$ A% o$ \
( V7 A* ], t% d. a# y, L, H7 E5 D1 ?配置时钟树

; t! H. @0 n8 }7 tSTM32F0的最高主频到48M,所以配置48即可:
* X5 R. A/ j+ V9 x+ Q* k% @7 Q; i! Y# L# P' S! z
20200604204550406.png / h; j" t4 c. V/ L, m6 t4 l3 T& V

5 Y' B; j4 a3 Y% e8 P# W3 @& `串口配置

' C8 t; l; Q: a. H5 R% i4 E5 J9 `本次实验使用的串口1进行串口通信,波特率配置为115200。
4 E' A- C& ?: m% @. e
8 [4 q0 `9 z! F 20210614162936131.png
- U3 N0 _3 s- Y% J1 m& r# w0 c0 ~. C+ h
开启DMA。2 v2 n2 y* E3 `. _. C6 r- c

! s# x+ p9 _: x) Q N_16%XT{@J)CZ)GTB]EIQDA.png - t5 o6 P: N' @5 K
, T. R! _) Q6 S( U' m6 T
中断。
4 X" L5 T4 A' C& Y) o2 U) Y2 N, V0 \3 T! e+ I
VBII06W}JD]NLOB}ZFO}NCU.png 7 Z& h& R9 I; ]3 p5 z6 {
9 C# Q/ P$ U) h3 _
! P- N$ v# B9 T% `; p/ C. l6 G
SPI配置; w( C( J+ r  i: n! r. Q
本次实验使用的SPI与Flash通信,配置如下。
0 o$ ~9 d) d0 R! ~9 kSPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。- m6 E6 Q; Q& R& y1 P- V! }/ i
(1)MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;
7 p4 T& {5 V7 @8 H) V% S! I9 T% a' X(2)MOSI– Master Output Slave Input,主设备数据输出,从设备数据输入;
+ E7 g. z+ l4 L(3)SCLK – Serial Clock,时钟信号,由主设备产生;' E! g2 S+ ^8 q  T4 }+ B
(4)CS – Chip Select,从设备使能信号,由主设备控制。
: ^* k9 ]3 [' m( H
. Q, L) f3 Q8 `0 t5 I# G+ k- u* R接线方式

$ a0 a7 g1 E* d- B- @: g( F3 P4 c/ X
(W7W[AN$X(90R]}GP`7_167.png , `" @2 X2 Q: i# \( m

. T# X" ]$ u  O+ e" k负责通讯的3根线了。通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCLK时钟线存在的原因,由SCLK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。因此,至少需要8次时钟信号的改变(上沿和下沿为一次),才能完成8位数据的传输。
6 {0 `" R; k; G# J时钟信号线SCLK只能由主设备控制,从设备不能控制。同样,在一个基于SPI的设备中,至少有一个主设备。这样的传输方式有一个优点,在数据位的传输过程中可以暂停,也就是时钟的周期可以为不等宽,因为时钟线由主设备控制,当没有时钟跳变时,从设备不采集或传送数据。SPI还是一个数据交换协议:因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。芯片集成的SPI串行同步时钟极性和相位可以通过寄存器配置,IO模拟的SPI串行同步时钟需要根据从设备支持的时钟极性和相位来通讯。8 n0 F7 Q" |6 D$ o, `; z$ g- H
最后,SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据。
& A; {+ ~" _0 Y) c
9 m; n4 e1 a% Z4 Q, L 20210610002146525.png
& G, h8 O  R, ^- V
0 _+ j% c' l+ [* z其中,CS是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个SPI设备成为可能。
& Y  R+ G( V1 j* e  s随便配置一个端口为CS片选,并且命名为CS。
2 f5 m% u0 ^; d7 O% Q! h/ W
+ J& S( G9 x1 L& o$ u% y) s& m: @4 V1 l 20210613153651922.png ' Z+ w' v; N: N: D( E1 X
4 ?$ Q! S9 S. a, S; s5 a5 {; P
生成工程设置
1 \7 s: P$ d. v( X注意在生产工程设置中不能出现中文,不然会报错。
- T2 R* m: m/ A4 k
+ C# M( H  _7 ^+ B' k: [ 20210610002715361.png 5 f# ^. w8 s- f) m7 @: d- n
+ N* G8 L3 S) E% }+ }
生成代码
* ^7 D2 j; r' U* ]! a' T  o* N5 ^( v! ^% z
20200604205807980.png 5 R7 ?: E( z7 l+ Q& V/ T" P

; q& j" K5 i5 i. c, N  c配置keil
  A% I* I+ I4 ~6 `
. p( ~6 g  L& Y$ V$ Z" Z* ^, W% k
20200604210002645.png   T/ I& [( ?+ L+ G6 y' H  Q
/ o2 G# [! \$ O& Z! Q9 M+ y
W25Q128的原理及应用
- Q: c# `) }8 |8 LW25Q128将16M的容量分为256个块(Block),每个块大小为64K字节,每个块又分为16个扇区(Sector),每个扇区4K个字节。W25Q128的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。1 r5 R( i8 k3 E+ ]
芯片ID如下所示。
- F, f1 t/ A6 K, h' J, L1 D7 L( g* o" v( D: d, u
0XEF13,表示芯片型号为W25Q80
! H6 C2 b* f" j/ _: E+ A( D0XEF14,表示芯片型号为W25Q169 h( r' A: f0 V! Y9 W3 U9 n) C
0XEF15,表示芯片型号为W25Q32$ ~0 v4 _% I: r$ ~
0XEF16,表示芯片型号为W25Q64' o  f3 c: v( T$ M0 l; a( S- M
0XEF17,表示芯片型号为W25Q128
* J. R& w! Y) l9 |3 r4 Y% h/ H1 n# p. p# O5 ?
驱动代码" ]& ?5 A9 c, R: O' _' Y/ @
W25Qx.c
9 _' q' c0 W7 c( `" c! W3 y
  1. /*********************************************************************************************************, Z% F( Z4 L* M. z& c2 G  ?
  2. *5 L1 z% b0 J% g6 o7 l+ |6 k
  3. * File                : ws_W25Qx.c# W- B" ]# _' s6 b2 R( K$ G9 I$ j
  4. * Hardware Environment:
    # i! J+ [$ F1 t* d8 [6 C( I7 P
  5. * Build Environment   : RealView MDK-ARM  Version: 4.20& P2 G) H3 n! g! _& i
  6. * Version             : V1.0
    2 h: u3 a( N& h: K8 y- Q
  7. * By                  :
    ; |$ @' l; s" Y+ x% A. q8 v: d0 ^
  8. *
    ' V# |( O# Y$ S
  9. *                                  (c) Copyright 2005-2011, WaveShare$ F! z+ f$ \0 f, O- C$ u; j
  10. *                                       <a href="http://www.waveshare.net" target="_blank">http://www.waveshare.net</a>
      U3 ]! L1 n5 m) w0 @: {
  11. *                                          All Rights Reserved, B9 ~+ R$ |' o1 u% ]2 o! g' y
  12. *
    " a" H9 x/ k' `* n
  13. *********************************************************************************************************/
    1 }1 e- [" ]9 _% V& z/ q
  14. # b) D$ I# k  r& D
  15. #include "W25Qx.h"% K! l0 C( A1 S: c" _  h
  16. 8 k/ q# G- ~% f1 w
  17. /**
    8 x3 W: w1 z: a$ S* f
  18.   * @brief  Initializes the W25Q128FV interface.6 g" p) d4 J- C5 \0 V4 w
  19.   * @retval None
    8 i4 x- ?( Y( W8 \' t, [5 q- x9 M( ~
  20.   */
    9 t& ^4 Z. }5 ~
  21. uint8_t BSP_W25Qx_Init(void)" ~) n, b/ ?9 D" U6 _
  22. {
    7 w+ H% h6 o4 z- Q+ M
  23.         /* Reset W25Qxxx */) [! n- H0 t$ E$ p
  24.         BSP_W25Qx_Reset();( j, l. G  M- r- [  c
  25.         + j* C& B3 x8 m2 x* p6 x% M
  26.         return BSP_W25Qx_GetStatus();
    . ^& R3 q0 T3 v4 |
  27. }
    1 c: `+ G; j" t- U* t; i' ?4 ]

  28. * D* \5 y# R0 l) J5 `2 ]
  29. /**% T  {# y0 P, ~3 i9 G5 }$ G
  30.   * @brief  This function reset the W25Qx.
    / e8 ]" r; m) C1 [6 T" q
  31.   * @retval None
    1 r6 l  t/ H8 _& q! P' v" O5 Y1 [
  32.   */
    ) _8 r; M7 E# y. M6 k  D) b
  33. static void        BSP_W25Qx_Reset(void)
    9 \4 {  N* E; h& N5 h/ g
  34. {# }" t/ M5 ~( z1 O% D5 V
  35.         uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};. Y1 B- n4 q" {9 z
  36.         . J$ Z8 A( d1 y5 R  @: i
  37.         W25Qx_Enable();/ \" Y! z" `$ {( v; ?
  38.         /* Send the reset command */
    ' t/ A3 H: p" U2 V% O/ |0 R6 y- M+ k
  39.         HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE);        & N/ Y( Z6 O4 a3 S2 M. w+ p; j
  40.         W25Qx_Disable();
    1 L# U1 q5 I- F

  41. 1 C) j1 S1 s. K+ Y
  42. }
    / g+ f+ U) i5 P

  43. 9 F+ w# ^; N- v+ x& V! v* X# H& u7 G0 H
  44. /**
    " E1 Z( A2 c9 ?! f3 e* C
  45.   * @brief  Reads current status of the W25Q128FV.1 O% @, E* Z, s$ ?6 |8 `
  46.   * @retval W25Q128FV memory status( [5 w% `" M9 r" P9 T& h
  47.   */9 v; f9 c* E: o
  48. static uint8_t BSP_W25Qx_GetStatus(void)
    ; s7 J, t; k" `& B
  49. {
    7 s7 P& l* f- v( A
  50.         uint8_t cmd[] = {READ_STATUS_REG1_CMD};
    + T9 T4 M& U3 ~/ t  W
  51.         uint8_t status;
    2 \8 [2 V6 ~' R7 \8 ^
  52.         
    . O) e5 o: z$ ]6 t+ ~) b! ]! H0 v
  53.         W25Qx_Enable();- D( _6 n6 f1 V; Q% \
  54.         /* Send the read status command */
    6 e7 |2 ^+ |9 c3 L- b: f
  55.         HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);        , ?6 `& E$ `' x) |; E2 w' D$ R. ?
  56.         /* Reception of the data */
    ( I$ M6 D) F! f$ {* @
  57.         HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE);
    $ R- o/ e: f7 C
  58.         W25Qx_Disable();
    ; ~1 Y1 A3 P* M! j
  59.         # a4 T% d3 J5 B6 _; ~/ Q/ L/ M
  60.         /* Check the value of the register */) @' [; V# i1 J9 E
  61.   if((status & W25Q128FV_FSR_BUSY) != 0)8 V$ |) }1 G+ K
  62.   {
      C% e8 b" X$ r& v& `% p5 R
  63.     return W25Qx_BUSY;
    3 w5 D# n$ F& m* w  }
  64.   }0 j$ @5 V5 R2 u, f8 w4 I/ b1 W
  65.         else$ Q) M4 I" S( }/ b6 V
  66.         {
    3 l5 i8 A/ E) {" O2 z' J9 G* t
  67.                 return W25Qx_OK;
    6 y+ C( p- Q) Y9 J. K/ l% f
  68.         }                7 H9 o/ Z1 X2 ?# Q# e
  69. }
    1 _) I. J" {( Y3 Z9 }
  70. ! M- x# ~  i8 W4 T
  71. /**# o# P; X; e- Y) m# G. j
  72.   * @brief  This function send a Write Enable and wait it is effective.
      k) ]  S& @  m; H7 b. C
  73.   * @retval None9 K2 t4 `& ?5 @( a2 u  J* r
  74.   */
    * d3 ]$ \" u$ S& f2 w7 s! {
  75. uint8_t BSP_W25Qx_WriteEnable(void)6 y& w/ M9 U- [
  76. {$ ~9 J/ G- B, G
  77.         uint8_t cmd[] = {WRITE_ENABLE_CMD};' s% g' V) }* B/ G. g$ B: e
  78.         uint32_t tickstart = HAL_GetTick();5 T( c6 p; C3 _) ]4 ~! J# v

  79. 6 l# F4 M' Q# ]- ]+ P: `
  80.         /*Select the FLASH: Chip Select low */
    2 `& @1 E0 S8 l5 U
  81.         W25Qx_Enable();+ j  _; c& n+ Y
  82.         /* Send the read ID command */5 l) m, L1 `6 R% g/ O: Q# B
  83.         HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);        
    1 t5 T* |& F, ~$ X4 \
  84.         /*Deselect the FLASH: Chip Select high */
    3 z5 q- Z- @7 \8 y
  85.         W25Qx_Disable();
    7 z+ O$ \2 x% h9 r8 D8 q6 y
  86.         
    ' ^" T" S, O  N9 m7 B  `
  87.         /* Wait the end of Flash writing */
    $ H6 f3 z- j: ?/ A
  88.         while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
    ) B7 n' G" t4 c7 y! i* e7 \; m
  89.         {- S! C$ r- ?4 h& {% A
  90.                 /* Check for the Timeout */
    0 @) e, ]- U6 k9 A3 K+ V
  91.     if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)
    - h$ F/ ~+ ?, Y; l" Y7 k  U! \
  92.     {        ! I: t0 [9 n- t6 p
  93.                         return W25Qx_TIMEOUT;% Q- b0 {, P" ?( D, [5 n% b
  94.     }5 x- B6 z/ S1 [
  95.         }
    $ O& W) z$ P9 ^! U, Z8 e8 k$ W
  96.         
    * v! K* ?. h( w( x' ^$ _" \% y* Q
  97.         return W25Qx_OK;
    & d$ l$ a: d3 k& U
  98. }3 g* I1 Z: e5 d9 y$ B

  99. 6 h, l( E4 v, y$ V3 d7 y8 r4 X
  100. /**
    + w' K- @% i: S5 g
  101.   * @brief  Read Manufacture/Device ID.6 V% s: }# f) J$ l8 g/ K
  102.         * @param  return value address
      K1 N5 f4 p+ q
  103.   * @retval None$ I7 F7 n7 c: p& K! P
  104.   */
    6 G  j$ n, ^, l5 {+ \, \
  105. void BSP_W25Qx_Read_ID(uint8_t *ID)
    ) j1 O# s* U# f
  106. {+ m* m! f. J: W: H& s  A: ~
  107.         uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};
    8 W! m5 l$ ]& K8 |- s
  108.         * M; M8 z1 R/ k( D7 |
  109.         W25Qx_Enable();2 f% u! Z5 F0 I" I) {4 U( G' @8 [
  110.         /* Send the read ID command */+ V3 m5 z/ [4 `6 r8 k
  111.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        
    + _' ]5 ^- g, {5 }$ f% d! \1 {1 R
  112.         /* Reception of the data */
    ; `( W& T% E! j* k
  113.         HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE);
    $ v1 q# `, s1 Y' ~' ?5 T
  114.         W25Qx_Disable();
    , t& J; c2 ?" c4 j# {- Y
  115.                
    5 N; @) {5 ?/ ?; H7 Z
  116. }
    2 |9 D0 \" U8 w1 F6 `1 P
  117. $ b# e  P* T$ x2 R' ^8 T2 x
  118. /**3 i% X3 O! n- \$ J; S- N
  119.   * @brief  Reads an amount of data from the QSPI memory.
    . i- i, X" I/ ]# J1 \, W6 I! G) H
  120.   * @param  pData: Pointer to data to be read+ h" Z1 q" D% g# p
  121.   * @param  ReadAddr: Read start address
    7 |+ c9 u3 L3 J1 ~* e
  122.   * @param  Size: Size of data to read   
    3 \2 B6 W8 R' I0 `  R
  123.   * @retval QSPI memory status
    3 Y: w2 i9 v$ t8 R" d  ^
  124.   */: y% x2 L& f: R4 S0 b
  125. uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)3 P, t. L' O9 A8 S2 h. _+ U) O
  126. {
    , v9 p/ m  U" y' V: k
  127.         uint8_t cmd[4];, p5 K  R) h& d6 b

  128. 0 }0 P7 x! @. j1 a" Z- u3 X: ?
  129.         /* Configure the command */
    4 d: n4 H6 O: _# H1 i6 I/ Z
  130.         cmd[0] = READ_CMD;
    % `! a1 B+ e1 |  L' V. Q( ^
  131.         cmd[1] = (uint8_t)(ReadAddr >> 16);
    ( ?- y* A7 Y5 W) a" w3 p
  132.         cmd[2] = (uint8_t)(ReadAddr >> 8);
    8 k, Q* n1 G6 q; ?  b# Q& Z  h
  133.         cmd[3] = (uint8_t)(ReadAddr);
    + G" M% m7 T- k' J! F. Z( ?
  134.         # v) [: l: ^* n5 O6 p0 c
  135.         W25Qx_Enable();& i; o* G9 k( p  x* H
  136.         /* Send the read ID command */; G0 a$ Z; v' S* \/ O& j: n1 m; ?3 I
  137.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        
    9 Q% ?: k( {! `8 k* V
  138.         /* Reception of the data */
    # F+ x/ ~* ]3 z* o) O) i+ Q
  139.         if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)
    9 n0 f' b; i, ]3 N
  140.   {# W6 Y. f- B$ g+ [# Z- l
  141.     return W25Qx_ERROR;
    ) J* c) Y9 g  `: L$ _, P
  142.   }- [1 J9 m6 P, S- L9 v& ]
  143.         W25Qx_Disable();
    - R1 i: Y. M& X5 |1 }0 ^
  144.         return W25Qx_OK;9 Z8 [( N7 y- V& r5 y6 m  r* u
  145. }  _' L- F2 R) R7 E' L+ k. C( b
  146. 5 w# ^  n8 \1 T& M
  147. /**
    ( n1 h! o3 j. O1 O
  148.   * @brief  Writes an amount of data to the QSPI memory.4 ]: |9 J) a7 c  s  |, C
  149.   * @param  pData: Pointer to data to be written
    & ~  n' N& N) e" @
  150.   * @param  WriteAddr: Write start address
    5 u; k, z" B5 L
  151.   * @param  Size: Size of data to write,No more than 256byte.   
    / v8 b- x6 d+ z& ^) B9 i
  152.   * @retval QSPI memory status" k, o5 c9 U1 x+ k
  153.   */
    . ^0 O- y; ]) B0 k2 Y
  154. uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size): S' u( t( L2 u5 h" T' ^
  155. {) n- n9 J! n: h$ t" ~7 F, N/ E: G
  156.         uint8_t cmd[4];
    & ]) Y! s0 e, G8 e1 F
  157.         uint32_t end_addr, current_size, current_addr;3 w/ p  b7 e/ I) Y
  158.         uint32_t tickstart = HAL_GetTick();
    0 m0 N8 H. Q7 i
  159.         % {4 N3 ^" x6 i( Q$ l, Q
  160.         /* Calculation of the size between the write address and the end of the page */9 v3 I: J- `9 B2 _) c. ]  q0 _
  161.   current_addr = 0;& i- \6 d& Y% y2 G% i+ \
  162. + c& n" Y4 c* ^
  163.   while (current_addr <= WriteAddr)" B# D: ^+ }8 {! O
  164.   {/ ]4 w) j$ E3 t/ a. H% e
  165.     current_addr += W25Q128FV_PAGE_SIZE;
    / c' L  P% n) E+ ?( n
  166.   }6 M4 ?& E  y; R& i* s" K  \; [
  167.   current_size = current_addr - WriteAddr;& ~9 \& o. z% y9 g

  168. : f+ P, X4 W3 ?4 p/ L2 Z
  169.   /* Check if the size of the data is less than the remaining place in the page */
    4 [4 ?1 a) E% O: h0 h2 {
  170.   if (current_size > Size)2 D) b& X. c: V0 o
  171.   {
    % J' `% ]4 b+ Y" n
  172.     current_size = Size;+ ~1 O! y# l5 k$ r( C1 b  x, r" y8 i
  173.   }2 X, v4 P4 e, |! T1 t2 Z

  174.   C3 m5 k( m9 K9 f
  175.   /* Initialize the adress variables */7 J2 j# W$ ^* v1 y4 H  n
  176.   current_addr = WriteAddr;
    & ?" g9 T/ O! ]
  177.   end_addr = WriteAddr + Size;1 T: }  W1 F) {- D2 r9 R, j- `: v4 X; H
  178.         % T/ U$ l$ L6 V4 J2 g
  179.   /* Perform the write page by page */
    2 J& I+ C; n9 g! _" [
  180.   do
    % C2 |! d1 L$ L, a% D/ l
  181.   {
    2 @7 W) `% }/ x6 J0 s7 j8 s
  182.                 /* Configure the command */: n3 T9 R$ E9 {
  183.                 cmd[0] = PAGE_PROG_CMD;
    4 {. C2 f, @- w0 A, Y& S
  184.                 cmd[1] = (uint8_t)(current_addr >> 16);$ J0 s& W# r; y  k1 r
  185.                 cmd[2] = (uint8_t)(current_addr >> 8);( w% E+ R" H1 v
  186.                 cmd[3] = (uint8_t)(current_addr);
    * I& w+ Z8 g" M! Z; _* V# D. V

  187. 9 K% N0 T' ]* K: g' d" h7 \
  188.                 /* Enable write operations */
    ' K; M3 j2 w2 Y0 @# j( U1 |5 L
  189.                 BSP_W25Qx_WriteEnable();. L8 [  n. d( l, u# t( [6 q9 N
  190.         ; y& V1 A- D8 Q, A7 I
  191.                 W25Qx_Enable();
    6 @" T1 i. W" \1 C# h- f8 N& S  h- {6 U
  192.     /* Send the command */
    0 t, c% m2 J3 j2 h' M3 i- \
  193.     if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK)
    ) t0 Q% I& {, o, ^
  194.     {
    , F! _; _4 N3 c! n" m
  195.       return W25Qx_ERROR;& I3 x/ i- Y  v+ i( v! R4 F# A
  196.     }
    2 _" }; H4 {3 I* p
  197. % R1 G6 S5 Z* D( S" V
  198.     /* Transmission of the data */- I2 y5 Y! F, Z- B& y
  199.     if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)
    & t3 t5 Y7 y- n2 K3 f
  200.     {7 ^3 `' q$ ^/ H3 G% t# w
  201.       return W25Qx_ERROR;
    3 g5 s3 {1 P1 O+ D4 t$ b/ y
  202.     }! h! i+ ~% {$ b8 U9 K! h* \2 o$ `) d
  203.                         W25Qx_Disable();# ^  _/ b$ u0 e% s2 o9 n! b- K7 y
  204.             /* Wait the end of Flash writing */
    , t/ M; w0 ^3 H- ]. a) {
  205.                 while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
    + A% a, Q- n! Z* E; A6 {' ?( G" a
  206.                 {
    5 j  `6 Q$ C7 @  r; @9 q/ W
  207.                         /* Check for the Timeout */
    : u, C, a! N. [. p# Z' r
  208.                         if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)
    ; I% y7 V4 [( c2 p0 n2 f
  209.                         {        " v  S" J; ~) {) u$ j/ C
  210.                                 return W25Qx_TIMEOUT;& r6 c6 G6 S5 i3 m& c4 Z
  211.                         }+ \; O6 e) `8 Z6 a$ ~  {1 {. Y
  212.                 }
    ; Y4 f6 G2 o1 D6 w0 c1 f3 M

  213. - {% A" ~( \* k2 d5 M
  214.     /* Update the address and size variables for next page programming */
    0 t8 J6 s8 _2 X& t1 S
  215.     current_addr += current_size;; K0 ]. d7 s( G2 f: J2 N! y3 a0 h" u
  216.     pData += current_size;  c) O2 r+ E! r
  217.     current_size = ((current_addr + W25Q128FV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128FV_PAGE_SIZE;! d- O! |8 _; D
  218.   } while (current_addr < end_addr);
    . W% F6 _% u8 j' z2 R
  219. 9 _1 v0 l7 f- A( ?" j: Q) Q
  220.         
    ) l9 j2 M; `% i/ N5 D$ D
  221.         return W25Qx_OK;
    $ v9 |+ x& j% J3 N$ ]
  222. }
    ; L) d7 K' l6 v# w4 A4 e
  223. ' l. ]& F1 k5 |5 \* G
  224. /**
    ' K* ]8 o6 s7 p" E6 ]6 ?
  225.   * @brief  Erases the specified block of the QSPI memory. ; }! g' I1 Z7 a& m8 w& i0 ~8 _
  226.   * @param  BlockAddress: Block address to erase  
    9 C0 ~, `) k' H
  227.   * @retval QSPI memory status! c7 Z4 W5 \3 |' c# ?- o8 o% j
  228.   */
    0 C; _4 v/ D3 _3 k- v2 f
  229. uint8_t BSP_W25Qx_Erase_Block(uint32_t Address)
    : t7 _3 W$ `2 ~' Q* w
  230. {3 F1 g  [# L2 k
  231.         uint8_t cmd[4];3 A2 X7 N$ p( D5 U( E
  232.         uint32_t tickstart = HAL_GetTick();
    / ~( [$ V, T; W. h
  233.         cmd[0] = SECTOR_ERASE_CMD;
    ' u! H- h: J0 i/ T
  234.         cmd[1] = (uint8_t)(Address >> 16);
    8 w* G- s3 u5 F
  235.         cmd[2] = (uint8_t)(Address >> 8);
    1 K* A( ^! ?" K! A7 C! d
  236.         cmd[3] = (uint8_t)(Address);: H3 I) l2 N- r" }4 A
  237.         ) p+ q% v4 G2 J$ a" L) b
  238.         /* Enable write operations */! w) A. p6 g5 Q4 [; Q/ L
  239.         BSP_W25Qx_WriteEnable();5 o& _  s( D+ d5 S# R) A
  240.         
    , V& z$ v1 q% Y, P% U- |+ @
  241.         /*Select the FLASH: Chip Select low */" S9 {/ g0 O8 C5 G5 c; x. v+ u
  242.         W25Qx_Enable();
    ) k1 H% T7 i. S; M  Y  e: h
  243.         /* Send the read ID command */
    / ~0 H. s& k, ^; H" }
  244.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        
    & y/ W6 N% v$ z# R% C' @+ w
  245.         /*Deselect the FLASH: Chip Select high */
      G% D1 j3 e( K/ n: ?1 N" {
  246.         W25Qx_Disable();
    ; l4 _* [2 w( Q1 r. o; Y- G
  247.         ; B* B; W0 }: {4 E8 I' w* Y6 b
  248.         /* Wait the end of Flash writing */0 [( F+ R" J& V/ w- c
  249.         while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);" K. n: t4 H9 B
  250.         {
    - l! E3 _+ v1 H* {
  251.                 /* Check for the Timeout */' B0 Y7 l! P2 `% p3 S2 Y$ v" Z+ m
  252.     if((HAL_GetTick() - tickstart) > W25Q128FV_SECTOR_ERASE_MAX_TIME)
    2 ?8 a) l( T' e2 F/ t1 l
  253.     {        + p" v, Z/ d0 ?; l" R
  254.                         return W25Qx_TIMEOUT;" a9 _6 @7 e( z
  255.     }
    ) B5 N) H9 _; y. n. L8 u  _5 d, O
  256.         }2 V# A8 o+ D' Z' d# E& P/ O
  257.         return W25Qx_OK;
    ! J# Q. a0 @4 S) m8 w% P0 n( V
  258. }5 O. R) m/ G# t7 T+ \6 G

  259. 1 d" H$ a) Q- c3 V" S) B, R% V
  260. /**& B9 F1 g3 i+ w+ h5 }" D: k8 G, G
  261.   * @brief  Erases the entire QSPI memory.This function will take a very long time.
    8 s  y# f' f+ @1 F, i3 n
  262.   * @retval QSPI memory status
    ! v0 ^6 J0 Z2 D/ E/ l
  263.   */% W4 z3 x. _) j7 U' ~, o' j$ ^1 f" r
  264. uint8_t BSP_W25Qx_Erase_Chip(void)
    3 F9 [6 `8 f4 R9 s5 T) F( x
  265. {# ]; \6 [7 B' t2 k0 t" d
  266.         uint8_t cmd[4];
    ) e* \7 D9 G) o5 B
  267.         uint32_t tickstart = HAL_GetTick();
    7 c9 K4 S5 G' u6 _; h! K" [& y
  268.         cmd[0] = SECTOR_ERASE_CMD;
    ( C: g8 ~9 {8 P6 _" r8 b  b
  269.         / u/ \9 i- H+ b8 l0 H: o0 p
  270.         /* Enable write operations */
    ( r( x' z" y% b; X+ y7 ~5 Z
  271.         BSP_W25Qx_WriteEnable();* b/ c+ [- r/ d9 c7 i: D# c
  272.         7 Z1 a% h& [. ^6 G2 g3 J
  273.         /*Select the FLASH: Chip Select low */6 |' p; C& |! x" ?& q
  274.         W25Qx_Enable();- |1 Q: ~7 y: b& n% B) y
  275.         /* Send the read ID command */
    3 U7 E- w' r6 Q! B9 \0 m$ \
  276.         HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);        
      a; A- i$ H1 g+ M# o& [
  277.         /*Deselect the FLASH: Chip Select high */6 `/ F9 Y' o6 M
  278.         W25Qx_Disable();
    ' T3 B* ]' t# v. F+ ]. s
  279.         
    ) ~% I# `1 Y" }+ T
  280.         /* Wait the end of Flash writing */
    9 K+ G, j+ G) y* h  w
  281.         while(BSP_W25Qx_GetStatus() != W25Qx_BUSY);) Q% _& G. d2 C1 C. Y4 U. {
  282.         {
    ) f5 `* I1 ?1 L7 ~$ w
  283.                 /* Check for the Timeout */
    . o0 `7 R; ~; Y: `* O( @9 t
  284.     if((HAL_GetTick() - tickstart) > W25Q128FV_BULK_ERASE_MAX_TIME)
    4 r, ?- n( ~1 R
  285.     {        ( [* C. y# d  w. _. u: u) Z
  286.                         return W25Qx_TIMEOUT;
    ( G; E# l, F- n1 ]4 M
  287.     }
    6 H$ n- M; X: Q" e
  288.         }
    2 a) o4 Q& b) }
  289.         return W25Qx_OK;
    . j) b! C) o2 y( Y6 N. {; u/ h
  290. }
复制代码
* u  F% v. C# J" s2 W
W25Qx.h% I# ]: k3 |0 o' ?
  1. /*********************************************************************************************************! _; S/ I7 {  ^( j
  2. *4 ^+ j% k) s# L5 `4 M4 ?
  3. * File                : W25Qx.h4 v$ i; f7 i/ s) z, a" S0 i) c8 n/ `
  4. * Hardware Environment:
    2 n0 ]% F9 f. I3 t4 f3 O2 l1 I
  5. * Build Environment   : RealView MDK-ARM  Version: 5.15
      ]4 h, r1 H% C% z8 o+ _# M0 l+ {
  6. * Version             : V1.0
    ! V0 R3 R1 r. r3 \, [7 ?$ b7 H
  7. * By                  :
    3 g4 i0 e7 `; o5 b% {, B! F
  8. *% Q% b. s, }( Y; }" r
  9. *                                  (c) Copyright 2005-2015, WaveShare1 V, v! k( c0 Q% J+ S
  10. *                                       <a href="http://www.waveshare.net" target="_blank">http://www.waveshare.net</a>% Y# c+ L/ M! ^2 T) I& _* T6 n* M
  11. *                                          All Rights Reserved, g0 ^' ?* U, Q) N( s* F1 X9 p
  12. *
    3 `  ~" t- x3 Z, L" p! T
  13. *********************************************************************************************************/3 y2 W: T1 R8 K# c/ i
  14. /* Define to prevent recursive inclusion -------------------------------------*/+ D* ^$ J1 j( X
  15. #ifndef __W25Qx_H
    5 M  q. ?8 R* b0 e. q- k( R$ G
  16. #define __W25Qx_H9 o9 q3 |- M9 O

  17. 6 _) I+ m; P1 a/ k/ X( S- U" ?
  18. #ifdef __cplusplus1 W' d! x* ^3 ~3 Y: ]
  19. extern "C" {) ^+ u5 N, ~) M$ Q- |3 {
  20. #endif
    $ l3 A' s* h6 b! K& J

  21. 7 u$ ]# F3 Y6 H1 K, u  U( a
  22. /* Includes ------------------------------------------------------------------*/7 n; ?8 l  R7 K' X6 \) T
  23. #include "stm32f0xx.h"
    / z. z+ p/ M; r" [
  24. #include "spi.h"4 J1 m, }* @+ p& c. L% F$ A; E
  25.          
    3 `6 r! Y/ x; z! }
  26. /** @addtogroup BSP6 o% t/ J; J+ y
  27.   * @{$ ~$ n- X9 l, K
  28.   */
    4 g  v+ Q( F9 k" H, N

  29. * u) [" o( |- }+ k' ^* l* |& F
  30. /** @addtogroup Components0 }7 q& _- Q0 }8 m
  31.   * @{
    , A! w4 U+ @1 B& X' A
  32.   */ ( l5 N. X! M& A$ w+ g8 q
  33. 8 Y5 T. Z" z  _2 C0 x/ g
  34. /** @addtogroup W25Q128FV+ L; h" \; b! g4 \0 y& b5 i' {
  35.   * @{
    " u& S6 F  N# B* ?+ j
  36.   */
    " V* D7 o, t/ Q* V

  37. - [3 L9 w# R' \4 N9 M
  38. /** @defgroup W25Q128FV_Exported_Types$ Q1 d, `* `# J& V9 k7 y0 E: _
  39.   * @{
    : l+ N" s0 F8 j9 l# d0 R
  40.   */: e- i/ b2 N$ M
  41. 3 N. y1 l% ?/ k( M$ S6 v
  42. /**  i+ n! y# y' e
  43.   * @}% _9 _" s) E  ~3 b2 z
  44.   */ " R- t/ f- G" }' X2 S. _
  45. ; ^, u1 j2 q; n2 y- N8 K
  46. /** @defgroup W25Q128FV_Exported_Constants
    # r; D0 z' N/ i9 F
  47.   * @{
    3 ^9 ~. p8 c$ k; W, O
  48.   */! ^! x9 [  A  ^' E* m- w
  49.   e' M4 E+ v. b/ u0 d2 C+ {  `
  50. /**
    " I1 }5 y% y! E5 A2 L- i
  51.   * @brief  W25Q128FV Configuration  5 L7 Q' ~0 g1 k: y1 O6 R
  52.   */  
    8 \' s: Q; f5 h( u: `* I6 E
  53. #define W25Q128FV_FLASH_SIZE                  0x1000000 /* 128 MBits => 16MBytes */
    ( Z$ t- V; l  {4 l1 f6 |, E( m5 w3 h
  54. #define W25Q128FV_SECTOR_SIZE                 0x10000   /* 256 sectors of 64KBytes */
      Z% d8 s  e. h5 y' h
  55. #define W25Q128FV_SUBSECTOR_SIZE              0x1000    /* 4096 subsectors of 4kBytes */9 J: t' t* y) F, s' E1 {
  56. #define W25Q128FV_PAGE_SIZE                   0x100     /* 65536 pages of 256 bytes */) D( W+ a; }6 D; l

  57. 3 w" P! i$ @1 X2 u! a0 N. B; G3 G; W
  58. #define W25Q128FV_DUMMY_CYCLES_READ           4
    % W* Q3 L% g+ Q* v
  59. #define W25Q128FV_DUMMY_CYCLES_READ_QUAD      10
    . G2 R# F/ b  s5 J2 c4 y
  60. . G8 F8 b+ K7 b6 h
  61. #define W25Q128FV_BULK_ERASE_MAX_TIME         250000
    - X3 l6 X, V* x
  62. #define W25Q128FV_SECTOR_ERASE_MAX_TIME       30000 ?; g% v2 z5 i' ]  Q# r
  63. #define W25Q128FV_SUBSECTOR_ERASE_MAX_TIME    800- O2 a4 y* k7 ^9 ?2 v# u0 N6 I
  64. #define W25Qx_TIMEOUT_VALUE 1000
    7 h* w: _* o9 y2 _

  65. 0 E2 i* N) _9 u5 f$ ?* Z
  66. /**   Y! P6 q! f  l1 B, ]; W5 w6 R/ c5 L
  67.   * @brief  W25Q128FV Commands  
    % W* b$ {5 X/ s0 M6 S9 B
  68.   */  
    % K8 L- [1 [. T+ h+ X2 A3 [
  69. /* Reset Operations */& k- h% A+ X8 O! B2 ?! F
  70. #define RESET_ENABLE_CMD                     0x66
    - ~3 z: Y/ p8 ]6 {: G
  71. #define RESET_MEMORY_CMD                     0x99* e9 H- w/ P' {
  72. % K" T6 r; f" ~( d" y+ F/ R# G$ D) t) J* Y
  73. #define ENTER_QPI_MODE_CMD                   0x38
    9 N3 Y# p: A7 A+ u" g* k
  74. #define EXIT_QPI_MODE_CMD                    0xFF
    . i/ ^- Y6 J. J5 n5 t' s5 C2 o
  75. + B. A3 l. G8 s, E/ D+ y& i
  76. /* Identification Operations */
    8 f& l$ `: E* w1 Z! I+ t5 ]3 y
  77. #define READ_ID_CMD                          0x90
    8 {  }& y1 t9 k  Y/ u* |3 I& x, [
  78. #define DUAL_READ_ID_CMD                     0x92& I$ S% |1 w% Z6 E% |  W
  79. #define QUAD_READ_ID_CMD                     0x94
    2 Y* S$ ]8 b) `/ _: n1 \
  80. #define READ_JEDEC_ID_CMD                    0x9F
    " H0 M( }: \- R8 T8 v

  81. 4 E$ u+ I6 @" e* k
  82. /* Read Operations */
    2 f( k1 I" H# U
  83. #define READ_CMD                             0x037 |! D+ B' I5 n+ J) Y: C' y/ T) s
  84. #define FAST_READ_CMD                        0x0B: @9 l& a9 ?2 G4 j
  85. #define DUAL_OUT_FAST_READ_CMD               0x3B& q6 ?. h  g, F% F+ L
  86. #define DUAL_INOUT_FAST_READ_CMD             0xBB
    / q0 t  h$ G9 F$ V; L1 K) ~. `9 ?
  87. #define QUAD_OUT_FAST_READ_CMD               0x6B
    ( x1 v6 z) d  M
  88. #define QUAD_INOUT_FAST_READ_CMD             0xEB
    , ?; x! K- s+ x% @$ _9 `

  89. ' I& ~9 E; L5 _( `3 s2 H
  90. /* Write Operations */! v% O8 x: V4 D6 @/ j
  91. #define WRITE_ENABLE_CMD                     0x06
    9 y/ F9 W+ R1 Q
  92. #define WRITE_DISABLE_CMD                    0x048 i5 I+ [- u" X8 `2 U1 d9 F* r
  93. 1 D3 ]/ t" b3 |5 y9 L) l& ^* `: i
  94. /* Register Operations */5 P8 z9 ?: ^5 o5 a6 y& R- f1 o2 y0 A
  95. #define READ_STATUS_REG1_CMD                  0x05, ~% N& q( q5 k5 G
  96. #define READ_STATUS_REG2_CMD                  0x35
    % Q) e# d4 k+ b; n4 R9 o
  97. #define READ_STATUS_REG3_CMD                  0x15
    ( L8 _; `/ `" u  A
  98. 6 f, Y# i2 D; @: F+ k' l) P
  99. #define WRITE_STATUS_REG1_CMD                 0x01
    ! D! w& I# u1 F5 P! ~) I
  100. #define WRITE_STATUS_REG2_CMD                 0x31
    8 s( a! U4 K; t& v
  101. #define WRITE_STATUS_REG3_CMD                 0x11- y  F5 m& y9 [4 j. D0 n
  102. 7 E! Q. d/ [/ B; y; U! E

  103. , C7 o( d4 ?; g1 M
  104. /* Program Operations */
    1 O( ^0 h% K1 D( F
  105. #define PAGE_PROG_CMD                        0x02
    2 A: B/ Y9 b8 Z  v: U7 I+ G0 T
  106. #define QUAD_INPUT_PAGE_PROG_CMD             0x32
    % b; c/ f, q% U5 N* Z$ _! X
  107. 3 ]8 ]1 e# x/ k+ I: @
  108. # T: o# q% Z. i! _- X( k  b4 D4 w
  109. /* Erase Operations */7 u, v# y8 W- [
  110. #define SECTOR_ERASE_CMD                     0x20
    8 U6 Q1 L2 u) C3 Z# ~
  111. #define CHIP_ERASE_CMD                       0xC7
    ( }1 B/ O% O, A( Y3 g4 a

  112. / I: ~7 r1 z- t) z' M6 c# t
  113. #define PROG_ERASE_RESUME_CMD                0x7A9 [% ?0 |" i. \% A
  114. #define PROG_ERASE_SUSPEND_CMD               0x75
    4 |# |- q: a7 j

  115. 0 R& e) A6 x" E

  116. 7 Z( W2 d+ u- X7 c5 N; R  _7 s
  117. /* Flag Status Register */* P7 e1 S' S6 u1 |! s9 C' @
  118. #define W25Q128FV_FSR_BUSY                    ((uint8_t)0x01)    /*!< busy */  y7 T2 _- |4 q  p9 I
  119. #define W25Q128FV_FSR_WREN                    ((uint8_t)0x02)    /*!< write enable */
    # O1 n8 {% E' W: B: k
  120. #define W25Q128FV_FSR_QE                      ((uint8_t)0x02)    /*!< quad enable */+ i2 F0 h% W7 d6 Y

  121. & I; q3 r% z1 ]$ H( C
  122. $ T1 m) c+ d. N' N
  123. #define W25Qx_Enable()                         HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET)
    , l6 r6 x3 J( y: w. Q
  124. #define W25Qx_Disable()                 HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET)
    , m# \  t, r# j

  125. # F. j% |* {0 F: o7 h& R6 `% O' P
  126. #define W25Qx_OK            ((uint8_t)0x00): s! C$ q3 T- w& i; j6 y0 z* j
  127. #define W25Qx_ERROR         ((uint8_t)0x01)
    0 u( C! q; R5 W
  128. #define W25Qx_BUSY          ((uint8_t)0x02)
    ' s+ n' W. }' G, _
  129. #define W25Qx_TIMEOUT                                ((uint8_t)0x03)& f6 w' _  O) n) u

  130. ; P, D# U1 L) O5 e, ]
  131. * H& E, }7 ?: E
  132. uint8_t BSP_W25Qx_Init(void);
    $ \2 ?: h4 T3 s, _  [; }5 O
  133. static void        BSP_W25Qx_Reset(void);
    7 t1 u  ~! o. L# ~/ \, g1 Q7 a
  134. static uint8_t BSP_W25Qx_GetStatus(void);
    0 u* f: E% E0 G3 r; L
  135. uint8_t BSP_W25Qx_WriteEnable(void);6 b) q& a3 S/ ]3 u5 f/ w( I
  136. void BSP_W25Qx_Read_ID(uint8_t *ID);) u: T9 J5 J8 s2 H; w% R/ p% X
  137. uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size);# N+ A2 r& ?# [
  138. uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);& Z7 h1 z# x1 i1 F0 d9 W* ~$ f
  139. uint8_t BSP_W25Qx_Erase_Block(uint32_t Address);
    ; D: l7 z8 e3 i2 ^" a
  140. uint8_t BSP_W25Qx_Erase_Chip(void);' i  L9 I8 w6 n. q

  141. 4 n% G% v- r! z: Q4 k4 M
  142. /**& R2 N) N* L4 `% o
  143.   * @}( A* P: }3 \9 S. e) c5 O4 F
  144.   */( W- V0 |' f5 O! m4 C4 h! Y
  145. 6 h- n4 {8 l+ Y) `
  146. /** @defgroup W25Q128FV_Exported_Functions6 O" _0 O: f/ L
  147.   * @{2 h$ {% v/ \0 Y# Q
  148.   */ ; S  P7 J- ~% |' M/ @7 u/ E% a
  149. /**
    5 d/ X* A' I4 L1 m; `# n
  150.   * @}
    ( V$ J5 A. }9 V! o/ `; n
  151.   */
    ; l' O0 O+ N- R$ j
  152. 1 m8 ~: G8 I4 Q
  153. /**
    ; d! p: S1 ]# U1 Y
  154.   * @}+ d, k9 _# B, W$ d# w# F/ X$ p
  155.   */ 3 O, X% q! F  P* c' t# i6 N2 T
  156.   E, r1 N0 \+ y4 ?0 I
  157. /**/ {' v( i% X" Z$ P+ I& K
  158.   * @}
    4 F4 l# y$ }4 g) K& Z' N
  159.   */
    3 ?+ j- }# Q, T
  160. 6 W! z4 C- G3 ~& B
  161. /**9 V/ N1 e- B; x* x% O% P9 ?
  162.   * @}1 _# n7 k( a3 [, V* U
  163.   */& i# I4 l. n* i$ H0 }! x0 p* W/ S" Y
  164. " i$ w+ v/ S" f# D
  165. #ifdef __cplusplus# E: a( R8 ]. g, y; X, D- n
  166. }5 k/ M) \6 H5 S, o* d
  167. #endif$ |1 _% ?# N: F! T8 Z) _! P% D

  168. ; y& S6 G4 X, S( E3 M* z
  169. #endif /* __W25Qx_H */
复制代码

& n9 i* L" E# ^! h6 I4 k$ p写好的W25Qx.c放入Src文件夹内,W25Qx.h放入Inc文件夹内,之后需要在keil中加入这2个文件。
* X9 P$ ~* w9 Y. I
7 Y& b% e1 q4 Z2 L$ p 20210614164044135.png
( A6 ]7 w, i" v9 p4 O" L# I) c  X- B$ K4 n2 x5 K# Q; F' L
代码

8 z" J. j5 z. ~本例程向1,2,3扇区中写入数据,并且读取出来,例程代码如下。
1 |  z  L' s; f) h* |头文件定义。
  1. /* USER CODE BEGIN Includes */
    5 T7 \* e9 g7 g; @* T
  2. #include "stdio.h"
    / u9 @- @6 c" ^0 a) e4 R

  3. 1 ?! }& C1 T6 [7 a  F6 f
  4. #include <string.h>
    ) X* V. H: m7 B& |
  5. #include "W25Qx.h"- i- y' d( d# {. ?: W3 E
  6. /* USER CODE END Includes */
复制代码

8 m+ B+ F- o  L5 b  h- _' F" E/ Y串口接收和flash数组定义。
" t0 L- z# N# c" B1 i$ ~. F2 o0 z+ W+ m9 V- F5 m4 P/ N8 y& ~; Q
  1. /* USER CODE BEGIN PV */
    3 Z: X) Q& L5 b. M9 Q
  2. #define BUFFERSIZE 255           //可以接收的最大字符个数       : l- n- G8 y8 n! P( D2 r# c/ I
  3. uint8_t ReceiveBuff[BUFFERSIZE]; //接收缓冲区) x! p) c1 O# H" \) T3 V' |
  4. uint8_t recv_end_flag = 0,Rx_len;//接收完成中断标志,接收到字符长度) q% y6 j/ e) \1 z; l

  5. & k9 b4 @! ~7 I6 g+ @
  6. uint8_t wData1[0x200];3 L, a: F; h4 D( K6 ]
  7. uint8_t wData2[0x200];
    ' r. E" U' j% |5 z) Z2 K0 y) {
  8. uint8_t wData3[0x200];
    8 B1 O0 D2 D& O7 s
  9. % a0 P, f5 k) Q6 B
  10. uint8_t rData1[0x200];( r% Q% k. z7 C
  11. uint8_t rData2[0x200];: C2 T8 R+ t) v% i3 x: w6 h
  12. uint8_t rData3[0x200];
    ; Q( }3 Y+ t0 u
  13. uint8_t ID[4];1 r* p/ i$ p9 [" t
  14. uint32_t i;
    7 E1 ]' K0 R$ f

  15. % O! v, Y. D7 d3 S6 E
  16. uint8_t flag[1] ;
    ! a2 u9 i: t6 X- t
  17. int i_flag = 0;- d( U  O) ~+ N4 F
  18. /* USER CODE END PV */
复制代码

5 t$ o- d1 Z8 v6 x2 x串口重定向。
4 N4 r8 f+ ~! I+ }! Z% |5 P5 r
! B( ~2 g( v+ e  O: x) B1 f! r
  1. /* USER CODE BEGIN PFP */- r# O9 r; \; s' k! o' _* X
  2. void uart1_data(void);                                        //接收函数
    % g1 ?( @: Q! m: U, m: l" q
  3. #ifdef __GNUC__                                                                        //串口重定向
    6 |$ l: P7 i, \
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    1 Q4 e' E1 P& p/ e1 _
  5. #else
    ( d; a" H5 I# z; G( O. t/ e6 @- s# ^
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)& c$ \( Z* c0 C4 W. [& j
  7. #endif
    . }6 t7 ?! ?4 y7 i9 [2 }
  8. PUTCHAR_PROTOTYPE( f( L  I& q6 M2 r" k
  9. {
    % p: Q9 `8 e$ G8 z6 A4 V  v' n5 y
  10.     HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);2 k' ^( \6 S' E, T7 W$ n7 ~% R
  11.     return ch;
    2 |3 B+ F7 A1 Y! [  |
  12. }; \6 p* m; g  g! z5 D4 j* R

  13. ( F( w6 I2 K8 S7 O; K: t- ]
  14. /* USER CODE END PFP */
复制代码

& w7 O  U, V; j#include "stm32f0xx_it.c"文件中断外部变量引用:9 m3 \1 }" g! R. D7 K5 O

8 h/ N, K3 B$ f- h. y% K+ c- L% D
  1. /* USER CODE BEGIN 0 */, e, F- n1 l8 f3 {4 j) K
  2. #define BUFFERSIZE 255        //可接收的最大数据量( }8 ^, Q% T+ G/ x
  3. extern uint8_t recv_end_flag,Rx_len,bootfirst;
    ' [5 U# m9 g7 U  {
  4. /* USER CODE END 0 */
复制代码
( ~7 N$ N" B1 g3 Y7 f1 D" e
串口1中断函数:
4 ]) x8 x, `" s# V7 l
! {* U' l- f5 u: u* m7 b) c
  1. /**0 m% D+ J9 `( h. A. K1 I3 A: @
  2.   * @brief This function handles USART1 global interrupt.3 |: D: v+ i5 R. x: `* B4 v- W2 m
  3.   */
    8 P& `3 }4 c) a* t  C; W8 b$ Q
  4. void USART1_IRQHandler(void)
    % l! w" j+ p8 G3 `+ {4 i
  5. {( I( @& M/ X% G' b# e
  6.   /* USER CODE BEGIN USART1_IRQn 0 */8 L/ i9 j) a" Q+ e
  7. 8 W1 _8 Z7 M2 H: M8 L
  8.   /* USER CODE END USART1_IRQn 0 */
    " L4 m* u3 z$ ?  h" c; _- b0 C
  9.   HAL_UART_IRQHandler(&huart1);
    ) t3 T7 Q, X' O
  10.   /* USER CODE BEGIN USART1_IRQn 1 */9 @. T/ Y/ H2 Z5 x/ y0 O
  11.         uint32_t temp;! N1 o6 C! ^' U: \0 M' Q$ ]
  12.         if(USART1 == huart1.Instance)//判断是否为串口1中断/ i, p, J1 P9 e8 p! e2 r" F/ ^
  13. - x2 q/ Z' u2 C* w. }
  14.         {      
    . d- {0 A$ l0 N3 X& Z4 B0 X6 ]
  15.                 if(RESET != __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE))//如果为串口19 i! a1 R0 J% s% ?) i1 ]
  16.                 {6 Y1 U; k3 d# D+ a
  17.                         __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除中断标志
    ! L4 ^1 B5 o, ^: w0 H: e
  18.       HAL_UART_DMAStop(&huart1);//停止DMA接收! y& _! r. i, l: V
  19.                      temp  = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);//获取DMA当前还有多少未填充6 G1 y* Y5 ^. S
  20.                       Rx_len =  BUFFERSIZE - temp; //计算串口接收到的数据个数
    ! q0 {7 |- N# o/ a
  21.                       recv_end_flag = 1;: ?# s/ t3 ?9 O# ^% L$ \
  22.              }
    % T9 ~" ?& c& G9 V8 ~
  23.         }        ' n8 p6 M$ q  h+ @
  24.   /* USER CODE END USART1_IRQn 1 *// O( [5 s# j. p
  25. }; V" N" Q5 |; L! v
复制代码

. i/ d  q0 H7 _/ A7 V5 {8 N在main.c函数中,初始化串口和W25Q128。7 q9 ~. o7 D# B7 K

: o7 ]1 G8 x; \8 h
  1.   /* USER CODE BEGIN 2 */
    ) N+ ^& h# B1 t/ T
  2.         printf("串口1DMA例程\n");
    2 h9 q, S4 A4 k* h' S: h
  3.   __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能串口1 IDLE中断
    7 O  x  d" Z; n! b
  4.         5 B2 i9 m6 K4 i7 s& t  j0 K
  5.         
    + r% U' L0 @# c' ~* [2 P" B& x
  6.         $ Q3 ?0 V: V( T2 Q% n" y
  7.         & N" \  g9 V4 B
  8.                 printf("\r\n SPI-W25Q128读写\n");" n: z0 C5 m6 ~! q
  9. # P8 H/ T. w4 O& L4 Z: P! g
  10.         /*##-1- Read the device ID  ########################*/ & E. s; ], o5 r& k+ x* d! P
  11.         BSP_W25Qx_Init();//初始化W25Q1283 a# h9 g5 C+ ?" y7 e3 l6 T6 `
  12.         BSP_W25Qx_Read_ID(ID);//读取ID
    + i/ [. f. p# c$ C% j

  13. 7 c, h2 n8 P; R  t' Y1 T4 Y
  14.         if((ID[0] != 0xEF) | (ID[1] != 0x17))8 i% _) c: @4 ~* A
  15.         {. N8 Y$ C7 _2 ?- ?- V% Q$ h# f
  16.                 Error_Handler();//如果 ID不对打印错误8 K' c& `) p' n
  17.         }+ u& z+ T- F( K
  18.         else//ID正确,打印ID
      {6 m/ [& a" J/ _
  19.         {5 ]1 u. ~/ M3 d% p  Y! _3 L8 G; y- B
  20.                 printf("W25Q128 ID : ");
    ; W9 S/ K6 c6 X  |
  21.                 for(i=0;i<2;i++): h4 V6 G5 A+ D, A+ s- e- _
  22.                 {! P* [* A7 r; h; h, V. E: `) D
  23.                         printf("0x%02X ",ID<i>);, [0 @1 z& `3 N
  24.                 }
    & U5 h& V8 w! G& k& D2 ~4 |
  25.                 printf("\r\n\r\n");
    - n' A" Q" X" ^& s+ o5 T6 ]7 Y  c: K
  26.         }% J( {3 S, F: h9 w' I+ Q
  27. $ F* l7 u8 @) ~( L1 z
  28. /**************************读取第1扇区数据**************************************************************/
    ) F, B! E& S: {8 n( s/ b% \

  29. 9 H& J3 ?$ o% @( L! I, d/ ?
  30.         /*##-3- Read the flash     ########################*/ 7 b) @+ _& J. U0 z& p" d
  31.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/* W" g, I; s6 y. z
  32.         if(BSP_W25Qx_Read(rData1,0x0,0x200)== W25Qx_OK)
    $ B) x4 z* ^9 i1 O! j* `9 {
  33.                 printf("读取原始的前1个扇区数据成功!\n");4 W+ v; i+ M5 c( a! c  b% E: d
  34.         else, l1 b1 H" L: j. ^
  35.                 Error_Handler();* r8 i+ V9 P6 v$ X! ?& N7 j7 c  v
  36.         /*打印数据*/        
    , W& r9 B8 ?+ U& b. r8 Q8 F
  37.         printf("读取原始的前1个扇区数据为: \r\n");
    / _3 L; \% s+ M* d! J1 M  ~
  38.         6 Q6 g9 N) p4 P
  39.         for(i =0;i<0x200;i++)2 k) }4 z6 y, x+ B0 t& [$ `8 l
  40.         {! T1 P; B3 M" `/ u: g" k
  41.                 if(i%20==0)& R% o$ f; |6 }$ K
  42.                         printf("\n1扇区第%d到%d的数据为:\r\n",i,i+19);
    - r3 e- T- U! d/ E8 V
  43.                                 printf("0x%02X  ",rData1<i>);! B* D% p7 @; r: \5 E
  44.         }0 i5 o$ k! Q5 [$ D. s

  45. $ N7 I) l/ M& K5 j7 d# x
  46.         printf("\n");
    * a3 _9 `; u, V# `; r8 ~  L

  47. 7 Z% Q4 Y+ {2 |
  48.         
    / a5 a. C$ y7 {+ c
  49. /**************************读取第2扇区数据**************************************************************/; t0 z: [+ ~7 u% M, H8 Q4 B. W# ^5 [" R
  50.         $ Q8 n' u  l  I3 N, l; R2 W2 N3 V+ ^
  51.         /*##-3- Read the flash     ########################*/ : h3 t1 u0 N# l6 f
  52.         /*读取数据,rData读取数据的指针,起始地址0x1000,读取数据长度0x200*/
    . r3 Y( g! a# X6 E) S: f, g
  53.         if(BSP_W25Qx_Read(rData2,0x1000,0x200)== W25Qx_OK)
    ( O7 L+ c; t* P' c  x/ }
  54.                 printf("读取原始的前2个扇区数据成功!\n");  N2 L. Z5 M9 W8 I* n* }
  55.         else1 c* y- y; n" ~) a& U2 B
  56.                 Error_Handler();
    8 F1 b" i0 I4 ^& C- |( B
  57.         /*打印数据*/        ; a8 K, F3 y6 `; g1 N8 H5 f- g6 L
  58.         printf("读取原始的前2个扇区数据为:");
    . \: e% h5 n3 v
  59.         
    ; R$ f: o: y) h/ }" k+ Z
  60.         for(i =0;i<0x200;i++), r+ K) O" Y  `  C% T  N
  61.         {& x& F: ~! p4 ~
  62.                 if(i%20==0)
    ) Z2 z7 |7 I4 y
  63.                         printf("\n2扇区第%d到%d的数据为:\r\n",i,i+19);
    & }5 Y9 z" E$ ]1 U& J$ Q$ ~. @* `
  64.                                 printf("0x%02X  ",rData2<i>);
    : d, D$ ?5 g( c* c9 k& k! X
  65.         }
    + d& ^  m1 Q  V: \7 z* U
  66. / j$ X0 J1 q1 {1 O* w" r, S+ s
  67.         printf("\n");        7 d8 i0 K' c; L0 @& F9 _* u
  68.         - P$ N" H" _8 G% S+ d
  69.         5 |6 q- n# x9 E; u2 `9 Y$ u  k
  70. /**************************读取第3扇区数据**************************************************************/
    + b( M1 k2 L& g; t* C# x: k" D! L
  71.         
    3 y9 |* g# V* |: a. b
  72.         /*##-3- Read the flash     ########################*/
    , y) z  i: C, w- _
  73.         /*读取数据,rData读取数据的指针,起始地址0x2000,读取数据长度0x200*/
    # J+ c) \5 B& I, R; l- \
  74.         if(BSP_W25Qx_Read(rData3,0x2000,0x200)== W25Qx_OK)
    " p3 g0 t  `* C; U: U
  75.                 printf("读取原始的前3个扇区数据成功!\n");& O! P& @0 n; _% _
  76.         else  ]7 s  z3 o' v/ Q% F; _
  77.                 Error_Handler();8 r# @9 c0 _& M
  78.         /*打印数据*/        
    , }- t. |9 r% A: `  v
  79.         printf("读取原始的前3个扇区数据为: ");
    5 Y# S5 t# H" e9 J
  80.         
    ! l; j! r6 I8 P4 x
  81.         for(i =0;i<0x200;i++)
      E! c* l3 o* h( r
  82.         {
    % w; q6 Y" o- c/ v! M
  83.                 if(i%20==0)4 D) g$ k5 A( Z6 W" w5 S
  84.                         printf("\n3扇区第%d到%d的数据为:\r\n",i,i+19);( \% g' }9 q# U9 ~9 p3 |% H
  85.                                 printf("0x%02X  ",rData3<i>);
    * l; T( ~0 F) k' l# h. Z7 M
  86.         }: {' j& t8 O, e8 T8 t

  87. 9 c$ U3 b6 o* M6 q- [7 r9 o! B
  88.         printf("\n");        
    8 A% D6 S5 Y, E
  89.         
    * J6 M0 y+ b( Q- K0 U7 a. I# c8 e
  90.         7 N( s* ^1 O  W# n
  91. ! C$ n( H. T$ j, |  b( P
  92. /**************************清除第1扇区数据为0**************************************************************/
    & i4 i2 |$ L" a3 z
  93. . i, `( y9 }6 y2 f% M* o" G9 r
  94. . u' _" C  k  M$ y. l
  95.         , C* W% p9 e' v5 X( \) n6 h
  96.         /*##-2- Erase Block ##################################*/
    4 \. u; f9 D" g$ R3 I+ c
  97.         if(BSP_W25Qx_Erase_Block(0) == W25Qx_OK)
      f$ W5 C; L: j$ i2 R  @
  98.                 printf(" QSPI Erase Block ok\r\n");1 X8 e) D* @- G$ c
  99.         else
    * q& f8 d/ u5 J
  100.                 Error_Handler();4 ]5 O/ r! @0 a8 l! h0 u' M; M8 p1 ^
  101.         
    8 G" j  x0 `2 p9 r) R
  102.         /*##-2- Written to the flash ########################*/ + `+ I- S- f3 {# y* `: f; p7 n
  103.         /* fill buffer */
    1 Q3 j$ z3 {5 h9 |+ r0 t; d
  104.         printf(" 初始化数据,清零第1扇区前0x200的数据!\r\n");
    ' s& T" J  N" d+ ]4 F/ C
  105.         for(i =0;i<0x200;i ++)' h8 \! P: G0 ?4 f
  106.         {
    ) G7 z1 ]; N  q/ l7 \% `& }
  107.                         wData1<i> = 0;
    7 n* S; D) v2 t6 M- ?$ ]
  108.                   rData1<i> = 0;
    & u& \$ y+ b* j0 y8 C6 ]- C4 t
  109.         }
    $ Q4 K8 _! N* N& t! l3 Z% p: ^
  110.         /*写入数据,wData写入数据的指针,起始地址0x00,写入数据长度0x200*/" m9 w% B+ h7 Y2 h2 z8 G
  111.         if(BSP_W25Qx_Write(wData1,0x00,0x200)== W25Qx_OK)% O: J: @0 E1 L9 y+ L3 Y5 U- y& B
  112.                 printf("清零第1扇区前0x200的数据成功!\r\n");- S; f, a6 A1 d5 ]: N
  113.         else/ ~! P2 a+ Q/ h+ Q6 ^4 t1 n. ~
  114.                 Error_Handler();0 t+ q8 \8 j& [5 \! |; h
  115. + L1 _8 ^2 ^$ t5 Y" L2 i! Y
  116.         7 `- t; c+ n3 a! \+ B* T
  117.         
    6 t5 S% I$ d0 H4 }$ D
  118.         
    4 N0 s1 k4 Q1 {+ y
  119.         /*##-3- Read the flash     ########################*/ " N+ e8 Z, D8 I6 V- s* Y( P2 }
  120.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/; e' T# A( J3 `7 f# o: f. F
  121.         if(BSP_W25Qx_Read(rData1,0x00,0x200)== W25Qx_OK)8 [+ o3 H7 ]# k( X; t
  122.                 printf("读取第1扇区前0x200数据成功!\r\n\r\n");
    - u6 g2 R3 x( M( g3 ]/ {
  123.         else
      r8 C4 s; g' D4 m* w; Q
  124.                 Error_Handler();
    7 S  z1 p; {- `7 M0 z
  125.         /*打印数据*/        ) V- F) H! s* [8 F
  126.         printf("读取第1扇区前0x200数据为: \r\n");
    7 U* o3 Q! H4 q. C# n
  127.         
    6 w+ J1 C% _& O+ w4 S& X) J6 W
  128.         for(i =0;i<0x200;i++). C( K& y4 t% j" E, M
  129.         {1 H) C' S+ h" e  I! H+ S, H
  130.                 if(i%20==0), o. P7 J) p5 o# L
  131.                         printf("\n第%d到%d的数据为:\r\n",i,i+19);+ \5 d* {9 [5 k$ E
  132.                                 printf("0x%02X  ",rData1<i>);- v7 R, G6 R& b+ r+ u7 k0 p
  133.         }  q9 O1 }5 E" C  N

  134. / M  v% Q3 o% f( R
  135.         printf("\n");0 i* C" q) h1 H  K7 t8 H# P5 \. x

  136. : }1 @) x0 M4 i# ^$ E6 L

  137. 7 u7 o' y9 v' U( C
  138. /**************************清除第2扇区数据为0**************************************************************/* u, l4 E( \: Z/ E

  139. / D# {0 v; w# M2 v' J

  140. 9 Q! d! E5 }1 y$ }3 k8 H; j2 [
  141.         
    4 ^5 I2 ?4 R7 t- w
  142.         /*##-2- Erase Block ##################################*/ - o/ L9 P4 ]2 G% `9 G
  143.         if(BSP_W25Qx_Erase_Block(0x1000) == W25Qx_OK)8 b$ c  b. r$ o' R
  144.                 printf(" QSPI Erase Block ok\r\n");
    5 V6 T9 W& |$ D4 e
  145.         else. [2 I. {# q( k' C6 C% `7 `
  146.                 Error_Handler();
    * E2 m1 k( ?- c) }' I
  147.         0 p' o+ F6 O$ Y+ V/ a
  148.         /*##-2- Written to the flash ########################*/ , g( f! t$ P1 k' x* g& k' t  o. N+ `
  149.         /* fill buffer */' ^3 t( x/ O. g* ^. Q' @8 Z) l
  150.         printf(" 初始化数据,清零第2扇区前0x200的数据!\r\n");
    . {; _0 M# k& [
  151.         for(i =0;i<0x200;i ++)% z* K" a* |/ \) L) @
  152.         {5 W: }, D! T( a" q
  153.                         wData2<i> = 0;9 a( v1 [  k, O8 |, Y& E. p9 S
  154.                   rData2<i> = 0;3 }+ }! b; w. ~5 S2 L0 B' V% e/ E
  155.         }/ {& K5 E7 L% v+ Z
  156.         /*写入数据,wData写入数据的指针,起始地址0x1000,写入数据长度0x200*/
    4 j( C* ~# a8 a: ?) D
  157.         if(BSP_W25Qx_Write(wData2,0x1000,0x200)== W25Qx_OK)0 m! J6 _6 h, `7 z  o: z- X
  158.                 printf("清零第2扇区前0x200的数据成功!\r\n");
    0 C6 ~; U3 K, K  {! F! _; O
  159.         else* Y- u4 ?: d2 o0 r
  160.                 Error_Handler();( [( g- n3 X' _
  161. 1 g+ W9 c1 o5 |" m! O; a( V
  162.         
    1 L: @8 I; @6 Q# h
  163.         4 h2 h9 Q3 ?: l& v
  164.         
    ( \- l9 Q2 U2 D& ^* o  z
  165.         /*##-3- Read the flash     ########################*/ : f- R/ c0 W, u$ a6 l' }
  166.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/
    5 m. u' r* t. f. E, y9 m- [
  167.         if(BSP_W25Qx_Read(rData2,0x1000,0x200)== W25Qx_OK): s1 a. D, v5 m0 s3 n
  168.                 printf("读取第2扇区前0x200数据成功!\r\n\r\n");
    1 N1 r( \2 s  Y3 F/ [# C. N
  169.         else. _+ c4 G2 O( ?5 a+ C( Y# n
  170.                 Error_Handler();
    % U$ u: `2 v$ E' _* \5 b  h
  171.         /*打印数据*/        
    : Q8 A5 |5 |3 J5 e6 [$ @
  172.         printf("读取第2扇区前0x200数据为: \r\n");
    5 s# D1 p( d( \7 h
  173.         
      H0 k4 ~' a2 K1 M4 k
  174.         for(i =0;i<0x200;i++)" Z  ~' E0 V) w, ~( o) |* u# Z
  175.         {$ h: L' |) l3 L# O6 ?- t
  176.                 if(i%20==0)( k* n1 _9 H, w. k+ Z& f- @
  177.                         printf("\n第%d到%d的数据为:\r\n",i,i+19);* x- D, X/ R. z3 w9 q
  178.                                 printf("0x%02X  ",rData2<i>);
    2 @0 G5 x0 v0 g# Y; R
  179.         }* Z4 ^9 e3 g5 u" r* r& H" D

  180. ' M* |0 y) }, |( e2 D
  181.         printf("\n");
    . a4 g6 ~4 k+ [! c: X. g
  182. 1 l  `" X' N6 v

  183. : K  M3 l6 C1 c; G. W' P8 C* f, P
  184. /**************************清除第3扇区数据为0**************************************************************/
    ; X8 V/ R- q4 P0 w" q$ T
  185. & F; ?! Q) \: W8 i6 Q: L3 `

  186. + E" M# U. x- W& L- G
  187.           \, m  ~- I6 ?- y
  188.         /*##-2- Erase Block ##################################*/ " x" }; b: S( f; }, o1 `) b
  189.         if(BSP_W25Qx_Erase_Block(0x2000) == W25Qx_OK)
    2 e. _6 j, q* m5 t# c8 X5 L* _* c
  190.                 printf(" QSPI Erase Block ok\r\n");) u& s# H/ w4 {4 z; o# F# d- D
  191.         else
    7 o! V/ m  n0 P, g$ o8 `$ y% y: F5 K
  192.                 Error_Handler();# e9 O% P% z5 A; i! }( q" f- |( T
  193.         # O4 d0 g# ~' ]* B
  194.         /*##-2- Written to the flash ########################*/
    % _: w0 [7 T$ g  L
  195.         /* fill buffer */
    0 r5 k) s. U. U; o, E& _7 A
  196.         printf(" 初始化数据,清零第3扇区前0x200的数据!\r\n");9 b( W+ D5 s: i9 ?
  197.         for(i =0;i<0x200;i ++); h# o; Z/ z) D# K9 i9 u8 o/ T7 Q
  198.         {+ d  M+ a+ ?& L( J4 m( W% `
  199.                         wData3<i> = 0;* m, Z$ S; \( o7 @# x0 e
  200.                   rData3<i> = 0;8 U3 d8 y. p/ N# R
  201.         }0 D, G4 B( O, ?" F- H' ]% B
  202.         /*写入数据,wData写入数据的指针,起始地址0x2000,写入数据长度0x200*/! y+ p1 ~+ s* G. z2 c, u0 X) t
  203.         if(BSP_W25Qx_Write(wData3,0x2000,0x200)== W25Qx_OK)6 y: G' R% {. H/ H' y( C3 j
  204.                 printf("清零第3扇区前0x200的数据成功!\r\n");
    + o* T" w" ^5 y" y
  205.         else% G9 L0 x7 ]6 p* r
  206.                 Error_Handler();
    + s- c3 U% y2 G- K  W
  207. / [( Y3 [2 ?* V1 X3 [5 p7 b
  208.         9 ?  n; E* A7 t/ g
  209.         ! O: C; M# S" s6 g% L  e
  210.         
    . M4 _3 s1 v9 `0 P9 F1 _
  211.         /*##-3- Read the flash     ########################*/ 0 L/ p) Q8 }) P( z$ ^( d
  212.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/+ ~1 U* ~: D1 J
  213.         if(BSP_W25Qx_Read(rData3,0x2000,0x200)== W25Qx_OK)
    ) M+ y9 P( G6 p( |. o9 F
  214.                 printf("读取第3扇区前0x200数据成功!\r\n\r\n");
    : ]9 g1 A) c2 `: Z, c3 ]
  215.         else" Y9 w' j* ^& h9 n" n# [- S
  216.                 Error_Handler();% U' }  p9 u7 e, b  q+ Y
  217.         /*打印数据*/        
    ! l: j5 W$ G+ g* j8 `) M# j' [! N4 ~
  218.         printf("读取第3扇区前0x200数据为: \r\n");
    & p# w8 ~) Z' N7 e1 f  C
  219.         ! s/ d% A/ y4 Z
  220.         for(i =0;i<0x200;i++)
    & ^( f/ j+ g; k" S' i
  221.         {( B; ~# r, A& j3 e) [' U
  222.                 if(i%20==0)5 H; M6 Z2 U( ~) S4 F
  223.                         printf("\n第%d到%d的数据为:\r\n",i,i+19);& |! g& T) k& u$ J
  224.                                 printf("0x%02X  ",rData3<i>);
    4 N2 b$ l# J9 c7 A5 ^1 O
  225.         }% b( L6 g, t' y5 h
  226. ; v6 |7 ?4 t; f$ G; s& L6 _* h
  227.         printf("\n");% Z9 n) B& q+ @# o

  228. 5 s2 R  m+ [& ]8 q
  229.         : s8 H6 R9 d$ O# q, p! _
  230.   /* USER CODE END 2 */</i></i></i></i></i></i></i></i></i></i></i></i></i>
复制代码

5 G' _/ \% P2 i6 K主程序。- \, x: M# `* w. V) q" ]0 |
2 J3 i3 I' }5 v" E- \" ?
  1.   /* USER CODE BEGIN WHILE */" R9 b& D6 o) d' W+ s. ?
  2.   while (1)& d* U+ [, m2 j6 L6 s9 \
  3.   {, o. S* K3 E7 W6 \6 P, e$ j9 r
  4.     /* USER CODE END WHILE */4 _% a5 |- L; @0 U( i; I# y
  5. + r2 \% Y$ v+ i5 N/ v
  6.     /* USER CODE BEGIN 3 */
    / w4 \& L% f& I1 Z  n6 `! G
  7. 0 }/ n, Z1 C0 V, ~3 k
  8.                 uart1_data();//串口数据处理$ y) g$ V2 P& Z/ |; l& |
  9.                 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);
    8 U3 ]8 c9 C$ G! m6 ~6 i7 S
  10.     HAL_Delay(100);
    0 r: i, ~* w5 L3 D+ v
  11. $ B' |! {( Q1 @% ^
  12.                 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);0 f# N7 P; A9 r, `6 S+ `
  13.                 HAL_Delay(100);
    , Z# I! W. d& z! z, B' q6 Z7 m( }3 i7 {

  14. 6 o. i  a+ s0 l$ |0 P% G: N. U; a
  15.   }
    - q4 S# r7 z3 t* N( H/ k' A; B
  16.   /* USER CODE END 3 */
复制代码

( A* k0 I! p" F& e4 F' E3 L演示效果

/ [6 s; C0 E3 W5 Q8 d7 g# j  WW25Q128芯片型号的ID为0XEF17,下方读取为0XEF17,所以读取成功。: P1 E( I5 s4 V
开机会打印出1,2,3扇区的前0x200个数据,即打印2页的数据。. Z/ P; M0 C6 e9 `9 B
2021061412103011.png - |+ K$ p& e  N; I4 B

, u/ v* p( ^3 @- S& `打印完原始数据之后将数据全部清零,清零完成如下图所示。
6 O; w' j; k5 P! {/ s+ H% u0 L: _. v$ |3 O) d- x/ p3 U; `9 w
20210614121333771.png
. v) ^+ i4 v0 D6 ~7 m/ y% u) ]
0 x0 d8 [4 l( r$ {2 F串口定义了ReceiveBuff[0]的数据为写入什么扇区,ReceiveBuff[0]为1写入扇区1,ReceiveBuff[0]为2写入扇区2,ReceiveBuff[0]为3写入扇区3,若为其他数据,则打印输入错误;ReceiveBuff[1]则为写入的位置。( \2 ~8 t& F- \4 \
输入:01 05 01 02 03 04
( f8 B) I/ O4 q3 L8 T1 I向扇区1的的05号位置开始写入数据01 02 03 04。
' c! z* \3 i2 i  g- J8 d( B: B! m6 `+ f! w6 x, M9 {; k; s4 {
2021061412183641.png $ t7 k8 s& @5 x7 `4 ]) w

9 u- y/ l% g1 H1 m. ~输入:01 28 11 12 13 14 15
$ W# Q( Y5 S$ j* b3 ~8 A向扇区1的的40(28是十六进制)号位置开始写入数据11 12 13 14 15。
% b: Z9 h1 n& J5 y1 w! e1 N2 z; x6 j) K9 [3 l7 |6 {$ ?
2021061412202059.png
% z1 ^& b! G! e# A& N9 w! k  i6 p5 ?  h. Q
输入:03 10 aa bb
6 V5 x7 h, A: |* y向扇区3的的16(10是十六进制)号位置开始写入数据aa bb。
5 v8 e8 d; ]# ?, j1 |
- m* t6 ^' n5 m* G6 p( m, i" K 20210614122136429.png 5 h. o) u' v$ z' x

% X' D& l7 s9 z6 g: F3 i4 t% x$ C( v& f1 ?1 |) ^) s

2 q# j1 P+ S4 \7 ~' g, v7 N3 h+ s
赞 收藏 评论0 发布时间:2022-4-29 23:31

举报

0个回答

所属标签

相似技术帖

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