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

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

[复制链接]
STMCU小助手 发布时间:2022-4-29 23:31
概述- j; S4 i+ s6 _0 ^
SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议,比如 EEPROM,FLASH,实时时钟,AD转换器。
) `0 D; Y  X0 @W25Q128 是一款SPI接口的Flash芯片,其存储空间为 128Mbit,相当于16M字节。W25Q128可以支持 SPI 的模式 0 和模式 3,也就是 CPOL=0/CPHA=0 和CPOL=1/CPHA=1 这两种模式。/ r8 x3 l6 L+ ~5 H2 F

6 G4 ^* x( V/ g2 Q硬件准备
% T& G$ r, u7 P& K6 h首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:
+ a* a  l. k* j, N$ m6 k
$ |% w0 S2 h$ B) k+ n H0)1(DOD46`N0X`9J48V~LL.png , Y: Y" a- A7 y
; [- o' ~# I2 t- q
选择芯片型号
* p8 _, K) x4 D: [使用STM32CUBEMX选择芯片stm32f030r8,如下所示:
3 W3 R9 h6 A3 H5 t. O) z$ R+ Q4 O
20200604204408810.png
+ s8 K# Q' j& ^; i2 r# u9 r: T  F3 v6 V& O( i
配置时钟源$ I8 M+ |7 P2 r; g4 J
HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:  B+ ?. O2 K' ?9 |, U
; |; s5 H! M2 l3 Q8 X
20200604204644344.png # Q2 L+ I  o  G% e6 l
) n  k+ \# M1 Z, l$ S
配置时钟树
3 K5 D1 B: g$ w7 f& V5 l$ o
STM32F0的最高主频到48M,所以配置48即可:
: w7 c$ Z, ~  I8 ~) p/ q4 _$ @8 ^5 y: t0 J% Z$ b  H4 E
20200604204550406.png
# M2 n, \' K  }% e5 S" B8 G" I) E; N& H7 i
串口配置

7 \5 r; H% R, f+ G% A本次实验使用的串口1进行串口通信,波特率配置为115200。
  P2 I$ Z7 `' o4 r" r* e, b5 N* |5 M  ?# c0 ?5 ^% ^# R$ Q
20210614162936131.png
/ L: Q3 b$ E1 Q0 G. D& t
$ A/ b1 ^5 L3 c; r( r" L2 `开启DMA。
5 e! u5 j+ b. p$ k4 I
( r# n7 Z' g( h# q/ k N_16%XT{@J)CZ)GTB]EIQDA.png
8 V; o1 A* L, }+ N: R' h, l. s8 j8 D- n( Y1 i7 x; L  Y. w
中断。) ], Q& {/ u) I. e- C& J4 I

9 l; D4 N: a4 s+ G0 g8 G& k VBII06W}JD]NLOB}ZFO}NCU.png
% u9 N2 _6 P8 R# T9 _5 b5 J6 l4 ]0 q! v; m

) j; V7 m. n% w. F/ I
SPI配置
2 \: D# z. {& k( P2 a' S* j本次实验使用的SPI与Flash通信,配置如下。
) n; ~& W- ?, P- j" cSPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。
6 D5 P6 P5 ~3 z2 l(1)MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;  k0 J8 `  R( @: d' j- F
(2)MOSI– Master Output Slave Input,主设备数据输出,从设备数据输入;
6 h8 I* w" S! {! S(3)SCLK – Serial Clock,时钟信号,由主设备产生;; u# c+ J  W$ K, c5 Y- P$ ^! H2 i
(4)CS – Chip Select,从设备使能信号,由主设备控制。( A8 o# W* e2 x. {
2 g( X1 ~: [$ {, ]
接线方式

9 X: u3 U- Q- a* i) _
+ k, o1 z3 |3 r& |7 [ (W7W[AN$X(90R]}GP`7_167.png
! L5 [2 ~) C: `8 ]4 t
( }6 ?6 K( R  _2 g& ~: v9 }负责通讯的3根线了。通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCLK时钟线存在的原因,由SCLK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。因此,至少需要8次时钟信号的改变(上沿和下沿为一次),才能完成8位数据的传输。8 d' W3 A" V& _; Q4 q
时钟信号线SCLK只能由主设备控制,从设备不能控制。同样,在一个基于SPI的设备中,至少有一个主设备。这样的传输方式有一个优点,在数据位的传输过程中可以暂停,也就是时钟的周期可以为不等宽,因为时钟线由主设备控制,当没有时钟跳变时,从设备不采集或传送数据。SPI还是一个数据交换协议:因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。芯片集成的SPI串行同步时钟极性和相位可以通过寄存器配置,IO模拟的SPI串行同步时钟需要根据从设备支持的时钟极性和相位来通讯。
& K5 n  n8 l0 u$ l5 r' H# ]$ W/ ^" Z最后,SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据。
& d' ?' B8 d2 T/ ~+ E5 H
# R* N2 P7 P/ R" h7 [, G 20210610002146525.png + s/ t  D% Y+ @4 k
6 }, v: w: D/ ]1 J
其中,CS是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个SPI设备成为可能。' f; O$ ^$ `2 y1 z, `; H2 B. \8 x- |
随便配置一个端口为CS片选,并且命名为CS。
  I& z* ]# w7 n- L8 J0 ~% `$ v! ?1 X& }0 l) O
, t& B0 u8 B% |# b 20210613153651922.png # o$ f8 ]) A# [

; \0 x- s: i) M生成工程设置8 {1 O9 |& Z$ u1 j
注意在生产工程设置中不能出现中文,不然会报错。1 O: Z- _. m! y/ I2 f' @: h4 T( [
; `* A, C  Q' s* u" M
20210610002715361.png ( I3 P7 i" T# g0 `
# H  b. C/ t* t0 P9 [
生成代码% o0 \' O5 l; ]

( r  V) \4 c5 ]9 l- a$ P( N# Y
20200604205807980.png 1 e; \4 o8 I6 s% \, e1 m7 X

/ ]8 Y6 ~* d' A. M配置keil

3 S7 O( c$ @6 k. X: {: Y2 X3 `8 c5 K0 {! x2 M. n8 y/ Q
20200604210002645.png 5 l3 }- \+ u/ y" i# D
% L7 `* H8 e$ G5 w
W25Q128的原理及应用
. |1 U1 @, y+ h' o5 SW25Q128将16M的容量分为256个块(Block),每个块大小为64K字节,每个块又分为16个扇区(Sector),每个扇区4K个字节。W25Q128的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。- g+ q2 R# G' o) @) \$ K
芯片ID如下所示。
4 y" }$ m) V9 h& y
! e+ G) H0 x/ ~! Y! h/ `0XEF13,表示芯片型号为W25Q80
  }, C$ L0 x. o( O) F& x2 J2 i5 ]0XEF14,表示芯片型号为W25Q16# j0 B4 T$ l7 T
0XEF15,表示芯片型号为W25Q329 H% g" U, y: Q; e
0XEF16,表示芯片型号为W25Q64
) d3 \6 H% M5 x5 Z; \& g/ x' W0XEF17,表示芯片型号为W25Q1288 Q" x2 T# p- a  T$ U

1 v; J% F% F4 _9 G+ }. U3 V驱动代码/ z- |7 O. y: ?* a/ i) t
W25Qx.c
3 s! q% W- ?9 w9 d" w7 B( Z
  1. /*********************************************************************************************************0 J: W$ u2 n& f# A
  2. *7 l& s9 K3 \1 j& a4 y
  3. * File                : ws_W25Qx.c
    . E% Z$ U. m! y! w' E. H. t
  4. * Hardware Environment: ' F! l2 Y/ m  u6 x
  5. * Build Environment   : RealView MDK-ARM  Version: 4.20$ T  w( _1 b6 k3 M1 m/ _
  6. * Version             : V1.0
    # H7 i' ]# l0 Y" V+ B
  7. * By                  : ) ]4 `4 w" y/ B
  8. *
    " ]2 ~6 q. {5 r0 u' K
  9. *                                  (c) Copyright 2005-2011, WaveShare' [4 A' \* _4 z. W4 e8 k
  10. *                                       <a href="http://www.waveshare.net" target="_blank">http://www.waveshare.net</a>  Z$ V! l3 e  p8 j
  11. *                                          All Rights Reserved4 g- a8 ^  p: A0 j( c
  12. *4 x. W, M* O- e3 g* X. H, Q
  13. *********************************************************************************************************/
    3 d4 E  m; ]9 a' k1 G

  14. 5 z0 u+ C! K: G$ o, f8 l* k- s
  15. #include "W25Qx.h"
    & G9 ^2 G8 y- G& ^6 P8 C

  16. $ ~: K6 B6 A& p3 j
  17. /**
    : B8 g  y: n% F) {
  18.   * @brief  Initializes the W25Q128FV interface.3 g: O- m2 m) O  W8 U
  19.   * @retval None
    $ s; [6 J: O% ?) N+ {! Y2 I) C: K0 G
  20.   */4 e) ~0 r2 F2 |. `& ^% m1 N: j: V  x
  21. uint8_t BSP_W25Qx_Init(void)
    + i/ U% r- c# v) {" \" g- w4 ~8 k
  22. {
    2 q; M- O% ?7 r
  23.         /* Reset W25Qxxx */; n# K0 x: Q: S3 O  m+ n* o, M5 b
  24.         BSP_W25Qx_Reset();0 @8 Q1 f1 Z* C/ L5 r8 y3 A2 |1 z+ d
  25.         
    1 h1 L- F' O; c# ]/ p
  26.         return BSP_W25Qx_GetStatus();! Y8 i/ ]3 R' f0 c% k$ S
  27. }
    . r5 v' m2 ]0 e* I8 u

  28. ; B- x+ S5 Y' o( x: V
  29. /**$ @/ N! a( ^6 m8 ?1 f
  30.   * @brief  This function reset the W25Qx.* m9 D! b0 ]& c* H/ v5 i* L: c0 z
  31.   * @retval None
    ( I* D& V1 k5 W; k) L
  32.   */- @  w/ Y$ W9 r$ P+ {' x4 j; W  i
  33. static void        BSP_W25Qx_Reset(void)5 N% o) e* ~( z, {2 ~
  34. {
    ' N1 I! Q- `# l4 v( d6 U. @
  35.         uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};. K. }: f7 M7 p
  36.         
    ' m$ A' V% w3 g
  37.         W25Qx_Enable();' Y3 ?) H% m* A8 }, }
  38.         /* Send the reset command */
    & Y2 X5 I" C# u8 `2 `8 t1 c
  39.         HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE);        
    7 M7 Q7 U9 L$ C* E) k) Q- f9 q
  40.         W25Qx_Disable();
    $ H+ l" ~$ g: o- S* m1 x

  41. " o: P4 ]7 b2 w2 ~$ C# v7 C
  42. }
    % S$ Q$ a6 V) K
  43. " s0 V4 |) s8 }) F
  44. /**
    7 u. V, R* g) _* g7 a- @8 _
  45.   * @brief  Reads current status of the W25Q128FV.
    / R9 i* F% H" d3 s6 o; i$ R7 H! F% `
  46.   * @retval W25Q128FV memory status: O/ _$ s  t; \3 L/ }% H0 ?+ t
  47.   */
    ; u3 l/ P/ j+ I; g$ }
  48. static uint8_t BSP_W25Qx_GetStatus(void)
    ! c/ H, j1 S6 R6 T* c
  49. {% p# F& |# F0 W* D3 O
  50.         uint8_t cmd[] = {READ_STATUS_REG1_CMD};: o$ O8 e3 G" m! U- Y- M
  51.         uint8_t status;
    & V  [/ g/ ]. s) g8 f- f
  52.           S; o9 x3 Z  a0 b
  53.         W25Qx_Enable();1 ]0 W7 h: e; o& N9 z  p! i
  54.         /* Send the read status command */8 {( Q" G. M$ u) l* n& g% D9 c) q, Y
  55.         HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);        ' Y5 b' }. b- j( ]
  56.         /* Reception of the data */
    % F+ L* b, h, g' a: h$ z: L
  57.         HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE);) }. U; Q' z. |: p  u6 g
  58.         W25Qx_Disable();! D: l/ d3 G. r
  59.         ) J- \- H1 G! ]1 ^+ t" R
  60.         /* Check the value of the register */: d( J# x3 _/ w9 `. T1 F2 `0 h
  61.   if((status & W25Q128FV_FSR_BUSY) != 0)* [6 X2 j. P+ i# k* C# s
  62.   {
    , ]3 m0 T+ F8 ]7 K9 L$ J# }
  63.     return W25Qx_BUSY;4 b  x  m# x' O8 I, m- \: g7 ?2 U
  64.   }' T% f0 [& Q6 h/ y1 y+ M" N
  65.         else" x* V% f4 Y2 `' a' b
  66.         {4 s4 ]$ M6 h& W% V# m
  67.                 return W25Qx_OK;" L, Q2 o3 \2 ^
  68.         }               
    9 l- N7 D$ V, Q+ B, _$ p
  69. }
    8 [$ X* W7 I5 O3 I& t2 r

  70. 1 ^+ s! k0 w& t( ]# B8 U7 ^
  71. /**
    - C3 D: r" m7 p
  72.   * @brief  This function send a Write Enable and wait it is effective.
    ' P' r2 Z5 F: W1 D- X
  73.   * @retval None3 N  W8 W4 Z" h2 z% ~
  74.   */
    + J* U1 X% O5 N* k% g( ]0 I
  75. uint8_t BSP_W25Qx_WriteEnable(void)# g8 z! B; H5 q1 h0 B, i1 Y1 M% r
  76. {
    2 P: O) |, h# q3 V/ d
  77.         uint8_t cmd[] = {WRITE_ENABLE_CMD};
    * U* l& s9 B' v$ Z( T' S3 B! ?6 z
  78.         uint32_t tickstart = HAL_GetTick();( c5 t5 ^3 ^: H( s

  79. $ ~. c1 Z. m% S4 V* i
  80.         /*Select the FLASH: Chip Select low */6 q- ^8 Q$ [' Z2 a, p
  81.         W25Qx_Enable();3 I* s* ^0 k" l
  82.         /* Send the read ID command */% H1 Z/ j, a- T3 b
  83.         HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);        : P9 M  m) T+ A6 ]
  84.         /*Deselect the FLASH: Chip Select high */
    & C, a9 y- [) _9 d# J
  85.         W25Qx_Disable();) n( a1 x4 s8 }7 L
  86.         
    2 f, d) [) {, J5 e
  87.         /* Wait the end of Flash writing */' b- K9 i' S6 J. `8 T  A, n9 f
  88.         while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
    ( M% v8 }2 @0 q: j# i
  89.         {" d4 f+ V1 J- |
  90.                 /* Check for the Timeout */
    " _; z" `# t  e0 r# C) O
  91.     if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)" p3 d; d" l( A3 V7 F+ Q/ ?) E
  92.     {        5 o8 C$ A- Q6 S/ v' X: `- ]
  93.                         return W25Qx_TIMEOUT;
    7 A4 D% q) [! c6 u) a
  94.     }9 w/ k9 {& w" c' c
  95.         }
    4 n: V, M$ H& a+ l
  96.         
    8 o) ?: I# ?) u5 p, P( v# T
  97.         return W25Qx_OK;& I- X% t3 Z' K% g3 `! f- ?
  98. }
    0 F3 j( Q' y* [& a

  99. 7 H5 i/ ]% [. _. V
  100. /**- W4 _4 _0 ^, A0 ^* h' ^  E
  101.   * @brief  Read Manufacture/Device ID.
    ( X4 Q- E; O' q' a0 f3 @. U/ O& a
  102.         * @param  return value address
    ' s0 W. \5 s3 O* P+ |8 i0 G
  103.   * @retval None( y6 Q# K, ~& l3 b9 h! T
  104.   */
    0 b7 S, C8 m, C" O6 Q( D
  105. void BSP_W25Qx_Read_ID(uint8_t *ID)
    8 z" r) p6 u- f9 j9 ?; Z1 U
  106. {
    9 p. N; M- |* G, t: I5 w& C/ e
  107.         uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};
    * l$ Z% M: T# ]% ?9 z9 U+ [" }
  108.         8 ~9 F( }" b& `
  109.         W25Qx_Enable();" L# [$ [# B2 K( V8 ~' t& r
  110.         /* Send the read ID command */3 k, r6 I' A( e. H' p/ R- m
  111.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        
    2 R8 w  ^$ I) Q3 `% C) h9 S7 M- x
  112.         /* Reception of the data */% P% E) m! W+ ~
  113.         HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE);; v; i2 q& {9 p
  114.         W25Qx_Disable();
    3 R( f( A8 }+ T$ s' P. N6 I
  115.                 2 |1 L" G. S, e& U
  116. }
    0 s  R* [9 N( l" R; P

  117. # ]! [! O0 {8 s# {
  118. /**
    , D0 F9 H0 v  K3 M7 c0 U
  119.   * @brief  Reads an amount of data from the QSPI memory.$ b1 P6 X  {0 U0 Q  W
  120.   * @param  pData: Pointer to data to be read" _3 P" k( K7 `) S* I, x4 u
  121.   * @param  ReadAddr: Read start address, f! h) w4 o5 V5 \
  122.   * @param  Size: Size of data to read   
    - d0 R, J3 [; V9 m5 @. g- P
  123.   * @retval QSPI memory status
    + y( ]2 c5 E" ~0 X! `; ~! O
  124.   */
    : }4 f7 l7 K( K" a% S
  125. uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
    - u% V) T2 G" }! I3 |5 f
  126. {
    . b1 o  a+ x1 X
  127.         uint8_t cmd[4];& a% `- z  \( l% F0 L

  128. 4 C4 ~; ~4 Y+ R7 g7 @
  129.         /* Configure the command */9 b9 D) F, D# k# T: _0 Y9 e
  130.         cmd[0] = READ_CMD;
    9 v! R! b& `; i9 X  ~# K
  131.         cmd[1] = (uint8_t)(ReadAddr >> 16);$ f2 ?1 n4 ~. @/ E! N
  132.         cmd[2] = (uint8_t)(ReadAddr >> 8);
    " T7 C1 c# v3 n, J' |& S/ B* ~) }
  133.         cmd[3] = (uint8_t)(ReadAddr);" n/ l8 ]8 k) Q. C& m+ P
  134.         9 w. V) e! l8 x2 |2 s
  135.         W25Qx_Enable();
    / C% J9 H1 i. S  z
  136.         /* Send the read ID command *// e/ r; I: H; \( f( g* E4 t
  137.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);        4 C  p  K; `) H8 n, r
  138.         /* Reception of the data */
    ; o+ r3 F- ~! Q& g5 F
  139.         if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)2 _" g! e0 R' p; F
  140.   {% W  J+ u" n* [4 G# Y
  141.     return W25Qx_ERROR;, c7 H# M$ ?7 H* Z- s
  142.   }2 v0 z/ k- n$ |4 u
  143.         W25Qx_Disable();
    6 E/ u: M5 D0 G3 h% F7 H; P6 h
  144.         return W25Qx_OK;6 y) a" Z( R7 F4 P" S
  145. }
    ! j7 `0 A  B8 Y

  146. 6 ^5 Z* ^3 }4 }! b6 k: ]
  147. /**
      n; o* m- i: K4 x( e
  148.   * @brief  Writes an amount of data to the QSPI memory.
    $ t1 m  T+ ]8 I
  149.   * @param  pData: Pointer to data to be written
    $ g1 M0 G) _8 _8 H. c# i
  150.   * @param  WriteAddr: Write start address5 m% {0 h4 q1 S5 f1 q6 T% h
  151.   * @param  Size: Size of data to write,No more than 256byte.    3 W" y$ ^4 M- Y9 V5 h  p" v
  152.   * @retval QSPI memory status" K7 @, C# y+ i* w
  153.   */
    ) m& j( `% |8 H% u7 s- U
  154. uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)) g- }% p! ^9 J( E2 Q4 V% S+ H
  155. {
    / K# F0 }$ W$ b8 H
  156.         uint8_t cmd[4];
    / c7 T$ w. x) C$ f- w9 k" u
  157.         uint32_t end_addr, current_size, current_addr;% ], n- W1 N3 M/ R9 I: R
  158.         uint32_t tickstart = HAL_GetTick();1 ^+ j5 _, {' \
  159.         4 V6 W: @: \* I: E- i
  160.         /* Calculation of the size between the write address and the end of the page */. ]' M" h) V3 i2 g% m$ y
  161.   current_addr = 0;
    % [* r4 m) W2 D: _9 ~3 E' H
  162. 2 _5 f' ?3 C4 l- x8 B, ?
  163.   while (current_addr <= WriteAddr)6 o3 \9 h# @) c  H$ a
  164.   {% w* `% w& v: }' X; ~# P3 P& d
  165.     current_addr += W25Q128FV_PAGE_SIZE;- [1 E# k( N. V( r0 N
  166.   }6 a0 N* t$ g/ e4 X6 ^
  167.   current_size = current_addr - WriteAddr;4 |, T8 Z1 Z. e8 E- D; F

  168. 2 _' Z5 m5 k5 D( {0 {  j! b
  169.   /* Check if the size of the data is less than the remaining place in the page */
    . |( x+ \8 z9 x) r  H
  170.   if (current_size > Size)
    - d5 t# D# w1 J% |& Q+ s+ d
  171.   {
    & E' G" L1 s/ j' p8 `: x: x
  172.     current_size = Size;/ O# K7 w4 i& X& d+ w8 _
  173.   }' K/ i! X. e/ n' r
  174. 6 Q3 \: i8 X* P' k; o5 h
  175.   /* Initialize the adress variables */
    . V8 _5 J5 G( s/ q* i
  176.   current_addr = WriteAddr;
    / R7 j% I- f. F% ?, M
  177.   end_addr = WriteAddr + Size;/ P# g0 M4 @, C$ k
  178.         5 P8 i* m. r8 [% @- W6 M  F. g2 u3 S! J
  179.   /* Perform the write page by page */
    1 Y: w; w. J: W+ O7 m8 T
  180.   do8 @1 D) G8 r& e& N. J6 R( T& ]
  181.   {, w# [' j" b( b& Q! W) a- C
  182.                 /* Configure the command */
    1 Z9 w1 w6 }$ x: K/ a; ?
  183.                 cmd[0] = PAGE_PROG_CMD;
    + J- [/ o, N4 F1 e8 A$ o
  184.                 cmd[1] = (uint8_t)(current_addr >> 16);
    ; m5 W6 q0 T) Y  g& A6 C$ k9 m
  185.                 cmd[2] = (uint8_t)(current_addr >> 8);
    ' R% c3 ~* l9 G8 O, z: T
  186.                 cmd[3] = (uint8_t)(current_addr);% L% c) l, e' C$ e
  187. ) u# x0 [$ B. N5 c# p& Z
  188.                 /* Enable write operations */0 R1 L& d/ B4 w& E0 h
  189.                 BSP_W25Qx_WriteEnable();
    3 s1 V; d. S4 U# q6 b4 h# c) i
  190.         
    ; ~+ S* h2 R' ?; S+ b. z! L
  191.                 W25Qx_Enable();: p5 T& |+ g4 w2 R. O
  192.     /* Send the command */
    + J3 n! V+ a, e/ G) ~
  193.     if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK)
    - T8 s, g* |: a- o
  194.     {7 C9 e" `/ Z: g; w( b% P
  195.       return W25Qx_ERROR;
    7 r1 R# l; P1 z* d6 p9 Y
  196.     }
    # e- `  K5 L) T

  197. 2 d4 j5 m9 n& ^8 f# Z7 n
  198.     /* Transmission of the data */' M: H0 |0 G/ R5 r) r: }
  199.     if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)6 o) ^$ O. }6 \% l
  200.     {2 [7 @% i, j$ U
  201.       return W25Qx_ERROR;
    # I$ o+ g0 C7 `" @
  202.     }, ]; D" g* Q- C5 E# E! x1 K
  203.                         W25Qx_Disable();
    - ?9 [  F( Z& }* E: q8 R  h6 Q
  204.             /* Wait the end of Flash writing */1 p1 {. P; `; A- V2 z/ c; C% }& d
  205.                 while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
      ~3 t& L' a' S7 K1 C) B
  206.                 {
    " W3 q8 y# a4 _; N: L3 H0 N
  207.                         /* Check for the Timeout */9 E4 R+ t9 T1 v" N% F, t+ ^
  208.                         if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)5 u. E2 F4 M4 D, j1 t
  209.                         {        
    9 ]9 a; M  {/ _
  210.                                 return W25Qx_TIMEOUT;) G3 p) _  v" k1 g* f- Y0 s+ x
  211.                         }
    : e3 ^* k0 d+ U1 Q
  212.                 }. X% `0 A; }# A5 I, O9 \8 [
  213. . I, o* |8 K; b0 z. c; U  N  w3 @, m# P, `
  214.     /* Update the address and size variables for next page programming */
    7 g+ m; U  B" }$ ~, @3 I) ]
  215.     current_addr += current_size;
    % \' m8 e# u, U. z$ l$ @2 M
  216.     pData += current_size;
    , _0 t& f0 E' w/ f& j; F! J. ]& y* N
  217.     current_size = ((current_addr + W25Q128FV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128FV_PAGE_SIZE;' H& U7 m% [: c* R) V! i6 O, p4 U
  218.   } while (current_addr < end_addr);+ K& J' [+ y( x  }$ z

  219. 2 d& k9 K$ J/ M3 B( V6 M
  220.         
    ! H+ }/ e+ A% J; N  w! O- D
  221.         return W25Qx_OK;
    9 I& Z% Y! s6 A7 E) q* @# b% n
  222. }
    2 o! I& J, @" l* @5 A

  223. 8 j% j3 }; x1 |+ J- X
  224. /**& g" B& f1 k: S
  225.   * @brief  Erases the specified block of the QSPI memory.
      k* Z/ N  Y9 a* @8 c$ G
  226.   * @param  BlockAddress: Block address to erase  
    : M3 V4 C3 p) i3 T* O' X! ]
  227.   * @retval QSPI memory status1 p8 E  i) o( l( U# ?* A+ ~3 ~
  228.   */9 R& \; V8 D9 Z& s
  229. uint8_t BSP_W25Qx_Erase_Block(uint32_t Address)
    0 E& m7 z/ q1 S( C! `6 v0 Z' j. I! k& R
  230. {
    . @$ P; f1 {: v9 {
  231.         uint8_t cmd[4];( N5 ?! y" P' y) ~( H4 j
  232.         uint32_t tickstart = HAL_GetTick();
    3 ?  K, p. s, l( K
  233.         cmd[0] = SECTOR_ERASE_CMD;' k& u$ j+ w# i! H- S, ~# V
  234.         cmd[1] = (uint8_t)(Address >> 16);
    ; C& @5 Y* t: m5 @1 w& \2 x
  235.         cmd[2] = (uint8_t)(Address >> 8);
    ' r8 T: K; G9 c8 k
  236.         cmd[3] = (uint8_t)(Address);
    , f6 d* n9 S4 W+ d5 R
  237.         
    ; g6 m. x' [6 C
  238.         /* Enable write operations */
    4 q2 V6 G5 n0 S% {& g+ j
  239.         BSP_W25Qx_WriteEnable();
    : V1 s. H% z2 L9 L
  240.         
    0 e, P/ b0 \. m$ V9 ]
  241.         /*Select the FLASH: Chip Select low */
    $ y; I7 ~- t$ X+ p7 z6 z0 |
  242.         W25Qx_Enable();
    5 D5 j( d' V) I0 t6 Y3 i6 C. @
  243.         /* Send the read ID command */
    : }. O; B+ r& Q% V7 ]# @
  244.         HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);          f( N2 \. r6 u
  245.         /*Deselect the FLASH: Chip Select high */1 j0 `# j7 f. P3 [
  246.         W25Qx_Disable();$ Y8 I5 Z6 d0 w9 x0 ^$ j
  247.         # V8 N8 s' P. L& Q8 C2 G- ~0 m, Z
  248.         /* Wait the end of Flash writing */, w3 C: c0 i) Q7 b, P
  249.         while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);+ l( l; F, j# l; U; m' Z
  250.         {
    + O( `5 E. M. v6 w
  251.                 /* Check for the Timeout */
    0 y( [# y- t- K+ @- H$ s+ @( L' t& E
  252.     if((HAL_GetTick() - tickstart) > W25Q128FV_SECTOR_ERASE_MAX_TIME)
    0 K) x. C& u' U' O
  253.     {        
    3 y' y* O* x* a% O1 e7 V
  254.                         return W25Qx_TIMEOUT;. h% t/ {' N- m& z! M
  255.     }
    - Y6 G/ O2 R& C- V
  256.         }) R- @. [0 g* k9 M
  257.         return W25Qx_OK;/ F* X2 z2 N: Z! \* H) L
  258. }$ k6 Y+ X- [- T# a, q

  259. & H) g: Z# O; D1 |- {
  260. /**5 \) N' H6 P/ X( v# m1 I
  261.   * @brief  Erases the entire QSPI memory.This function will take a very long time., d) }4 G; v- b2 ^* L' o7 S* M- z
  262.   * @retval QSPI memory status
    4 o0 d, T. ?: K9 |& J7 X
  263.   */
    ; R/ T/ x- E5 o) C, Y' U4 M- f; r
  264. uint8_t BSP_W25Qx_Erase_Chip(void)
    ( e" T; x, e) \5 T/ d
  265. {; }. H: n# Z7 t' V' p& ?/ e+ W
  266.         uint8_t cmd[4];% ]" K" e: V# }. {% H2 ^2 l
  267.         uint32_t tickstart = HAL_GetTick();
    ' s. S3 N% f  J5 ]
  268.         cmd[0] = SECTOR_ERASE_CMD;3 j; L# j1 Z% A3 a0 |. u
  269.         
    % {3 V& N6 ?2 H4 \& }% w& w/ Z6 s6 d
  270.         /* Enable write operations */$ R# P7 {3 S4 o: p) D. k# [
  271.         BSP_W25Qx_WriteEnable();
    - h$ C0 D+ [0 b+ j$ y1 u% F
  272.         3 E" J1 X' B8 |8 F2 k
  273.         /*Select the FLASH: Chip Select low */
    4 I0 G1 Q! u  D) U. E. ], m; K
  274.         W25Qx_Enable();
    7 T4 U% ~% s8 K( R2 q1 A' J, u! t9 l
  275.         /* Send the read ID command */4 H( U/ E- t$ `* f9 n, I
  276.         HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);        
    ' ]# K0 g$ d5 C( ?1 o
  277.         /*Deselect the FLASH: Chip Select high */
    ( {7 l) d. W' }% p- p
  278.         W25Qx_Disable();
    4 a6 Y( p; n* V$ N
  279.         ; R7 G) j& V& G
  280.         /* Wait the end of Flash writing */
    7 u& E+ g" K' S+ d
  281.         while(BSP_W25Qx_GetStatus() != W25Qx_BUSY);
    ' v1 \1 l! b" r# B  N
  282.         {
    : p& k3 U1 H" f
  283.                 /* Check for the Timeout */
    9 y, t6 V$ t+ Q8 S$ ]
  284.     if((HAL_GetTick() - tickstart) > W25Q128FV_BULK_ERASE_MAX_TIME)( z" D1 z& \* c" q7 i0 A( s2 k
  285.     {        # ?/ {; E+ N4 S) ]3 n% [( q
  286.                         return W25Qx_TIMEOUT;
    & k6 v$ {# K0 M2 M% o
  287.     }
    / O  i9 J; B# w
  288.         }
    . h5 t3 {5 ?# I
  289.         return W25Qx_OK;
    + l  s) F0 b8 v! n7 v) S% m! r$ a+ h
  290. }
复制代码

; U3 M3 ~. G6 \8 Z9 yW25Qx.h
- D1 `7 s* B; B7 N, W; Q" s
  1. /*********************************************************************************************************. ~9 E) u& k- F. j
  2. *  ~9 y# w. n' n) S% k- ]
  3. * File                : W25Qx.h
    : T( I3 V5 d! w+ Q  Q3 F* v9 K
  4. * Hardware Environment:
    8 {$ t7 _* e/ p$ n8 s% M
  5. * Build Environment   : RealView MDK-ARM  Version: 5.15
    1 g6 s  ^8 Y3 v4 J4 _0 c
  6. * Version             : V1.0
    & t, }2 v" x9 N: ?) {
  7. * By                  : 8 y/ j' u# Q$ A/ X% B4 u
  8. *
    ' b* c" F' v1 @' n( b. S
  9. *                                  (c) Copyright 2005-2015, WaveShare# W, q' R. J; w( ~% d( ]7 ]
  10. *                                       <a href="http://www.waveshare.net" target="_blank">http://www.waveshare.net</a>0 K+ y5 R5 k! I/ y: s0 ^7 E" ~
  11. *                                          All Rights Reserved( J; c$ w0 x0 B
  12. *
    " I) ?$ g6 _( ^% j" V
  13. *********************************************************************************************************/
      u% X  o% M! i$ y: ^9 y) x
  14. /* Define to prevent recursive inclusion -------------------------------------*/- v- H$ D5 d, R* Y
  15. #ifndef __W25Qx_H6 P; A2 S3 ^$ y2 X4 b# z  _* }  [; j; z  G' ]
  16. #define __W25Qx_H
    ; ~6 C& p1 G- Z3 I  B
  17. $ f+ n+ l* B+ h
  18. #ifdef __cplusplus
    . @% U  U9 F. G0 W# |& z, n  v8 j
  19. extern "C" {
    $ u+ V2 W9 e3 F) M9 \) M
  20. #endif
    . S0 T9 l' B/ D- s% z+ \4 w
  21. ( v0 I! l4 h% Y2 g2 Y$ w0 x8 w
  22. /* Includes ------------------------------------------------------------------*/
    , ?) ]6 |' N+ Z; \. B
  23. #include "stm32f0xx.h", Z5 K$ s  F6 V! x: C
  24. #include "spi.h"( R# n0 ^9 ^% {8 y
  25.          6 m$ m1 p/ u, E7 q7 U6 r4 @9 e
  26. /** @addtogroup BSP- j' k) n/ q( ^, N& @* B
  27.   * @{) J& Z* \6 Z! F; }3 x$ W) ]
  28.   */
    9 t3 |# W# _2 p" O& o6 J$ W

  29. " }- }# q5 u$ A; }1 S0 o
  30. /** @addtogroup Components! B0 |; S. `* T
  31.   * @{; \( C+ k  X; x* z* m4 C( e+ T2 ~( X" m4 E
  32.   */ $ i& z- v1 X3 E; H
  33. : ~0 E  f& Z, t1 T
  34. /** @addtogroup W25Q128FV
    + N6 q  d) h5 _6 R! I( s1 q: a+ H
  35.   * @{
    4 {% D- r. _7 W; s. l0 R* }* {1 k- B
  36.   */
    " I, f# I& Y9 f

  37. + f$ x, w& O0 a( N* Q2 a
  38. /** @defgroup W25Q128FV_Exported_Types; g! l, ^% Y6 [9 G/ i$ _) J' S$ D
  39.   * @{
    , L& _- G9 g, q# y1 S
  40.   */
    1 c5 @; ]" E0 L9 V+ }

  41. % j9 |4 C% R2 _9 R9 ~" v6 S' F( [
  42. /**! m- D+ \6 s7 w# P+ F( D/ h
  43.   * @}
    : b! ~- M* a9 _6 c' d$ F$ `
  44.   */ ( t3 r/ d' `; N8 v
  45.   ~+ D5 F5 g4 d) q, q1 D
  46. /** @defgroup W25Q128FV_Exported_Constants
    + Q/ }+ y/ S+ g6 l3 z
  47.   * @{4 _' i: X2 ^$ s; l. w/ w
  48.   */1 m" M, _# o* b) @

  49. + L. v* ?4 ?  S1 U' X
  50. /**
    7 W2 t0 S7 F+ ^# p
  51.   * @brief  W25Q128FV Configuration  * a* k6 c6 \& }
  52.   */  * _5 [) {, i- b3 _% |
  53. #define W25Q128FV_FLASH_SIZE                  0x1000000 /* 128 MBits => 16MBytes */
    9 U, R4 r1 d- {  u
  54. #define W25Q128FV_SECTOR_SIZE                 0x10000   /* 256 sectors of 64KBytes */
    6 M* N" ^/ I& Y, E. s/ e
  55. #define W25Q128FV_SUBSECTOR_SIZE              0x1000    /* 4096 subsectors of 4kBytes */0 i. _& S" d" w# k4 n2 M8 ]
  56. #define W25Q128FV_PAGE_SIZE                   0x100     /* 65536 pages of 256 bytes */
    / ?. b1 g+ P1 U6 R" F0 i
  57. 3 A$ o7 W: y$ k, A# V
  58. #define W25Q128FV_DUMMY_CYCLES_READ           42 ~$ q7 `2 L. u0 z
  59. #define W25Q128FV_DUMMY_CYCLES_READ_QUAD      108 P+ ]) H6 G& \# {  `# ^
  60. 7 |: d  J. U, G1 y$ p1 S5 {/ Y' }
  61. #define W25Q128FV_BULK_ERASE_MAX_TIME         250000# m' t8 z+ `$ [3 X% I
  62. #define W25Q128FV_SECTOR_ERASE_MAX_TIME       3000
    3 ?6 @' q6 r; w! ^9 `* V: {1 ?
  63. #define W25Q128FV_SUBSECTOR_ERASE_MAX_TIME    800; I! Y- l9 g& j, v/ k7 t% S" b
  64. #define W25Qx_TIMEOUT_VALUE 1000
    9 y5 F* }2 x) t, Y5 h0 B3 J" W6 W5 G

  65. ! x, m, ?* |& `" }( t* Z- t
  66. /**   A5 O0 F- ?- z6 O  _
  67.   * @brief  W25Q128FV Commands  
    # N; P; V. ~( b- e2 R
  68.   */  
    * k, X# ^) d+ V: o! |
  69. /* Reset Operations */
    4 K% q& f4 M' J
  70. #define RESET_ENABLE_CMD                     0x66
    : q$ x) H$ X9 m
  71. #define RESET_MEMORY_CMD                     0x993 D, L, u- {  b7 c1 Q
  72. 5 o9 ^% Z6 z5 C+ @- E( d
  73. #define ENTER_QPI_MODE_CMD                   0x38
    8 i& P; U2 u# E0 c7 B* Y
  74. #define EXIT_QPI_MODE_CMD                    0xFF
    . l8 E' l6 y# ]( y, ]- E/ c1 ^% M' s
  75. 3 V  I, \) t$ C
  76. /* Identification Operations */# z" L; k# w! d% [
  77. #define READ_ID_CMD                          0x906 w# t6 i* C* Q( {1 f, ]) K
  78. #define DUAL_READ_ID_CMD                     0x929 \+ N$ g! k* |3 h
  79. #define QUAD_READ_ID_CMD                     0x94
    , r# F% I" s& D/ ^
  80. #define READ_JEDEC_ID_CMD                    0x9F
    6 R$ n' W& n3 I
  81. 0 E! e; w. R( N
  82. /* Read Operations */
    4 n- s" @# i  e7 I7 v
  83. #define READ_CMD                             0x03
    6 ^7 v  W7 K* G4 t
  84. #define FAST_READ_CMD                        0x0B9 F: p/ C& i( @- Z
  85. #define DUAL_OUT_FAST_READ_CMD               0x3B
    + k% }7 t$ }4 ^+ ], f* }6 I2 n
  86. #define DUAL_INOUT_FAST_READ_CMD             0xBB9 w6 U1 c9 r, i9 {7 g( P
  87. #define QUAD_OUT_FAST_READ_CMD               0x6B
    & p3 _5 y2 K( I+ z+ u
  88. #define QUAD_INOUT_FAST_READ_CMD             0xEB: U6 l/ ~, O- u
  89. : V5 ~3 w% I/ Q  H0 \0 t& Q. C  F
  90. /* Write Operations */% E1 a2 i# T' [& l( C2 G5 e# u2 ^
  91. #define WRITE_ENABLE_CMD                     0x06
    8 B6 m- G! F: `' ]2 |& m0 B
  92. #define WRITE_DISABLE_CMD                    0x04
    2 z0 I6 t$ H- Q4 J0 @. y
  93. : L: b. X2 s1 u" }( x
  94. /* Register Operations */
    1 k  q! I  ^1 R6 n- Q% K4 H0 T
  95. #define READ_STATUS_REG1_CMD                  0x058 }8 u$ w- @" h( r
  96. #define READ_STATUS_REG2_CMD                  0x35/ _) D2 Q5 i( O3 k# m) H
  97. #define READ_STATUS_REG3_CMD                  0x15
    ! l- ~. s0 Q9 e1 `
  98. 3 D0 v7 W3 `$ \' G8 s
  99. #define WRITE_STATUS_REG1_CMD                 0x01
    # Q* u6 w0 F. y
  100. #define WRITE_STATUS_REG2_CMD                 0x31
    2 y2 K$ m+ R4 X# {( [2 H" e2 H6 J7 A
  101. #define WRITE_STATUS_REG3_CMD                 0x11
    , f/ T- U: F  n- e( m
  102. 1 f5 K0 s: R7 s) b, _/ P
  103. 0 u6 G# f4 ?3 g. ]  }
  104. /* Program Operations */
      t/ t1 v( ?$ O% R, A
  105. #define PAGE_PROG_CMD                        0x022 g; `8 T3 G  h0 e6 W9 d
  106. #define QUAD_INPUT_PAGE_PROG_CMD             0x32
    . g5 {+ d& D) ^! a5 c0 Y+ c$ H
  107. 6 E1 c& B3 j# Q5 H1 S% ?$ ?% F1 Y2 t/ j
  108.   h& @+ s/ z! J/ |. f3 I# j
  109. /* Erase Operations */! h9 A+ w# s9 l% R4 N* q2 E
  110. #define SECTOR_ERASE_CMD                     0x20
    1 U5 q* l+ [8 v( J- b" R- A
  111. #define CHIP_ERASE_CMD                       0xC7
    # E/ i1 K* Y4 C5 e, M4 }- r- |: n

  112. " d) K4 r7 ^' ^- |- J, o7 R  N
  113. #define PROG_ERASE_RESUME_CMD                0x7A
    - n0 `: j) J) e! h" t
  114. #define PROG_ERASE_SUSPEND_CMD               0x75; ]6 B% V9 |# ^0 d7 R% l
  115. 2 l* O4 G( X/ ?# T2 H0 l
  116. ) r2 a- h, y! A/ A' P
  117. /* Flag Status Register */2 x  @( Y+ z  o2 o3 {8 e
  118. #define W25Q128FV_FSR_BUSY                    ((uint8_t)0x01)    /*!< busy */5 i0 [  i! {2 ^. k
  119. #define W25Q128FV_FSR_WREN                    ((uint8_t)0x02)    /*!< write enable */) z2 S3 i+ O4 S' @
  120. #define W25Q128FV_FSR_QE                      ((uint8_t)0x02)    /*!< quad enable */, y- f6 O! ^7 o' T  f

  121. - O7 I- p* I# o6 H

  122. + B, G+ ~. D6 e4 |
  123. #define W25Qx_Enable()                         HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET)
    : B: R% f6 o. z( q- x
  124. #define W25Qx_Disable()                 HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET)9 u" S, t6 F3 D% O) ?/ _- z

  125. 2 H  C5 U/ k5 R% A( j2 \4 P
  126. #define W25Qx_OK            ((uint8_t)0x00)
    8 R3 D2 b6 `& Z  g
  127. #define W25Qx_ERROR         ((uint8_t)0x01)
    ' K7 A- v& @- Y$ H% N
  128. #define W25Qx_BUSY          ((uint8_t)0x02)
    0 g" _+ \# D2 [$ H+ U
  129. #define W25Qx_TIMEOUT                                ((uint8_t)0x03)
    ( R8 R% _. M! @2 p

  130. ! ?& \  o* z: V+ R% N

  131. - o4 H! M2 M3 R+ |( m( r5 c6 R/ }) n
  132. uint8_t BSP_W25Qx_Init(void);) ~$ L+ f; h9 {( R! G
  133. static void        BSP_W25Qx_Reset(void);' r4 }5 \" S, E: A0 a
  134. static uint8_t BSP_W25Qx_GetStatus(void);" L! H8 b& V" |5 {/ |
  135. uint8_t BSP_W25Qx_WriteEnable(void);2 e3 z$ b. k( m3 x1 [
  136. void BSP_W25Qx_Read_ID(uint8_t *ID);
    4 Z' q& J( w+ E1 k# v
  137. uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size);5 ^8 B! J7 b0 M+ {$ ]
  138. uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);7 \! X; C; o. r$ _2 h5 O
  139. uint8_t BSP_W25Qx_Erase_Block(uint32_t Address);
    " u$ ?# L* r: Q$ f. ~( {! U/ N
  140. uint8_t BSP_W25Qx_Erase_Chip(void);. _! I& L: _5 }; z* S

  141. , O  Q, w+ m+ K3 G9 Z
  142. /**) i7 H& ?. p" v. D3 }: x
  143.   * @}
    5 l) n8 d5 A  y7 e
  144.   */
    6 P1 u# I) @/ j9 c
  145.   K% s1 J4 o7 i, m0 i9 x) V
  146. /** @defgroup W25Q128FV_Exported_Functions$ g4 P, M2 T1 W  c: W% {
  147.   * @{
      N- M% p9 U$ h6 {: {% u
  148.   */
    9 K; b, b# k2 {9 N" f. i0 E) [. T$ E; d
  149. /**
    * ^3 ]; s! r  O) l' `0 [+ z
  150.   * @}
    % L# W+ D& [5 _# F: t
  151.   */
    1 z5 X: H+ n0 M5 _+ {) y- w% V

  152. 3 i& u, D" {" a+ n
  153. /**' d0 n: H- J) R, Z4 |# Q
  154.   * @}" {" ]# j0 o, D; _
  155.   */
    & a+ @4 O1 c9 a# A: ?

  156. 4 k- c; q4 @- y: `2 W& H! w2 l' f
  157. /**
    ' E1 N$ g# Z$ z/ Y1 y8 i
  158.   * @}. m" r0 e! w7 A3 S. @
  159.   */
    6 S& G! C8 L' g& O5 v/ l/ y

  160. 7 I+ g8 h8 N' K. g% ~7 i7 E# ]$ Q
  161. /**
    4 O2 ~5 V( m7 `& w" M! A3 Y
  162.   * @}
    * H  G" l. C& J' e
  163.   */
    ! r" Y3 }- I4 J7 O4 S, k4 a
  164. 9 ~) K( V% i; f: K
  165. #ifdef __cplusplus
      J" k  o1 X7 [5 ~- Y) V. i* x1 h
  166. }# L, {7 f9 a* N9 j" z
  167. #endif: m/ a+ Q* l- c/ @. i. W8 r6 L
  168. 2 n+ a' A5 R4 n& [! K9 _( Y
  169. #endif /* __W25Qx_H */
复制代码

* E8 r7 E# b3 P) B写好的W25Qx.c放入Src文件夹内,W25Qx.h放入Inc文件夹内,之后需要在keil中加入这2个文件。, Z4 F; {5 J% E0 r9 a5 X8 m% z

) V% Y' \9 ^; F5 X; i: | 20210614164044135.png
* i, {4 O! v2 Y- Y2 {) i$ d, T; c
# E  Y5 t% I# ~$ y- K/ r# y代码

$ W2 u  z& }% O2 N- K% D0 ?本例程向1,2,3扇区中写入数据,并且读取出来,例程代码如下。
8 v4 Q6 d; J$ h% n头文件定义。
  1. /* USER CODE BEGIN Includes */0 j$ m5 m9 Y3 _. K6 X0 u, G$ h
  2. #include "stdio.h"
    - \# Q# y- h8 V6 ^1 d+ z1 w
  3. 3 M# L" y, m- F" j
  4. #include <string.h>
    . B0 x4 m" l7 F- p
  5. #include "W25Qx.h"
    7 ?: s9 N+ ]! C# d# Q/ b% B
  6. /* USER CODE END Includes */
复制代码

8 L  l  U8 H; ?6 O串口接收和flash数组定义。
  a8 O& z0 q' g  h9 v: n7 J3 x# m% g" T: B
  1. /* USER CODE BEGIN PV */
    " }0 x. b3 L9 ^
  2. #define BUFFERSIZE 255           //可以接收的最大字符个数       2 T/ M8 i+ z- r3 G* U# W
  3. uint8_t ReceiveBuff[BUFFERSIZE]; //接收缓冲区/ S0 w3 E& c$ i
  4. uint8_t recv_end_flag = 0,Rx_len;//接收完成中断标志,接收到字符长度
    5 u) y" ]7 k0 l2 e

  5. : g. \. N. @( H# ~& b6 L6 `
  6. uint8_t wData1[0x200];
    1 l3 r( x/ U7 q/ l5 |+ M5 F* d
  7. uint8_t wData2[0x200];; y9 o9 Z# _/ v+ g) z6 c
  8. uint8_t wData3[0x200];" `* g7 w4 Z" @- G

  9. ) g0 |% ?' ]: f
  10. uint8_t rData1[0x200];) }: i# M% e  f+ W# V- ]; h# {
  11. uint8_t rData2[0x200];9 U/ d  h' K# b" s
  12. uint8_t rData3[0x200];
    2 x$ Q: z% P8 `6 E0 t+ A
  13. uint8_t ID[4];
    $ D" q  X* v, k; H4 A7 f
  14. uint32_t i;3 Z4 z, T0 }/ e) ^" Y
  15. * D$ V0 I1 ^% U, t+ z6 T
  16. uint8_t flag[1] ;, X' p9 m) F4 U) o& N. F9 s
  17. int i_flag = 0;
    0 @0 T: C+ I7 @; e
  18. /* USER CODE END PV */
复制代码

" p- y/ L" _& C# {$ p串口重定向。2 z/ L- I) r6 H1 m7 S5 k: I
; k8 t* o. W. c( p% c% g5 b% `
  1. /* USER CODE BEGIN PFP */
    + o: k6 w/ {6 h+ t0 \
  2. void uart1_data(void);                                        //接收函数
    * D" A$ W$ d7 w: t- h
  3. #ifdef __GNUC__                                                                        //串口重定向
    5 O" d; U2 z6 O
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    " V$ D1 z( @7 C
  5. #else8 }! M% N8 [0 c3 I
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    3 `: n2 A! T1 a& L, G- ]
  7. #endif 2 R% h% V/ F+ |+ S
  8. PUTCHAR_PROTOTYPE
    8 r4 z. |: w, o
  9. {
    ( }" z; t. z5 P+ X1 L' I9 C6 z& L
  10.     HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);- m! K( c( x5 p1 W0 \' d! c' ]9 l' h
  11.     return ch;
    8 L6 _% m' O6 q# ^: Q  v
  12. }2 C8 O+ b; }4 C

  13. / ?' t; n2 A/ _, u
  14. /* USER CODE END PFP */
复制代码

; m5 f3 z7 M* k7 m0 r#include "stm32f0xx_it.c"文件中断外部变量引用:
- R2 ^! u9 N9 p* _; G
5 I* K7 U# H; u% E
  1. /* USER CODE BEGIN 0 */4 r/ M5 p2 X; x* u0 X; i) B+ C
  2. #define BUFFERSIZE 255        //可接收的最大数据量4 j  ]9 r% C% y' H+ P! u
  3. extern uint8_t recv_end_flag,Rx_len,bootfirst;; G$ w5 D. L' k7 v3 j
  4. /* USER CODE END 0 */
复制代码

. N# v+ A* _, [/ o5 v+ U- J0 |串口1中断函数:
  k! G: ~+ u; r( M/ ^- y
0 }3 e  S% E9 }$ s- S
  1. /**% T5 v0 b- J6 ^! U8 p7 ^
  2.   * @brief This function handles USART1 global interrupt.
    . r! ]. d4 ^, f2 @& I" k+ ]; X
  3.   */' [' v9 V/ K! v" b* L" o
  4. void USART1_IRQHandler(void); h8 |. [- e3 @; a3 k
  5. {9 W$ `: G; g( p8 l( L2 m
  6.   /* USER CODE BEGIN USART1_IRQn 0 */
    ( z) n! K) J& N# m/ P7 r2 m0 ^

  7. 6 h+ h3 S  X; P4 ~: D+ u
  8.   /* USER CODE END USART1_IRQn 0 */
    9 V; j: V9 @  p' J
  9.   HAL_UART_IRQHandler(&huart1);6 g5 @  _' ]  m8 u3 d) _) w
  10.   /* USER CODE BEGIN USART1_IRQn 1 */6 n" X6 o# F% y8 U9 [) Y
  11.         uint32_t temp;& M2 L. B# K0 H9 Y
  12.         if(USART1 == huart1.Instance)//判断是否为串口1中断' L6 `" B% Y* t$ d# D/ O
  13. ) f8 H1 Y6 p( g5 h& n
  14.         {      4 C& S* F: W1 z% F0 [: X
  15.                 if(RESET != __HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE))//如果为串口1
    $ Q: d" z( T- y& t, ?) W' K
  16.                 {
    1 P- L( ]0 i6 o
  17.                         __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除中断标志1 L7 ?; M" G9 r) ]' t
  18.       HAL_UART_DMAStop(&huart1);//停止DMA接收- j& Y' b5 |3 ]. \# }5 C( f5 S7 J
  19.                      temp  = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);//获取DMA当前还有多少未填充6 N3 t5 b( H. k4 m1 S  q
  20.                       Rx_len =  BUFFERSIZE - temp; //计算串口接收到的数据个数6 E! `2 P; {- }3 {" G0 o6 Y
  21.                       recv_end_flag = 1;2 ]/ y% F& k9 K2 F* w
  22.              }
    8 q! Q$ N6 n( h+ J$ F. v# [! [4 s. g
  23.         }        
    ( V# B, F1 F. U2 A; p
  24.   /* USER CODE END USART1_IRQn 1 */
    ! `7 ?, U% l  ?1 s
  25. }
    - U/ v& i7 z( O$ H# A" p: h9 h
复制代码
" z; V" B# s6 |) o, M( H- g
在main.c函数中,初始化串口和W25Q128。
' t, K5 k' m# [/ B. ]! U
  u3 p. }; c2 r* ~  N9 R! f4 b
  1.   /* USER CODE BEGIN 2 */
    # B1 s7 m+ J$ @' U/ W- g/ l
  2.         printf("串口1DMA例程\n");
    4 E* Q( z; _7 M% o
  3.   __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//使能串口1 IDLE中断 : M4 }+ T7 L: i9 H. l# p6 ]
  4.         
    # U# Z; |6 M5 \
  5.         
    % z  m# T) [' ~! h. [4 g
  6.         
    , t% T. r, ]2 M( L
  7.         
    2 ]- u: v  y9 w
  8.                 printf("\r\n SPI-W25Q128读写\n");
    + f  ?1 n7 }' u0 O) k& c

  9. 3 O1 r7 T0 X: C
  10.         /*##-1- Read the device ID  ########################*/
      l. S8 p# w5 Z$ U8 k! d8 h
  11.         BSP_W25Qx_Init();//初始化W25Q128- v$ i7 R4 J: A, R1 q+ d$ q
  12.         BSP_W25Qx_Read_ID(ID);//读取ID
    & t; F+ @# f4 J* ]
  13. & _4 m; n) X9 y5 v/ a
  14.         if((ID[0] != 0xEF) | (ID[1] != 0x17))# T* ]' u; s5 j0 N- u( J  ^
  15.         {
    * Z! r4 A$ c8 O0 w- e
  16.                 Error_Handler();//如果 ID不对打印错误
    ' z  P5 [' H# l
  17.         }
    1 e0 P$ P8 @7 t
  18.         else//ID正确,打印ID
    1 q9 t% ~& g8 Z; N+ |/ k
  19.         {8 ^8 u- Y9 `, L! g* |4 i, n
  20.                 printf("W25Q128 ID : ");9 X. e# U2 a( c
  21.                 for(i=0;i<2;i++)
    7 P* M  f6 B- U6 K: n. L. R/ t7 Z# a
  22.                 {
    + ]  W$ ]5 O( |* D% C' F/ U
  23.                         printf("0x%02X ",ID<i>);
    6 d/ ]4 l5 r! P; ^6 H$ i# b
  24.                 }
    ! h! j# e/ ?: Q
  25.                 printf("\r\n\r\n");- J0 a7 J$ R; G+ u- }
  26.         }+ L$ G, h& y  H

  27. ) y# v) Z; }& D/ j
  28. /**************************读取第1扇区数据**************************************************************/
    $ d0 {. w5 q9 X' G6 a; v7 Q
  29. 0 z+ h. N  H4 q
  30.         /*##-3- Read the flash     ########################*/   I7 ~$ w! \3 b/ O/ M
  31.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*// M& I; U5 T$ Q
  32.         if(BSP_W25Qx_Read(rData1,0x0,0x200)== W25Qx_OK)0 B: G! l# R1 w7 p: ?! a. y% e" L
  33.                 printf("读取原始的前1个扇区数据成功!\n");7 s( l  E. k0 E7 Z
  34.         else
    " p! {# V3 e( R2 W4 I. z
  35.                 Error_Handler();
    8 `, ~0 }& I5 p' l+ Z  m2 C5 S) `
  36.         /*打印数据*/        
    * ?0 g3 Y6 `, U# x( l/ C
  37.         printf("读取原始的前1个扇区数据为: \r\n");
    & p% [9 }4 `( w# m7 X: v$ P
  38.         / g2 u3 z& y+ O& H
  39.         for(i =0;i<0x200;i++)4 }# z! T2 c% {! j/ K
  40.         {$ x$ r8 p+ V7 j, y" x
  41.                 if(i%20==0). `9 B$ w4 u1 X* s3 a6 y
  42.                         printf("\n1扇区第%d到%d的数据为:\r\n",i,i+19);9 t6 ~* k* }  \) F6 L9 U  b2 z
  43.                                 printf("0x%02X  ",rData1<i>);& w6 @3 x6 K' c5 p
  44.         }' J) e$ e5 D/ g8 m6 {& K9 L3 R1 ]
  45. 9 S8 c5 P* a( y9 k' c# ~2 U- h
  46.         printf("\n");
    + T" D! V5 ?7 v* M7 ?; s

  47. + Y8 I8 y# y$ b, v. p
  48.         8 s" b8 K$ l% w; W+ Y
  49. /**************************读取第2扇区数据**************************************************************/: Z+ Z6 k7 p/ `! _. ^* ]) u% S
  50.           i- m/ d- L' P% Z/ Y7 I
  51.         /*##-3- Read the flash     ########################*/
    5 a# [# U$ r0 D5 u+ g
  52.         /*读取数据,rData读取数据的指针,起始地址0x1000,读取数据长度0x200*/
    8 m* p" X7 g7 e. O, x
  53.         if(BSP_W25Qx_Read(rData2,0x1000,0x200)== W25Qx_OK)
    ! o. u5 o6 s' ^7 ~
  54.                 printf("读取原始的前2个扇区数据成功!\n");
    5 q( \. j. j3 b5 y- j
  55.         else- z, L9 ?- {0 F7 n2 @. y
  56.                 Error_Handler();- @/ B) w7 G0 ^, n
  57.         /*打印数据*/        7 ?2 k0 G- K6 F" `
  58.         printf("读取原始的前2个扇区数据为:");8 B" K" F4 r8 x
  59.         ; C8 ?8 ?' k. t9 H: ~0 `' j$ w  p! }3 W
  60.         for(i =0;i<0x200;i++)
    3 e0 g  M; b/ x8 S+ s
  61.         {
    9 X: F, e# U7 S$ j
  62.                 if(i%20==0)8 u& k7 l: _& N; z) @
  63.                         printf("\n2扇区第%d到%d的数据为:\r\n",i,i+19);
    . l6 f4 W, j0 K& O. `& ^  E
  64.                                 printf("0x%02X  ",rData2<i>);8 t! V/ d! d5 w; D1 \" l
  65.         }, I4 B' @0 v* U) i7 r
  66. 2 C# F( q$ K1 e1 |" f1 X/ e
  67.         printf("\n");        
      X3 u2 J$ w) j. _* C8 u9 i8 p
  68.         
    # X0 u* _& V( J* [& b( o
  69.         
    / `2 K9 Z$ h6 H% n# }& [6 x: W
  70. /**************************读取第3扇区数据**************************************************************/) E) E$ g5 R  ~2 J
  71.         
    6 C  I0 u: D' F5 f; l& I
  72.         /*##-3- Read the flash     ########################*/ " g) m' ^8 G& W& f  }
  73.         /*读取数据,rData读取数据的指针,起始地址0x2000,读取数据长度0x200*/$ O9 [6 i3 r1 W1 N
  74.         if(BSP_W25Qx_Read(rData3,0x2000,0x200)== W25Qx_OK)
    : w" a' j/ ~4 @5 h0 ^
  75.                 printf("读取原始的前3个扇区数据成功!\n");
    0 I2 q( h7 _' n' n/ d" q4 ]) {
  76.         else; n8 M8 h5 ~2 i  c
  77.                 Error_Handler();6 T* R, `& M0 Z3 t$ q- J* ^
  78.         /*打印数据*/        
    9 X4 O8 O6 f# w- o. ?2 n+ h
  79.         printf("读取原始的前3个扇区数据为: ");8 s5 Q+ C% C/ {7 F
  80.         ( v+ P# O, O  d  ^
  81.         for(i =0;i<0x200;i++)
    + i2 c7 Y5 V( K  l7 x, S
  82.         {- \- l) Z- e3 c
  83.                 if(i%20==0)' v% z5 `2 m: z8 j6 s
  84.                         printf("\n3扇区第%d到%d的数据为:\r\n",i,i+19);
    , H1 C7 N6 Q4 Z
  85.                                 printf("0x%02X  ",rData3<i>);6 v9 w* P$ x; G8 e! w' n7 q
  86.         }
      ~- O5 q8 J' o. Z

  87. " d0 E1 b4 [% p" _  e) x
  88.         printf("\n");        1 s& }1 @4 s, R9 G# {
  89.         
    ) |, o# g+ h9 D- @: ~
  90.         ' W/ x9 d! u0 s: A. v
  91. 1 ~1 y* [+ d; ~+ ?" S5 }
  92. /**************************清除第1扇区数据为0**************************************************************/6 A2 Z" ~) ?9 Q- q

  93. ( u# I2 J  |( Q

  94. 4 B  ~) B3 l8 Z* y& A) ^
  95.         
    9 c  ~1 T& r9 e. O
  96.         /*##-2- Erase Block ##################################*/
    4 }6 l1 n- ]! I/ Z( |
  97.         if(BSP_W25Qx_Erase_Block(0) == W25Qx_OK)% Q0 G4 n; q/ ~5 X  B
  98.                 printf(" QSPI Erase Block ok\r\n");
    0 Q9 y& R( o0 m/ `4 I! _3 {
  99.         else4 K# {* U- x, K5 e4 F2 `
  100.                 Error_Handler();. k" H6 c: c2 ^0 L4 ]
  101.         
    3 m9 q0 z9 U, h; q
  102.         /*##-2- Written to the flash ########################*/
    8 u, V& B/ d( T+ W4 [7 V1 {
  103.         /* fill buffer */, T, b8 m- {( Q4 i% K
  104.         printf(" 初始化数据,清零第1扇区前0x200的数据!\r\n");
    2 L3 R% u: V* X0 C9 ~
  105.         for(i =0;i<0x200;i ++)) @4 r+ o, N# O+ R
  106.         {
    7 c# S- k2 Q. `7 }) v* z
  107.                         wData1<i> = 0;
    $ c* ^+ y9 N  o; Q& z5 T  C% L0 e
  108.                   rData1<i> = 0;$ h& x% M( N2 x9 S$ o& e# }* V
  109.         }( E5 A3 ~9 x- R
  110.         /*写入数据,wData写入数据的指针,起始地址0x00,写入数据长度0x200*/3 T- y/ H! q) P* {" a; n0 x; h
  111.         if(BSP_W25Qx_Write(wData1,0x00,0x200)== W25Qx_OK)) u4 H- [6 j1 L2 J% k* |- F; X/ y; F
  112.                 printf("清零第1扇区前0x200的数据成功!\r\n");
    . i* V6 p6 C0 k# p, |: X0 t* |
  113.         else
    7 Q! d. F0 R/ Z' |! f: b
  114.                 Error_Handler();
    - `3 O" U! f& T* b" }

  115. - H( V7 G! N2 K" X) x& T* s  t
  116.         
    ) r- ~* n6 ?+ B! B
  117.         
    5 Y' H9 y& r% B. ?% k4 z; t
  118.         ! l$ C8 [, A/ g& e
  119.         /*##-3- Read the flash     ########################*/ , V# h5 _- M" ]0 U8 W+ L
  120.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/
    " n( m9 b! a) L3 l0 C, l
  121.         if(BSP_W25Qx_Read(rData1,0x00,0x200)== W25Qx_OK)
    5 T( F: `' H# A2 c  H
  122.                 printf("读取第1扇区前0x200数据成功!\r\n\r\n");
    9 R8 e4 N1 {/ F# S  M3 d( u+ |  Z
  123.         else& C( M! U8 a! |& D: W# I* V0 ]
  124.                 Error_Handler();
    3 r. K# @, Y/ Q/ f9 w5 G
  125.         /*打印数据*/        / U8 k2 D4 |% A& y4 N
  126.         printf("读取第1扇区前0x200数据为: \r\n");; x( m' _) W6 i
  127.         . s/ m# `, r1 s( D1 Y
  128.         for(i =0;i<0x200;i++)
    " `# f7 p  F) S% x) ?0 U
  129.         {
    ; i2 `' P% @1 `4 I; Z6 Q
  130.                 if(i%20==0); I) N' R3 u4 T# [! I" ]
  131.                         printf("\n第%d到%d的数据为:\r\n",i,i+19);
    2 K) @$ D$ N$ Y5 Q* x% J
  132.                                 printf("0x%02X  ",rData1<i>);
    7 ]1 X1 m5 ^. [* J& n  ~
  133.         }
    8 L' Y: A, S/ l
  134. , b1 k% b  R$ s% {! y& ~
  135.         printf("\n");
    % I' T. \; s7 M! R) v/ ?
  136. 6 V4 b3 p2 g* u, d  c! q* t
  137. 2 z* a% _% t1 r& W! D& z8 y
  138. /**************************清除第2扇区数据为0**************************************************************/: ~& f7 ^& p5 b% L
  139. 3 J# ^5 [6 w- v% u: ]
  140. 6 J  a0 C) b" d' g+ }2 r7 `# e- Q8 K
  141.         
    - H6 a0 n* r2 M' K: l- ]$ n
  142.         /*##-2- Erase Block ##################################*/
    * I" s8 r: N3 u, @2 b6 v0 W
  143.         if(BSP_W25Qx_Erase_Block(0x1000) == W25Qx_OK)
    ' x- M; U2 o5 _+ A4 Q7 u
  144.                 printf(" QSPI Erase Block ok\r\n");3 e# T- ]7 D, Y, w  ~
  145.         else
    ) }# _/ y2 O, a; Q6 W" i
  146.                 Error_Handler();
    + L; c; T# @$ [  U1 W
  147.         
    ( P$ I# u: _' B) L* X! h
  148.         /*##-2- Written to the flash ########################*/ 5 F3 J0 _) a; m! X& G
  149.         /* fill buffer */8 ^4 s# l/ F( P) g
  150.         printf(" 初始化数据,清零第2扇区前0x200的数据!\r\n");
    / K4 b, D8 w2 s( ~& d  P9 I0 A# X
  151.         for(i =0;i<0x200;i ++), b9 N' ~& A2 o4 o0 b2 y* b
  152.         {; w0 \- C' o: D+ W% U& A
  153.                         wData2<i> = 0;
    0 Q2 ^5 k7 V6 j" e, [! \
  154.                   rData2<i> = 0;
    ( H/ E; D; \3 P# e
  155.         }) b. Z) b/ r! h
  156.         /*写入数据,wData写入数据的指针,起始地址0x1000,写入数据长度0x200*/) Y- e) d6 k4 p8 R2 v( F1 d
  157.         if(BSP_W25Qx_Write(wData2,0x1000,0x200)== W25Qx_OK)
    0 Y4 ^8 X0 i5 Y/ q- B. I' T
  158.                 printf("清零第2扇区前0x200的数据成功!\r\n");3 P( m% }3 H- y. d5 l! y
  159.         else4 A# `, R# t4 P& U/ b! f( N
  160.                 Error_Handler();
    0 V* L5 W8 \$ |/ |6 I

  161. * i$ K/ d8 }4 x) G' P4 T
  162.         
    / v0 [& W. y  U2 @0 `
  163.         
    * v( D, J; H" z; t7 z7 T
  164.         $ Y9 c" T9 `, h6 M) Z( k7 i
  165.         /*##-3- Read the flash     ########################*/
    7 c2 v' c8 j# a) B9 l3 F4 }
  166.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/
    ! t  P1 N# R& L" h# T5 q
  167.         if(BSP_W25Qx_Read(rData2,0x1000,0x200)== W25Qx_OK)5 D' i+ N4 a$ I1 V$ P8 f3 }
  168.                 printf("读取第2扇区前0x200数据成功!\r\n\r\n");' o9 ?& n9 h9 {
  169.         else" U4 _1 Y6 L$ x% c0 S4 J
  170.                 Error_Handler();/ j8 d, W; r5 k
  171.         /*打印数据*/        
    / m* `8 b8 x4 C+ f  r( A  H4 w! E
  172.         printf("读取第2扇区前0x200数据为: \r\n");& J3 u) c; ], l  K4 x+ e6 t
  173.         
    ! F% j4 L$ z: l7 L0 U) H
  174.         for(i =0;i<0x200;i++)
    " D" w1 P4 T9 e8 r
  175.         {
    + U& H) O8 G; d
  176.                 if(i%20==0)# \) Y% S$ J* C  D
  177.                         printf("\n第%d到%d的数据为:\r\n",i,i+19);3 E* e  `+ N. ^1 Y# W
  178.                                 printf("0x%02X  ",rData2<i>);
    4 f( b9 j% Q0 h/ V1 n: F
  179.         }
    , a$ C) X" v( k- d* D

  180. " V0 r. k! _- W6 ?1 l
  181.         printf("\n");
    3 }# f4 N1 E& F6 n5 O$ V
  182. 6 q0 d" P& o6 t% F, t

  183. 1 S, O* Y( C4 u6 k; [& _. O
  184. /**************************清除第3扇区数据为0**************************************************************/. |% B  a1 q2 |- t4 }

  185. ; k' H- m0 |" E, ~
  186. 2 s" s% `2 q! K/ c& F, w1 }% P
  187.         ' L4 O* e! d# _' a$ ^
  188.         /*##-2- Erase Block ##################################*/ 1 h! X' f# q4 ]/ U5 S
  189.         if(BSP_W25Qx_Erase_Block(0x2000) == W25Qx_OK)
    8 z! A! r% S% R6 J, k7 ^
  190.                 printf(" QSPI Erase Block ok\r\n");+ w- ?# B0 V0 H" h2 Y
  191.         else' v7 d# i) v$ \% _
  192.                 Error_Handler();
    2 q3 z) c: y) r; p3 \' E
  193.         + [2 d. @) l8 E' a4 U
  194.         /*##-2- Written to the flash ########################*/ $ H7 H1 E) R9 c; P
  195.         /* fill buffer */
      x( A! ?% V, d; i
  196.         printf(" 初始化数据,清零第3扇区前0x200的数据!\r\n");
    " i5 r& |1 N9 a# x% T* H
  197.         for(i =0;i<0x200;i ++)
    / F: H, q( @! T5 ~- [
  198.         {6 w: V; ?+ d1 L, r3 d/ ?3 N
  199.                         wData3<i> = 0;7 s5 c" A2 c1 \$ D3 c1 N4 C
  200.                   rData3<i> = 0;2 y' Y& p4 L, u9 j% y+ T6 H$ Y
  201.         }
    " k, I" b8 Y7 }* j- G) G
  202.         /*写入数据,wData写入数据的指针,起始地址0x2000,写入数据长度0x200*/9 m# h' F* I4 C
  203.         if(BSP_W25Qx_Write(wData3,0x2000,0x200)== W25Qx_OK)
    $ v$ x7 z" ?. y' H. G3 W
  204.                 printf("清零第3扇区前0x200的数据成功!\r\n");
    ( |& T/ z$ u+ d" Q8 m# ?. t
  205.         else
    ; g/ W8 T# c' Z7 s2 A- _
  206.                 Error_Handler();
    2 y: {) r3 B  p9 b6 G/ D4 y5 r
  207. 4 q: ~6 t8 s, S- t& ]9 p; A& ]
  208.         
    1 n4 e/ f9 r. M" D2 ^0 r- i
  209.         
    , j! {3 u! y* k7 s. c7 Y
  210.         
    & |7 M9 d& c6 m3 z6 \* T5 }: Q9 l7 ^8 u
  211.         /*##-3- Read the flash     ########################*/
    0 d& `* K+ ~& A4 K
  212.         /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/
    * s1 r: P7 A) ]# L0 B
  213.         if(BSP_W25Qx_Read(rData3,0x2000,0x200)== W25Qx_OK)6 N1 K1 ], A* F
  214.                 printf("读取第3扇区前0x200数据成功!\r\n\r\n");( `' i2 g$ {# j+ r8 H
  215.         else
    ; f5 [7 o( }; [; a+ q
  216.                 Error_Handler();6 L% ]. q& T# @& {! `1 n
  217.         /*打印数据*/        4 j6 c" ~* \- w/ T7 z
  218.         printf("读取第3扇区前0x200数据为: \r\n");
    ! Y2 G6 Q: I- M9 C# q6 T
  219.         ( B8 `9 H  ~' I3 Q0 r* D
  220.         for(i =0;i<0x200;i++)
    3 Q" V0 z$ C1 W0 {& P
  221.         {
    + i+ l# n% V8 X# [
  222.                 if(i%20==0)
    3 D; \; P8 x9 G, Y2 K' f
  223.                         printf("\n第%d到%d的数据为:\r\n",i,i+19);
    ' \& ?. L) L4 A% L
  224.                                 printf("0x%02X  ",rData3<i>);
    8 j) K0 x, W7 N
  225.         }
    5 J# G$ z& l0 `; N3 r
  226. % A" @# g' L! }  H8 S8 m' [/ U1 S, W
  227.         printf("\n");% l. M7 d1 {% j) ^6 C, q0 h- U7 p

  228. + A4 v5 i$ J9 n* N, M
  229.         
    # M( l5 A( k# ?) t' j  w
  230.   /* USER CODE END 2 */</i></i></i></i></i></i></i></i></i></i></i></i></i>
复制代码

7 v( x' _0 w+ m# _! N主程序。# k/ K, z# j  [

. H9 ?+ Y- R6 F  E' w6 |
  1.   /* USER CODE BEGIN WHILE */  E# ?+ K$ P9 x2 A; P$ }" \" X& U
  2.   while (1)
    ) T. w/ y5 w  k- o" |
  3.   {
      c9 J1 k, D% b2 N3 g. U
  4.     /* USER CODE END WHILE */* y% ]. q7 O) \; `
  5. 6 `. y  I- A3 d' n# ^+ W$ g( a
  6.     /* USER CODE BEGIN 3 */
    , D; J* p3 V# B! f# W

  7. 8 {+ B9 l7 A9 c- U$ R3 R; G" m- q. b
  8.                 uart1_data();//串口数据处理( c+ \- P' W. m5 s
  9.                 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);+ ?: K  H$ p% D
  10.     HAL_Delay(100);7 z$ R8 ]0 W! k, d4 B: F
  11. / K6 l9 C! \% x
  12.                 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);  \& c: p! }/ ?" o% u- b% B
  13.                 HAL_Delay(100);  v- F+ x. Z. p( \- N
  14. 9 q/ h; p- \% H* Z- O
  15.   }
      u, o6 ?  z: \- v. Y+ x
  16.   /* USER CODE END 3 */
复制代码

6 ?) C$ W0 I3 _$ Z$ x演示效果

5 [9 _4 |, n! m+ i* n4 J7 W+ qW25Q128芯片型号的ID为0XEF17,下方读取为0XEF17,所以读取成功。% g2 O4 H4 R% ^4 ^3 i! V$ I
开机会打印出1,2,3扇区的前0x200个数据,即打印2页的数据。! K9 w* ]& T3 }  r( W- a
2021061412103011.png $ h: a8 B5 h( }
: {) V" q6 B8 }3 D
打印完原始数据之后将数据全部清零,清零完成如下图所示。( H2 t0 ]! \$ u- e8 [) ~

" L) a1 ]0 |8 N+ Q# ?( @4 O7 k1 [' E 20210614121333771.png 5 G& R' u1 p: q4 B
+ ~+ K5 a6 c7 D8 l. _
串口定义了ReceiveBuff[0]的数据为写入什么扇区,ReceiveBuff[0]为1写入扇区1,ReceiveBuff[0]为2写入扇区2,ReceiveBuff[0]为3写入扇区3,若为其他数据,则打印输入错误;ReceiveBuff[1]则为写入的位置。
) x$ ?" p# _" {. t0 i' I输入:01 05 01 02 03 04
' h& Q# z8 P- S7 W# Q" @+ K向扇区1的的05号位置开始写入数据01 02 03 04。  Z5 p/ {% C  z
8 d4 F9 U  O$ T, v
2021061412183641.png " q2 f$ A. I& p8 p/ q

( Q, y% D! S# X6 Y7 @: M2 f输入:01 28 11 12 13 14 15
$ q# @3 T. m$ R: {: R向扇区1的的40(28是十六进制)号位置开始写入数据11 12 13 14 15。
0 h( K' T5 B1 z! W3 y
6 o/ X& N9 N0 L! y6 @ 2021061412202059.png
+ M7 [% |7 p+ o" c' L- d, T
  G# a% J* J  p$ q9 ~. G; i. q3 \: c) ]输入:03 10 aa bb4 ]( Y: t2 U( c; }1 e. O
向扇区3的的16(10是十六进制)号位置开始写入数据aa bb。& b- f6 ?6 H- k
+ V0 I2 A4 v* E+ |
20210614122136429.png
$ k  \) z" v' n; @* Z; K+ f& G3 _# s8 o- [7 |6 v, H( k' b

. N. F4 j1 r& f9 }) M# s; H. I$ H! s( B$ s# H
收藏 评论0 发布时间:2022-4-29 23:31

举报

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