spi概述7 {+ C$ @* p7 U* J0 A
SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议,比如 EEPROM,FLASH,实时时钟,AD转换器。
9 l( n' _+ P$ y2 [( k, OW25Q64 是一款SPI接口的Flash芯片,其存储空间为 64Mbit,相当于8M字节。W25Q64可以支持 SPI 的模式 0 和模式 3,也就是 CPOL=0/CPHA=0 和CPOL=1/CPHA=1 这两种模式。2 b8 Y! H4 k& {. d) N9 s$ \
" z* `8 m9 |8 E* c生成例程3 E; c. W3 T( _, m, c- D
使用STM32CUBEMX生成例程,这里使用NUCLEO-F103RB开发板
) W3 k$ K* F8 A8 Z2 l. s0 {- R2 U! X L5 I- X# h: }, R* ^
& O- L. c" A" J. y# ~( q; u) L
: R) w8 A5 Z _ ~2 C& ]
配置时钟树,配置时钟为64M。0 A; Q* F% y ]2 K' h
9 J5 U( G, P: a$ u- j- q8 e( g
' b) m5 {6 O( z7 x
5 |8 t1 N) v) n" V1 U6 _( n, u
查看原理图,PA2和PA3设置为开发板的串口。
, @0 g" n! o! @4 K t6 z Y$ R" l# i3 u y7 ^3 c
1 q6 q) h0 ^8 F6 R* }* a8 |/ |
! b! z5 ?+ _8 H5 N3 [
配置串口。
" e: A8 E$ H. W+ C% ], k6 A9 x$ Q/ C0 y
( B' Z3 J* A8 w7 o
- F7 N1 U) j: \5 S4 q! N
由于需要输入数据,开启DMA进行接收。
. i2 M( U* h% Q* }/ t
. L7 y' U$ R1 E. D0 G" o8 t9 } ^
1 `3 _0 Q( w! O/ E7 M& y M. H5 l- T4 r- M6 ]7 P- I
中断。. [7 {4 N) O0 h S! r4 `
. I: T2 p2 y$ c3 [
4 s- p' N8 x& n4 k7 X5 M" i- ]: |' W
4 }0 E9 ?+ u' K3 E
SPI配置
" ^+ A1 _& l* G* x) \在开发板中有arduino接口,配置这几个接口为spi。
" P) ~- \3 W5 j" x8 }/ V2 S5 j$ s+ {
% \* K. y6 v) u# B. a$ l4 {. a
& V" a+ {; Z9 X0 N! @9 }( e
6 J9 \$ [) d) b. ]5 f$ s2 R本次实验使用的SPI与Flash通信,配置如下。
( _3 r9 w+ b/ X8 b; ]0 p- S: I7 ySPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。
% W% H9 M9 R6 i6 {8 a(1)MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;) [0 h" T% ?* X) U$ S$ Q5 [6 r
(2)MOSI– Master Output Slave Input,主设备数据输出,从设备数据输入;
( Y/ S; |' O. V4 m2 O8 z(3)SCLK – Serial Clock,时钟信号,由主设备产生;
' f3 W* ~5 v6 |1 O& V; g(4)CS – Chip Select,从设备使能信号,由主设备控制。
0 ~/ T( v& l$ D2 S1 I
0 U. U5 x! C3 }8 V( v
; E; m9 n4 C$ r, Z2 | n; m" D
9 k+ A7 }/ e: c7 m' k0 h. _% P负责通讯的3根线了。通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCLK时钟线存在的原因,由SCLK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。因此,至少需要8次时钟信号的改变(上沿和下沿为一次),才能完成8位数据的传输。
8 J7 r3 Z& i8 {3 h2 ]时钟信号线SCLK只能由主设备控制,从设备不能控制。同样,在一个基于SPI的设备中,至少有一个主设备。这样的传输方式有一个优点,在数据位的传输过程中可以暂停,也就是时钟的周期可以为不等宽,因为时钟线由主设备控制,当没有时钟跳变时,从设备不采集或传送数据。SPI还是一个数据交换协议:因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。芯片集成的SPI串行同步时钟极性和相位可以通过寄存器配置,IO模拟的SPI串行同步时钟需要根据从设备支持的时钟极性和相位来通讯。
* S r7 ^# M( F/ X3 ]* @, n最后,SPI接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据。
) I2 T }# M' l+ T4 }/ E+ k
) t7 r% E+ f' ~2 b
9 k+ [- h( A( \! `- ?' E+ `# h' x& @; d
7 F/ I* A! G. _4 o其中,CS是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个SPI设备成为可能。
" I7 D! h4 v% w* u0 Y1 p7 I& }随便配置一个端口为CS片选,并且命名为CS。 G5 c: {5 R# J0 O5 x$ e
' c* _$ [! _* o+ y3 m% g
- L- F7 j/ r; Q' g& x4 h* x$ I4 P& J1 x4 T7 l+ E/ O$ I$ O8 F2 C
NOR Flash/ D2 \2 O; ]4 Z) v# }4 U
NOR Flash是一种非易失闪存技术,是Intel在1988年创建。是市场上两种主要的非易失闪存技术之一。 ]7 D. I- D7 i$ _
以GD25Q64E为例,该 Flash为64M-bit大小,即8192K-Byte。
8 j% L) H5 p+ V9 y; A! h3 _
|5 k; \3 K- V" w2 D3 X0 M( P
) ]. J$ A3 o; E5 W5 R' E0 Z
0 V$ y9 R. X- }2 v o# }
! m7 j/ c. w+ q8 o; M) k9 A
W25Q64将8M的容量分为127个块(Block),每个块大小为64K字节,每个块又分为16个扇区(Sector),每个扇区4K个字节。W25Q64的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。/ K5 C' H; {# [& ^: T! E+ i
即4K16128=8192K=8M
& [+ Y" X: u7 J' ]& R% B+ U/ ^, s; c- z
8 u3 _8 ] ^5 c
9 Q. K7 s& ]; Q2 s0 B# ?
W25Q64的原理及应用; h* P9 G# r, K* k8 S* g+ [3 n, C
复位初始化4 b% w" n" N8 }
对于复位,需要发送0x66和0x99. }2 R# P. w; I# A0 M* e
1 o. }8 ] U; b
/ q* W% \2 z7 [; M+ l
! R0 a1 @3 {$ U6 S7 i; {& l5 a1 ^; ^代码中的初始化。
1 F1 L/ {* |& l# Z& O- _9 F" |+ i/ u0 R# i2 @
- /* Reset Operations */+ T8 p, l# s8 n7 h1 {4 _
- #define RESET_ENABLE_CMD 0x66: k" E. c7 e+ x! i9 ~) B; b
- #define RESET_MEMORY_CMD 0x99
) R& X4 A6 \" K1 s6 ^" l* f% \, l - /**6 U7 f! x8 x6 c' `/ I5 E L, X
- * @brief Initializes the W25Q128FV interface." g% _, K& W! ~, e! T
- * @retval None
; C! R i4 r5 c: z9 T V - */ o& w+ M$ I% }
- uint8_t BSP_W25Qx_Init(void)3 {$ R: e, j! l2 F- B: K# l
- { + g0 y5 K0 l" C5 R
- /* Reset W25Qxxx */! Y, l' z; I% b( A- V* u
- BSP_W25Qx_Reset();& _+ H) ]% R( d9 Y) U9 w
-
. A# _- ]7 C! u' }. V2 ^ - return BSP_W25Qx_GetStatus();% L2 L; C( }# y( f; B/ G7 E y1 w
- }
2 D1 s$ T, N. A- W+ K - - }( @$ C, `7 B6 i0 L# S
- /**
- _ N* A! i0 @6 [. z0 I - * @brief This function reset the W25Qx.) C2 j3 u4 ?' J' X( M' S
- * @retval None# {; q, k8 Y+ d
- */9 F7 W8 [; f& A& b8 ?
- static void BSP_W25Qx_Reset(void)& B( {* M4 e% F
- {
[) ]9 |4 O+ \7 Y; |+ H; {; A - uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};
7 j [5 P# z* t8 m3 \; S - 2 {: e, I" X+ r% \
- W25Qx_Enable();% b# Q( a% q% n; F! @4 ]4 _
- /* Send the reset command */& J( L h/ n& i; U2 F, N4 h% ]& g! V
- HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE); 4 L, ]) X" K2 B) z! f9 L
- W25Qx_Disable();
' g7 ?4 l. w" D& w5 ]5 z. r
5 G! H: c" i* u) Q- }
复制代码 9 V1 f4 m4 R8 A5 U
; o3 s6 L5 s( w; a9 Z
* t/ E2 l- ]; Q- {5 eID
9 b) f" z/ s# w对于兆易创新W25Q64,主要有三种查询ID方式。5 F6 ^' V- }& Q& [
; f1 H$ I* ]7 Y4 }
- o4 |8 z q _% Z* X; I, X- A. \+ |/ s4 @! I1 z, H* r
可以使用90H查询设备ID,以判断是否是W25Q64设备。
% C+ @ H, _/ w* {- R# j# P8 m
; C* B! j7 p) p$ [+ x; T
1 H3 G L [' |0 p4 x+ Y2 D
- ; b) U' r) G4 ^3 C7 \9 c/ O
- /* Identification Operations */$ M- z7 {# k3 J' G5 j4 E3 k+ q
- #define READ_ID_CMD 0x9F3 ?- i: u" C+ q5 z5 M4 o
- /**, I+ L* A- X6 o- D% ~/ R
- * @brief Read Manufacture/Device ID.
8 ?- I% i3 W( T6 M! L2 \' a7 a - * @param return value address9 K& |' H8 s+ y" G8 h: h
- * @retval None* g! a5 [. W1 ]8 U/ ^- Y
- */% {4 f- n7 O/ C
- void BSP_W25Qx_Read_ID(uint8_t *ID)
0 [ @6 z/ O0 _- n - {
i, ?, d2 ^8 n) K) q - uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};( m0 v+ B/ y! F4 e& j
-
5 V# O6 Y3 Y' q4 l - W25Qx_Enable();! H# b9 b ^5 h- F
- /* Send the read ID command */" f8 _, E4 i5 f! t. Z
- HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);
4 M: H/ p$ V/ G) F" W - /* Reception of the data */* Q* y8 q, R5 g9 ^/ u P$ d
- HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE);
* U/ S+ \6 Z& a - W25Qx_Disable();% b. M8 ^- D9 z: ] ^
- # Z4 P! @2 G+ E, a2 k* S) f
- }
复制代码
* p! z+ e+ _6 I+ }# E
6 p$ ?8 _( a/ U! s5 x
0 K1 _4 T4 T7 K
- I# k( j, ^, f/ f
读取数据
/ `5 z! m$ ]2 A; w. f对于兆易创新W25Q64,读取数据使用0x03指令,后面添加需要读取的数据地址。
( n! ?+ Y! L4 r; g( L数据可以一直进行读取,当不需要读取数据时候将片选CS拉高,关闭时钟SCLK即可。
3 j$ i3 {# o2 @; ^2 B1 }' u9 X I9 M. @2 ]$ P( l
8 a% W6 {! y' q# v) T1 \2 H
7 E v0 [" e7 [6 ~; ?# [
- #define READ_CMD 0x039 p# c; m, I+ o
- 4 X: |9 i* }! d, L) s; P+ z
- /**9 i) T. u- }: l: h2 H
- * @brief Reads an amount of data from the QSPI memory.1 j, F% V+ Q+ I
- * @param pData: Pointer to data to be read/ Y9 e, i. \% q, N
- * @param ReadAddr: Read start address
" r7 T7 O! w! M - * @param Size: Size of data to read $ d1 `8 `$ S- \& j& I
- * @retval QSPI memory status( c' \' n& L/ _
- */0 G6 ]6 }5 S- B6 ~3 W
- uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)5 p8 s2 G& a* n6 Y1 k
- {
6 M+ l1 v7 |5 G$ g! F - uint8_t cmd[4];
+ Q/ E- p: w/ B! a' L% i - ' Q1 x8 b+ {7 S# z6 I4 {
- /* Configure the command */% v9 ?. z1 ^6 v+ k
- cmd[0] = READ_CMD;
, j6 k& m( b. V- h - cmd[1] = (uint8_t)(ReadAddr >> 16);3 [4 ^2 l! I3 b; Z5 \
- cmd[2] = (uint8_t)(ReadAddr >> 8);
% d' u5 q4 j8 [0 [" t) W - cmd[3] = (uint8_t)(ReadAddr);2 H6 t. O/ D( B7 c
- 2 U9 }& w$ S' h! O
- W25Qx_Enable();
/ o A7 r/ ~1 p4 k6 `# ~7 }' ] - /* Send the read ID command */1 @& I* f9 q7 S0 Y" n
- HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE); ! F4 g' w, f; B( d. F8 ]' `; R
- /* Reception of the data */
5 u" n; j/ e" j' r5 I/ H - if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)
" B1 K2 f/ I. ` - {8 O5 r4 r3 I/ A& B7 H
- return W25Qx_ERROR;
/ U( X( N* B! {- x$ U' d; a4 ~( }! M - }+ o4 k4 x* d& \! P- W9 P* r C4 O
- W25Qx_Disable();
2 a/ `7 z0 z L8 \ - return W25Qx_OK;: G: y2 t! C& m
- }9 r- ?9 M: y! P4 M% s
复制代码
# r g' Z- F% H9 e* h' D# w" B, y以读取10个数据为例子,波形如下所示。
0 w$ U1 p3 W) W: Y+ y! x7 S1 ~# c" n$ H$ t/ N: `4 l, C- t
- BSP_W25Qx_Read(rData2,0x1000,0x00a);
复制代码
/ J3 Q. Z' v! C8 i- X
; E$ s0 u& w# ^8 x0 s, V) V- z9 Y E; b7 g! C7 _/ n, y9 ]
擦除扇区
# \! R# z' j* ?+ C最小的擦除单位是扇区,擦除指令为0x20和3字节的地址。
! s2 L8 `+ V. p5 h5 ?1 b$ o8 d O0 a) h6 b* @
w6 K/ O$ y" M7 K) n, H
B+ \8 _: o# J" Y: M- #define SECTOR_ERASE_CMD 0x20& X4 ?% w5 P' `2 O% J9 Z0 i
- uint8_t BSP_W25Qx_Erase_Block(uint32_t Address)/ P( X' x ]8 \
- {3 r4 O/ M4 h6 B- w) H) P% t
- uint8_t cmd[4];4 z6 b% {* t7 b: q2 G( q
- uint32_t tickstart = HAL_GetTick();; _4 n' K8 i0 {, c
- cmd[0] = SECTOR_ERASE_CMD;2 `5 _& P5 N. n, p ]
- cmd[1] = (uint8_t)(Address >> 16);" `! [6 ~5 l# K/ B: J5 H
- cmd[2] = (uint8_t)(Address >> 8);
1 A/ ]9 W6 ~$ m. J - cmd[3] = (uint8_t)(Address);3 a% m7 O* \ N) |) Z% h1 a, J: V }
-
6 W0 S; z2 V2 L: u7 n+ e - /* Enable write operations */: t. w/ W6 |$ @7 J
- BSP_W25Qx_WriteEnable();
/ y- l: e4 s) y" @ -
# w7 V. m" r' S: g2 @' t# r$ q$ w - /*Select the FLASH: Chip Select low */
9 R% T8 c4 D" v' a* _ - W25Qx_Enable();* \3 Z. {+ [) y; D; B/ w5 h0 ]5 u* L
- /* Send the read ID command */
: M7 p5 Z9 p, G7 b. r - HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE); ) }8 |7 j& ?3 B5 u5 R% j5 r0 r
- /*Deselect the FLASH: Chip Select high */
0 {# D% A, o0 \) b/ V# M - W25Qx_Disable();
- Q: ]* g& J8 ?7 p3 S w/ `& O1 S - 7 ]% E( w3 ?: R1 K3 I
- /* Wait the end of Flash writing */' ~9 x& z* X: W) }9 r4 t1 S
- while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);+ I9 S( d% Y. [6 {! m
- {1 S! O) \( k# l7 t! `! F1 ?; a" Q
- /* Check for the Timeout */ z# d0 e3 a+ Z9 _+ Q8 B; v
- if((HAL_GetTick() - tickstart) > W25Q128FV_SECTOR_ERASE_MAX_TIME)- A5 n, Z5 l0 i% ?& N
- { : b6 U. Q" t0 u: v/ ]& ?5 [0 [
- return W25Qx_TIMEOUT;) d, T$ i! Z& @/ }
- }+ S6 R7 ^" W6 z% `% ~
- }" Z" E9 h6 m h0 H; ?
- return W25Qx_OK;6 z5 x8 q# c2 Z" L
- }
复制代码
* W( K1 j$ {+ O! J
1 {/ l1 ]! h& Z1 R& A
) B4 ?: e/ R/ p5 f% b' M7 @& Q
) h% t3 x' \* Z, I+ H: J写数据: C1 `) e4 ?. A& C
对于写数据到flash中,使用0x02指令进行写数据,后面还需要指定24位地址,才能进行写数据。
8 K/ a3 _% ^4 C7 v; i# W' b1 O( U9 J2 H# P# f/ Y2 i! J& Q; \
3 q& x; V* Y# a$ L/ l: R& q" G0 T. R i- ^
- #define PAGE_PROG_CMD 0x02
: f/ X4 Q$ I/ D, B: C' } - /**
$ s U/ J7 s7 o5 D, i Y3 z2 E0 n, g - * @brief Writes an amount of data to the QSPI memory.& [& i7 X3 G( H# k* i
- * @param pData: Pointer to data to be written$ G, g# K( w2 Z, l% `) ] P
- * @param WriteAddr: Write start address1 W, F+ X, I& U* }% J7 k6 `
- * @param Size: Size of data to write,No more than 256byte.
5 P0 I+ d+ T3 H* g* |' J9 u) ]% a - * @retval QSPI memory status
6 q4 }% l( v! }, U - */' H: C5 q. p5 s$ _/ z7 P( k" v. L
- uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
) r2 q- N$ x, O0 G - {
# r1 n3 f1 [2 l1 E - uint8_t cmd[4];/ J: \* o- ]$ ]- k
- uint32_t end_addr, current_size, current_addr;
& U! V# c! s4 {! ? - uint32_t tickstart = HAL_GetTick();
, ~7 d% A3 t6 d' { - 7 l$ q9 G6 @8 @. t- r/ y6 k1 ` j
- /* Calculation of the size between the write address and the end of the page */) b6 y! a) D4 U% p F1 b
- current_addr = 0;+ P! x4 _- p& m) D; N8 g& `
- * K3 D4 f' Z# Z3 K$ [9 S. X
- while (current_addr <= WriteAddr)//判断地址属于哪一扇区开始- F& {7 k! _1 n% {" S+ n
- {: ^) e2 ~9 P" x$ o U
- current_addr += W25Q128FV_PAGE_SIZE;//0x100-> 256 bytes$ f/ R- p: C$ _5 ` v% `6 M' l
- }. V& o1 o9 s9 h
- current_size = current_addr - WriteAddr;
% c' j$ G1 B) n' a8 X
7 p' ~$ B* w+ T/ H! B- /* Check if the size of the data is less than the remaining place in the page */8 A0 o9 l- i2 x# a
- if (current_size > Size)
% A# K+ u5 X0 P+ m0 m - {# N. A! [. U, A ^% E& P: Q- e' p
- current_size = Size;
1 s" i- T5 f |: X1 ]' m/ @$ a) D* Q - }+ d8 q H/ h5 l, h0 U
; Y- F, P5 j, I$ J) |- /* Initialize the adress variables *///写入地址大小范围
$ B3 i- U# V/ F - current_addr = WriteAddr;, c) I @4 O, v& U2 C4 L
- end_addr = WriteAddr + Size;/ K8 p9 n; c) F4 i! ` Z: c/ Q
-
- X, L1 X4 d( [) Q8 m# c/ p - /* Perform the write page by page */4 z8 y6 b2 R# ?6 @6 ~/ a; o
- do" Z+ Z* s% c5 k: Q$ ]5 r& H
- {
4 A, j1 Z" ^) _ E, J% E - /* Configure the command */
+ {# [& M6 M! i& w) R2 L% [ - cmd[0] = PAGE_PROG_CMD;
1 v" G3 ?! m4 _( o* r: z& r - cmd[1] = (uint8_t)(current_addr >> 16);( \9 c1 E- S) \5 i) V7 o
- cmd[2] = (uint8_t)(current_addr >> 8);# K1 [* U1 }, s2 a
- cmd[3] = (uint8_t)(current_addr);
# W' N) ^& P7 Y0 }1 d. F1 A+ I
) |7 E; A+ l6 S9 M- /* Enable write operations */
2 F# O" U4 F& p* F2 g - BSP_W25Qx_WriteEnable();) S3 c7 ^! x# V: j& A
- : W, B& ]: A j0 [$ N. p
- W25Qx_Enable();; o0 L1 P0 s' w2 j! N' _6 g* D& m# s4 `
- /* Send the command */
' [% s) q+ R# g+ w/ U7 V - if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK); m* Q, m {3 W5 N; u( V
- {, v4 o9 B- R9 X4 f
- return W25Qx_ERROR;
' a; F: t0 w5 I* c+ V# ~ y - } T3 A$ @6 C" T" ^/ e
+ c$ T$ U" U+ s+ v! U/ T- /* Transmission of the data */' l9 C2 N4 V6 r+ i9 v
- if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)
5 ~0 l9 W. n3 g1 ^% Z+ y - {
4 r y( S$ o) g! B& V - return W25Qx_ERROR; ?: l6 y) L- s5 m# f
- }+ D8 o' W" |* V; f5 f
- W25Qx_Disable();
4 V% o- ?# N& C1 {& b( C6 E - /* Wait the end of Flash writing */, Q- L8 F4 b4 [4 I3 N
- while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
( h8 v7 ~4 j# Q. U5 a* P' c2 q - {
) l D1 V, F) [% ~2 h6 o; H - /* Check for the Timeout */
8 ]* ?. R' |: H+ ]: R: e& e9 h - if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)
8 W9 l6 e% a0 k& y" S d. o8 u7 f - { 7 r6 C6 G; ~ R7 }
- return W25Qx_TIMEOUT;6 Q0 e6 |8 |& m Y9 ]
- }
|9 Z9 M/ q- Q+ T - } \8 l. L$ h# m
' S6 S; I3 i! w: D- /* Update the address and size variables for next page programming *// L l: e$ u0 t& j% B& q4 J8 l E
- current_addr += current_size;, p% K! \2 I0 w" D% N4 o& z
- pData += current_size;
5 {( B9 R8 F3 x, p; ^1 U' P0 r/ n - current_size = ((current_addr + W25Q128FV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128FV_PAGE_SIZE;
+ h: u0 c: o! E$ _) T - } while (current_addr < end_addr);
m& V0 r" X" } - ; M/ U' o- V& |$ y
-
. I4 n( U* e6 g - return W25Qx_OK;: N! `6 l7 v- r( h
- }
复制代码 ( o" q( _# R) l- R4 |+ Y0 H
对flash的0x1000地址进行写数据,指令如下。. F0 W& K# l0 v7 P( @
' D/ d3 d( o) {7 {' v- BSP_W25Qx_Write(wData2,0x1000,0x000a);
复制代码
! A D/ V$ G0 ~& A6 i" @波形如下所示。
% g+ z) w; ~/ z/ t; R& x7 U: _6 X0 q
* B2 N8 o+ F4 ~* ~, E1 g
2 A& Y7 @. Q; x8 h5 \+ \W25Qx.c9 ~6 t! x$ X" P7 {( k# l6 ]
- /*********************************************************************************************************
. m9 K. H, s& F: { - *
. j( N" E U4 B. n1 o - * File : ws_W25Qx.c( b X4 b T. u1 g/ Z6 M
- * Hardware Environment:
; u" _4 t: u# c7 B- G/ g* ` - * Build Environment : RealView MDK-ARM Version: 4.203 L1 Z: t! R* h, c* |
- * Version : V1.0
# | O8 [6 J9 o3 \ - * By :
6 f3 ^/ [. ?7 H( q5 |% m+ s - *2 u% X* s0 T7 j! N
- * (c) Copyright 2005-2011, WaveShare
' |. }- q( [% m4 _ - * <a href="http://www.waveshare.net" target="_blank">http://www.waveshare.net</a>- q; V- k& K& c6 g
- * All Rights Reserved+ j3 Y! W4 C( Q M7 {
- *, d: t& p9 }, A8 k* |
- *********************************************************************************************************/8 Y' @7 Q7 A8 ~: o7 J
- / X) j- J! m+ \; {
- #include "W25Qx.h"4 \2 z& o9 y/ Q( L+ y% H. l: ~
- B# C; n3 @6 p$ Z' S' v* Q- /**. K! [, ?: K# B: w/ N1 |
- * @brief Initializes the W25Q128FV interface.
& T! }9 u& b0 L" N+ W' J - * @retval None
/ y$ D X) ?; }/ L3 i5 ]/ ` - */" N% {+ O& [. B9 c1 x3 } X
- uint8_t BSP_W25Qx_Init(void)
0 B; H. U b7 c/ K: v) i - {
7 x; J( [. s' c) I g& W3 x - /* Reset W25Qxxx */
9 k- Z& i( b3 z- h( ^/ D - BSP_W25Qx_Reset();
7 x& c+ G4 P; ^ -
E7 x4 O, ]' n0 J( F# ~ - return BSP_W25Qx_GetStatus();- W# u, W7 x) t: Y$ ^& I
- }" y4 T& \8 r0 t
* p; k5 S; S9 C% f9 \- /**2 Z/ P0 N0 V: k o
- * @brief This function reset the W25Qx.
) l1 z2 X, H' a( |5 M2 A ^3 \ - * @retval None0 X& {8 A" o1 n) n9 w( A
- */
4 g4 j1 x9 _9 g3 H - static void BSP_W25Qx_Reset(void)
3 T! j6 F, j1 M# f7 V" W! G - {- M; ?% P$ e2 p7 N7 _5 o
- uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};
8 b; @) F2 d) u5 @ - ; Z3 h$ i8 E5 u2 u0 q( v% S3 Z& G% H, H
- W25Qx_Enable();
% F; S8 @1 @( m. x2 s. ] - /* Send the reset command */" ? c3 a; C5 i3 T% q9 h% k
- HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE); R. r1 \. f' D2 B& l- ]9 L* ~
- W25Qx_Disable();
$ m7 }3 a& u; W, @1 {
, Z" h" T' O5 u- }- H( q L3 v+ L' I1 y5 |
- , K0 ^/ ]6 d3 l
- /**
1 K5 i' X, g) o1 a# W7 K8 D0 _ l - * @brief Reads current status of the W25Q128FV., ^3 ^; d! w5 ^* z1 L+ P% G& s
- * @retval W25Q128FV memory status: D4 g# A- c0 ^4 Z* c% u
- */* x# g3 T" A5 N& q& Q' L4 F
- static uint8_t BSP_W25Qx_GetStatus(void)" O8 W, {% @% U$ e! N b3 N; u
- {; P5 C+ l8 l- R, m3 A3 j
- uint8_t cmd[] = {READ_STATUS_REG1_CMD};
" Y( q: _/ |3 U- B7 y# I2 [! y' [6 f - uint8_t status;
/ r1 S6 C: x" U -
; U* \3 D1 q2 o- g: |8 Z0 m - W25Qx_Enable();: l# q0 i: _! x6 i; s3 l9 u
- /* Send the read status command */5 `, X6 }% ~6 A# _
- HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);
7 G% i* C$ j# f6 F) Q - /* Reception of the data */: m% h/ ~- F! Z( a, ]
- HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE);4 w" S0 M" H/ G' t& q5 I- `1 X
- W25Qx_Disable();8 y0 J4 T. y- n; o$ k
-
- o- ? A- K# r( z% g - /* Check the value of the register */
( N& ]/ h+ c) O - if((status & W25Q128FV_FSR_BUSY) != 0)
7 s- E; j3 a. ?7 B$ M - {
0 X/ \( L+ |2 a' s. l/ b7 C - return W25Qx_BUSY;- I! x- O9 M& \& t
- }' t9 t+ V# v9 b/ M+ Z5 r
- else
: W! i# R" p" m" L. |$ w9 P - {& T9 I+ e7 N; k/ S2 S
- return W25Qx_OK;# v& t/ v7 c) k' \3 ] @" I0 @
- } 4 w0 o2 k( s( H& m* T: [
- }
+ {8 y* a% h6 H% ?6 V( ? - 6 O% {* S; s% h5 y
- /**
; P, q1 ^; r% h( Y - * @brief This function send a Write Enable and wait it is effective.
+ b2 W( Q2 l8 e1 o' v - * @retval None
% y$ z$ z* A# V# q( [- ? - */
& Y. O) ^; X( n" z2 r9 K3 p( h - uint8_t BSP_W25Qx_WriteEnable(void)$ U, b3 f2 r+ Z3 B& v! }3 M
- {
( Y& C4 a- Z$ x5 i6 `* y - uint8_t cmd[] = {WRITE_ENABLE_CMD};
. F& W; O# ?6 [0 U7 B6 b( _/ X - uint32_t tickstart = HAL_GetTick();
X- i; p' [ a+ S& V. w! \ - 3 T- ]; }- Q3 b
- /*Select the FLASH: Chip Select low */
2 M3 S4 d1 D: B4 [7 N& Y - W25Qx_Enable();
2 u0 H. s# h; P4 x: M" ]2 k1 k - /* Send the read ID command */
" S1 z! H. W# I( @: k# H - HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);
/ L1 l# T3 G" x - /*Deselect the FLASH: Chip Select high */' ^6 }$ J2 P; H7 S7 C" P1 |
- W25Qx_Disable();# X" n9 k9 Z X9 x- ~: n' p2 B+ I
- % v! h2 Y' t% ^+ O: o
- /* Wait the end of Flash writing */* }4 }4 f$ M% d2 P: h& `8 M
- while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
; ~ {+ f5 g9 z1 W c - {; k! h U0 C1 e% G5 ^; B
- /* Check for the Timeout */
$ X& }% J2 i9 N3 X* i - if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)$ R5 ]6 n& g5 T9 n3 d e
- { 9 |4 e2 ?% c* v$ N. X6 @
- return W25Qx_TIMEOUT;' w7 P F. @: K+ y, v
- }# R9 V- ^+ H: \ R; [- z5 h6 @
- }6 w1 s8 k( o* m6 Q$ q
- $ T. w' w6 H1 c( p" S6 ?; b
- return W25Qx_OK;
' j! Z6 r0 D: O5 \: ` - }
/ T# M2 h" ^0 j8 E. j( l& z8 i/ c
6 p+ t3 L8 {$ d- /**; i, o* f l- K: y
- * @brief Read Manufacture/Device ID. e6 a" L5 k3 |: c, c
- * @param return value address
8 P, J1 }" U; w6 V0 y4 r - * @retval None
2 j3 S6 P6 e' m" Z) G% D5 B - */
& k- C+ }4 W: d {3 r+ c, S6 ^8 } - void BSP_W25Qx_Read_ID(uint8_t *ID)
D- ?1 u( S* P' n4 E: v0 n - {
2 h2 o, u7 ^. H! ^* m1 X! E - uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};
: o+ Q( }1 L$ G7 }# g% u; I# } -
1 C! A/ b: k6 ?& } - W25Qx_Enable();$ w" h t: a/ c; U+ U4 w5 l$ ?) f/ z
- /* Send the read ID command */
! S/ F- j7 x# o- ^! N% g! I - HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);
' U4 @1 Y" \- w, ^0 s |& P2 c - /* Reception of the data */" G2 Y$ \& i1 {" \0 q0 P
- HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE);! ~9 {7 c ?# w0 t
- W25Qx_Disable();$ ^+ ?+ F: Q8 H7 ]% v' y9 d
- ! v9 c K4 T2 f
- }+ q" p2 L, {# b
- 4 ]+ b$ {$ ~6 I8 \
- /**) p* F; c& ]$ j& J
- * @brief Reads an amount of data from the QSPI memory.! H* s* y4 Q* k7 {
- * @param pData: Pointer to data to be read( w5 ]* \4 L4 t4 Q- [
- * @param ReadAddr: Read start address
- V7 B0 p$ d9 D! N: r2 ] - * @param Size: Size of data to read
u9 Z5 X- `5 u4 u, O - * @retval QSPI memory status9 h7 S+ D; T/ _( [
- */
; e- V2 e! ?- F( L - uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)- w: n& w- a, J
- {
4 j4 {& @ N( | - uint8_t cmd[4];0 u9 F/ P& w& _3 k& D" ~3 ?- V' i! J
- 1 ~7 L2 R) ~# F$ y6 R' F5 e
- /* Configure the command */
, i& e, y: N9 t - cmd[0] = READ_CMD;
! e& Q' R5 y! `3 Y; Q9 J- a - cmd[1] = (uint8_t)(ReadAddr >> 16);
$ ?! Y7 c p2 r# h) r" Q3 G - cmd[2] = (uint8_t)(ReadAddr >> 8);
8 ?, Z! U* D' T! i - cmd[3] = (uint8_t)(ReadAddr);5 L u+ Z2 A- m p0 @6 m
-
5 W, q: _. v, s - W25Qx_Enable();) j; J8 M5 B. l" z' P. ~
- /* Send the read ID command */
0 J* q) \7 o7 y' |8 {4 }! q - HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);
6 @6 v, t; b5 t, V3 c. K - /* Reception of the data */
- Y7 Z/ M- Z, r! K* T# C; N0 O - if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)$ e9 F! e. W; p) u. c& m3 L' D
- {- c2 P: r1 S1 [$ M8 G, q- W
- return W25Qx_ERROR;6 H3 o9 d! ^& {% k% k5 A, V: N
- }6 y. R7 @/ P( D" t/ c
- W25Qx_Disable();
y( z& o& M0 J0 G7 r0 t - return W25Qx_OK;5 l3 c3 t# U7 \1 }. d. _: Z7 u v. s
- }* y- K1 z. f) r4 a
3 U2 G6 v2 x% Y* y% ~+ |( y- /**
8 L }" K+ {, Y# Y# O" m - * @brief Writes an amount of data to the QSPI memory.; d& e# \: U4 P) z
- * @param pData: Pointer to data to be written
5 ~2 p& V/ v9 Z9 x1 e, \- e - * @param WriteAddr: Write start address
1 V% b" E, V0 R8 e - * @param Size: Size of data to write,No more than 256byte.
! ]- \3 _; L: ~$ t g/ A - * @retval QSPI memory status. w! i6 d3 x, `- E% A; O
- */
$ n- [' ]6 C* b) v- v) | U1 @- i$ Z - uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
; n5 ]9 ~0 m7 C% d' _ - {$ g/ m$ D" D- l
- uint8_t cmd[4];
) r' X- i, ^: n - uint32_t end_addr, current_size, current_addr;# ?' `2 K& |6 N
- uint32_t tickstart = HAL_GetTick();
z* P" D: T& [4 O' _ - % g* z- b# Y: K5 R4 \
- /* Calculation of the size between the write address and the end of the page */
+ p5 R! q* N" a4 F, d' W1 F" O - current_addr = 0;
9 ?' W' I6 h( U5 z6 p, I! C4 N - " F$ g, Z- s) V8 S0 s
- while (current_addr <= WriteAddr)//判断地址属于哪一扇区开始/ L/ ^* T$ W7 V0 _! b
- {
7 o, X0 [) \4 J) }( N - current_addr += W25Q128FV_PAGE_SIZE;//0x100-> 256 bytes1 p# r6 F8 G6 X j h
- }
7 J. R: c/ I- x8 ]$ X - current_size = current_addr - WriteAddr;( J8 F% m: }8 I+ O+ z1 b5 A
& D$ \0 F) r- u- /* Check if the size of the data is less than the remaining place in the page */
$ x% k/ d( Y- { - if (current_size > Size)0 L4 b2 `, l) m7 k1 Q
- {
K8 z, H" M( q# Q$ L5 a d- d. o' s - current_size = Size;
; N3 X3 J$ M" m5 D - }
" w& L( W" U( L) ]& n - & n, V/ t0 z" i R
- /* Initialize the adress variables *///写入地址大小范围
4 y. L1 q3 `: t1 i" d _ - current_addr = WriteAddr;8 v6 P" E9 a+ z
- end_addr = WriteAddr + Size;
( Q5 o2 n i2 }! Z -
* [, t0 Y, F5 \, M$ [' _ - /* Perform the write page by page */7 c4 r7 K* G$ y" S, }
- do2 K3 ^! ?# h) p+ V) G, ?3 \
- {# w: U7 o) y( E, q4 b3 S$ M
- /* Configure the command */
9 O5 D K' T! ?" I$ u( G Z1 `5 x: M3 U - cmd[0] = PAGE_PROG_CMD;
) ~* E/ @9 |( ? X! c7 k6 q - cmd[1] = (uint8_t)(current_addr >> 16);1 Y0 A7 ]( a* n6 m- N, u
- cmd[2] = (uint8_t)(current_addr >> 8);
0 ]& F& ]6 a* R/ ^9 x1 S4 M - cmd[3] = (uint8_t)(current_addr);
8 _% O- D/ O3 a1 m2 Y/ [6 y - ! ^! b& Q2 N& ^4 O
- /* Enable write operations */
' Z% U+ u$ J# [3 x0 o - BSP_W25Qx_WriteEnable();% _* x; ]7 h) W
-
1 D7 N; h$ L: P/ \ - W25Qx_Enable();6 e+ ~+ w$ R" F9 k% H
- /* Send the command */3 `! V9 [- M0 J
- if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK)7 Z1 ?) @3 @# a" H
- {
; A6 [& W- N# l; d - return W25Qx_ERROR;
1 [3 m4 H5 `* w, a - }
. Y; C/ Z7 P, F
' f: g) s: `2 j- /* Transmission of the data */
% Z7 B/ y6 d8 y. t) r+ t, G% N* z+ q: @ - if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)& Y' Q4 l1 g% Y' F8 f' D! q
- {
0 O$ {: a( k' j; n- H1 T- \ - return W25Qx_ERROR;
" H% X% m9 y/ X - }( `. k$ t; D! P9 ^, u7 r- I" Z
- W25Qx_Disable();% \! e5 Q' V4 ?) K6 ]
- /* Wait the end of Flash writing */
, v; h# K6 B; ]' @, r0 y. M/ M+ _' J* m - while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);( G' x* M: p' c1 z; j" ], h/ M
- {( l: Q3 K* V4 ?3 W9 J9 I
- /* Check for the Timeout */) T6 o8 N. ~2 n; f- w( O8 S
- if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)8 t6 {6 w, x* p/ `- o1 n" u* o. ~
- {
8 x2 x8 w, H8 Q3 } b - return W25Qx_TIMEOUT; k0 d8 i! R* g$ ] K; m
- }* U1 ^ \* v! V) D5 m9 {" ?
- }. z& |+ X4 F8 F1 F* q/ `8 J4 R
- % y6 G9 h7 Z t
- /* Update the address and size variables for next page programming */
4 y* ^, \3 S5 b* j: l - current_addr += current_size;
) w5 p4 o& M; S# k4 u4 B7 S - pData += current_size;
* I+ o6 ?1 ^ V6 O; T - current_size = ((current_addr + W25Q128FV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q128FV_PAGE_SIZE;
& Z8 G& `/ b. O: p: _ - } while (current_addr < end_addr);
* C; ~8 r3 y& `* X1 j - 9 p9 `% A% j& B8 N! Z) ]
-
* b9 O0 s+ V* l. T' ~6 e: J! ^ - return W25Qx_OK;. o* b K* x6 V+ c" }. g* v1 G8 P
- }5 n9 l3 {7 ^/ J/ r3 n4 r1 {1 w( B
; d* @& K3 d* ]" F+ Z; `- /**
" v2 {0 `6 W/ [4 M/ r - * @brief Erases the specified block of the QSPI memory.
& v! O; b; e$ W1 _; r - * @param BlockAddress: Block address to erase
0 O: l* K; e1 ^* r! H. x - * @retval QSPI memory status
, T' ~% i2 c2 z8 T - */
& \/ E' Y/ S7 Z; n3 U% [ - uint8_t BSP_W25Qx_Erase_Block(uint32_t Address), U/ B" S0 X$ M: I
- {: N( ^8 L' d; {: ^
- uint8_t cmd[4];( V2 X5 Q. i# ?7 p
- uint32_t tickstart = HAL_GetTick();% _8 o' K; R5 M
- cmd[0] = SECTOR_ERASE_CMD;- b8 v$ w# @. Y2 Z
- cmd[1] = (uint8_t)(Address >> 16);
+ O3 N! L8 ~; O+ p, C; I0 c - cmd[2] = (uint8_t)(Address >> 8);
: O3 i# u: l$ e- l - cmd[3] = (uint8_t)(Address);7 G7 b1 K: c. d% C* U
- $ ^" g! o# Y7 X+ M4 ~9 Z5 y
- /* Enable write operations *// l9 h7 }( p7 h5 y+ S, m
- // BSP_W25Qx_WriteEnable();2 a8 r2 _) j* Q8 [1 c% J; ?( D
-
* s" A _7 `' N0 j' c* Q - /*Select the FLASH: Chip Select low */
+ g# o# Q' u! {7 T" g - W25Qx_Enable();
7 q3 S' m* o1 [; q- T! T! R& Z+ Q - /* Send the read ID command */$ s+ X0 `6 Z1 ]( l' s2 U
- HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE); * E# C0 k+ O5 Q1 {8 a; J
- /*Deselect the FLASH: Chip Select high */
! q& S# a1 U7 C+ }9 l - W25Qx_Disable();7 F0 \. W! v/ ]; Q/ L+ c
-
4 w6 t* U s" p. }6 [/ B - /* Wait the end of Flash writing */3 Y4 T: K6 g/ ^
- while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
7 V0 ~! I3 c# v5 C1 s9 i4 A# }" f - {
! ]) X8 Z* ^5 z# g+ X3 [: U! f - /* Check for the Timeout */
" a: t) b9 L+ v% B9 V& I$ j, a - if((HAL_GetTick() - tickstart) > W25Q128FV_SECTOR_ERASE_MAX_TIME)6 v' t. t0 v5 ]5 C; b
- {
7 j2 S) n9 }- c- U; N! F j& x - return W25Qx_TIMEOUT;4 b5 M/ [: f+ U& s
- }7 b; A" H" R3 d( J: A+ F
- }, z% {; d4 q- N8 Y* x2 j. n
- return W25Qx_OK;+ t! p' X7 q" Z5 a
- }: ^% E ?2 P% w6 Q7 x! t/ z" [
- - p- q/ @* b! L8 I1 ^
- /**. s* z( J- F' q/ o3 F
- * @brief Erases the entire QSPI memory.This function will take a very long time.
5 ~% h$ @/ H! N3 ], ^( h - * @retval QSPI memory status
" P3 T) {: P, d0 a. g; { - */+ H5 m7 a" @, H S% s& G" R
- uint8_t BSP_W25Qx_Erase_Chip(void)
. k7 S# a& Q( @1 F. V% { - {
5 s4 Y. V4 ]' l- o. v3 @6 |" { - uint8_t cmd[4];, K5 `/ i7 d- J: Z! D7 p6 L
- uint32_t tickstart = HAL_GetTick();
! W3 t( q" l' d' n1 B6 l& I - cmd[0] = SECTOR_ERASE_CMD;
, f% ~$ b1 q6 [3 G! f2 g, K -
; R* V' q2 s- P2 M6 q8 A - /* Enable write operations */
7 [* a$ t% I6 G - BSP_W25Qx_WriteEnable();2 W2 e. a8 j& S- J/ x7 l5 J
-
! H/ T0 {3 s- H$ K+ v - /*Select the FLASH: Chip Select low */
/ j S U1 f$ D; M! i - W25Qx_Enable();
7 S. R E: ?* t1 S5 O - /* Send the read ID command */
$ E$ A' ^0 R, h' { - HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE); 2 K* F8 j3 P) y! m& i3 G
- /*Deselect the FLASH: Chip Select high */
) j6 B( f! h' V7 F; N- {0 M - W25Qx_Disable();
! j( y& P1 x$ n! f: S8 J* K -
+ X, v3 M' y% ]! P* J# d2 c - /* Wait the end of Flash writing */
& u: h- F6 j' i! l# D# Q - while(BSP_W25Qx_GetStatus() != W25Qx_BUSY);
; p& C L( n3 b# Q - {
3 B$ X9 _, ` X5 V8 ~8 W { - /* Check for the Timeout *// Q3 n3 V. Q @' r( G, R
- if((HAL_GetTick() - tickstart) > W25Q128FV_BULK_ERASE_MAX_TIME)
6 [* j) K3 ^5 ?; j0 W; k- @1 ? - { ( m* g1 H2 r; c7 c
- return W25Qx_TIMEOUT;: G: g9 Q1 D/ G4 Y+ N1 T% h
- }
; E' b6 w7 {$ Y4 p: o - }
# L! c( B4 `! X5 Y2 i* ` - return W25Qx_OK;4 w5 [6 E R$ g& t% v; v
- }- v: S' _" Q8 X6 P
复制代码
& P8 d' ^: ? F8 uW25Qx.h
# E! J4 @. E$ X. R4 [" D- /*********************************************************************************************************
; F8 n' f7 x4 B% k0 X3 g0 } - *
5 q9 W& X+ O `: ?4 W - * File : W25Qx.h* r0 b) F* q, r1 f1 d
- * Hardware Environment:
: w! a; a6 h4 O% W/ l/ \ - * Build Environment : RealView MDK-ARM Version: 5.15$ h' M: I& F2 I+ B5 w7 L) ~
- * Version : V1.0
1 N' r o/ \$ x7 o - * By : ) d/ E1 N4 A2 _) ?. q
- *
- v$ M( J4 |$ P3 ~, |% Y; ~ M - * (c) Copyright 2005-2015, WaveShare
. v6 E/ t7 U. {4 @ - * <a href="http://www.waveshare.net" target="_blank">http://www.waveshare.net</a>1 _ x. D k! V
- * All Rights Reserved
1 U& J. H# C: N* P - *
# L, T9 y- t$ D- `6 m- H, C& t - *********************************************************************************************************/! e7 d, p4 Z3 Y/ i' N9 @! Y2 T
- /* Define to prevent recursive inclusion -------------------------------------*/2 Z' P0 W3 D! X8 w
- #ifndef __W25Qx_H" s6 `- j- b, z' W5 E4 ?1 T; o! a
- #define __W25Qx_H
# o; s& I2 d" e7 L
9 a# {9 w2 m8 @7 _" j- #ifdef __cplusplus
: |( F0 V6 J7 p" P; |2 h% k - extern "C" {
" i+ A4 M0 t+ d, [) ] - #endif
) M, P& P3 x- h; W# N! Q' ^
+ t" H) C! J4 O) t+ W3 a. q- /* Includes ------------------------------------------------------------------*/% E @5 Z* B3 x& |- R. L
- #include "stm32f0xx.h"
. }6 B: ~" e j8 G; t( D7 ?, q2 r - #include "spi.h"
0 z. o4 s: e8 B( x - . U: ?, t3 |: ]0 q; Q! M; t0 p
- /** @addtogroup BSP
3 z6 V) @8 [+ W& v - * @{
* n5 r I- j( ~# c* z9 X# C - */ # c- ]) t/ T- v
6 ~6 e9 _/ t* H1 _/ }$ ~; p/ e- /** @addtogroup Components5 \/ g0 Z3 W1 i+ M* t$ s. p
- * @{
; L! R f! M' {$ ?2 d# s7 Q! m - */ ) K4 X6 m5 q# m% L5 P4 i
- 3 Q9 R) W4 A5 O9 [2 k# s
- /** @addtogroup W25Q128FV# D9 | B# P" L" L
- * @{
8 B+ T) ~4 m( y( X - */- w8 D/ q4 c: w" t& [3 ~& o$ _/ K! ^/ A
- 3 j6 Y8 u. x9 V; a
- /** @defgroup W25Q128FV_Exported_Types
. V/ u4 n E, Z5 s& b) z: @. \ - * @{: @4 R. q4 `3 K, V4 \
- */: J& D5 [3 x- Y+ ^- |, @
- # Q/ x h6 V+ S) @
- /**
$ l0 t" Z; y( C% g6 Q- ^ - * @} q8 [* e0 B- o, @/ ~8 i9 J
- */ b" s2 M7 X4 J! Q
- : [9 {0 H R' M2 C# [+ C
- /** @defgroup W25Q128FV_Exported_Constants: y5 B1 N$ p7 G& R4 [/ ?4 v
- * @{) D ?6 z( k ]0 I8 D9 D9 w
- */
2 D5 c" S8 M: Y, E6 f - , T; N# ^# U0 w" B
- /** # X$ M1 b- p8 A* e
- * @brief W25Q128FV Configuration
: {# T+ a! ?9 A( Z' r: J; L. S - */
' C. _* `& K \ - #define W25Q128FV_FLASH_SIZE 0x1000000 /* 128 MBits => 16MBytes */, S0 m* V3 F" @
- #define W25Q128FV_SECTOR_SIZE 0x10000 /* 256 sectors of 64KBytes */
$ F6 _- Y: _ d* L7 h- m - #define W25Q128FV_SUBSECTOR_SIZE 0x1000 /* 4096 subsectors of 4kBytes */
: Z0 s& X" o9 p. I$ H) d8 `4 U7 u - #define W25Q128FV_PAGE_SIZE 0x100 /* 65536 pages of 256 bytes */
' ?. E$ k d6 ^8 ?0 f - ; H, A) |7 O' X; \
- #define W25Q128FV_DUMMY_CYCLES_READ 4) u) j3 `) t2 w: w0 L' V; g2 _% A* J
- #define W25Q128FV_DUMMY_CYCLES_READ_QUAD 103 B3 w& h# k0 v9 w
- , w+ ~$ t" m+ A/ w8 J
- #define W25Q128FV_BULK_ERASE_MAX_TIME 250000
1 R8 d x! m. B! F! M- R) O - #define W25Q128FV_SECTOR_ERASE_MAX_TIME 3000 _& l, U' c3 o0 D3 b
- #define W25Q128FV_SUBSECTOR_ERASE_MAX_TIME 800! z) R e( X( {/ M' ~3 \
- #define W25Qx_TIMEOUT_VALUE 1000: G" ~6 I9 l. s3 s* |- u
- ) m) `9 p! F/ Y4 d- d
- /** ! d' k8 d! m4 T4 N. {
- * @brief W25Q128FV Commands
3 c' ~# ^4 ]( _+ [ - */ * d; q! t3 l% x* l6 \3 S* G7 Y: P
- /* Reset Operations */1 ~" K9 r9 I$ Z/ x8 H
- #define RESET_ENABLE_CMD 0x666 ]# d2 G0 @2 T- T. V
- #define RESET_MEMORY_CMD 0x99
i7 g- R$ D3 c3 Y+ b" W - 6 m/ p1 m2 b1 n- v5 ?, R
- #define ENTER_QPI_MODE_CMD 0x38* j2 s- r# G3 Q; P$ N1 }0 Z
- #define EXIT_QPI_MODE_CMD 0xFF
S9 C8 }: N0 c+ U - " Z- t' u1 y- K' g. s
- /* Identification Operations */' Q, T/ I5 d" Y) M
- #define READ_ID_CMD 0x90
6 n) a- S J% `7 Z5 |4 ~( t - #define DUAL_READ_ID_CMD 0x92- S4 b) E0 R: A+ p! T# D
- #define QUAD_READ_ID_CMD 0x949 `( G# @% [& @" `/ k
- #define READ_JEDEC_ID_CMD 0x9F8 m5 ]5 l; v1 b3 i$ h
- : {1 i7 s2 L# W8 b+ t* g$ S
- /* Read Operations */) ?1 S4 u. G4 T5 I u O4 T
- #define READ_CMD 0x03 v2 `0 g6 a% t/ j b: K
- #define FAST_READ_CMD 0x0B% v: O% c b5 Q5 h, E+ v1 V
- #define DUAL_OUT_FAST_READ_CMD 0x3B }( _3 C. o+ [4 C8 \' A' A [
- #define DUAL_INOUT_FAST_READ_CMD 0xBB, v$ ^+ @( I+ e& _- x5 m
- #define QUAD_OUT_FAST_READ_CMD 0x6B
) Z# |# J7 H6 E) @/ s' s - #define QUAD_INOUT_FAST_READ_CMD 0xEB
- [ Y, x/ F5 D1 F- n
6 b7 I" Y5 P# ]! _/ r& @ S/ {- /* Write Operations */
/ u4 T5 s" Q% J- |! _% W - #define WRITE_ENABLE_CMD 0x06) D. Z5 f$ r. Q/ n9 E) @3 i: Z
- #define WRITE_DISABLE_CMD 0x04
1 g3 w% b0 `; e/ Y& `+ T6 ?' H# a - 5 d* m& e7 H. a8 U( D; s
- /* Register Operations */
& Q! G9 O5 h6 e$ b! n7 R0 Y* b8 i - #define READ_STATUS_REG1_CMD 0x05
: B# E6 J0 g5 J4 V' ]" Y% L - #define READ_STATUS_REG2_CMD 0x35, ~3 u2 q, _) F% ^& e
- #define READ_STATUS_REG3_CMD 0x15) _$ r+ b. Y# D' u* K n
- ) w3 u. e) i! B* q/ ~- t' U# {
- #define WRITE_STATUS_REG1_CMD 0x01! `1 Q0 H. d8 s3 z/ x# B; I
- #define WRITE_STATUS_REG2_CMD 0x310 z# d7 L: k, x# L
- #define WRITE_STATUS_REG3_CMD 0x11
2 K. P$ R) Q+ D! c* U E - , E9 F& I/ t+ ~& d5 X6 P
- 0 [1 R4 c$ r0 \! x) ?) j% U& g
- /* Program Operations */
+ f0 u/ M& X: j! f; @ - #define PAGE_PROG_CMD 0x02
; P4 U+ |, a; o- \) K. g - #define QUAD_INPUT_PAGE_PROG_CMD 0x32
. G0 R! I. T+ @
7 L/ ]( |! T! C- 8 T2 u: z, F) L. r5 R- z/ f8 `2 r- l
- /* Erase Operations */
7 C( g- Q9 W2 l" o) a+ V - #define SECTOR_ERASE_CMD 0x209 Y7 o( H8 r: y4 o0 @5 T, L7 h
- #define CHIP_ERASE_CMD 0xC7- {: K6 K; I9 v, _9 |+ j3 `$ Z
- ! m, E" K" o3 V7 x9 f: U4 ^
- #define PROG_ERASE_RESUME_CMD 0x7A* a! O3 p% Y2 J2 l. s) o$ u
- #define PROG_ERASE_SUSPEND_CMD 0x75
) q& A* ~% [; X) p- v) ~
+ L& i& e. D" d! D- 3 \ l0 q/ f& q- @: q: C) c
- /* Flag Status Register */
1 x" |- W3 }( y5 i" K4 @3 V/ { - #define W25Q128FV_FSR_BUSY ((uint8_t)0x01) /*!< busy */
0 t* ^/ F4 K5 B" ^ y - #define W25Q128FV_FSR_WREN ((uint8_t)0x02) /*!< write enable *// x" \9 `! `% ]
- #define W25Q128FV_FSR_QE ((uint8_t)0x02) /*!< quad enable */
/ `; w' }; l: k1 P
. M, t/ z' X- v- ~! j) U- w$ H7 Z4 u2 S, c9 K& \
- #define W25Qx_Enable() HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET)
! i. C9 a5 v2 m8 c2 T; W - #define W25Qx_Disable() HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET): p! Y% h3 x% P& |
- - l2 ]: Q# q& k( R, t- H0 ~0 G. |
- #define W25Qx_OK ((uint8_t)0x00)
2 y1 P+ f3 ] N3 Y, V6 Z0 B; w - #define W25Qx_ERROR ((uint8_t)0x01)
# L3 j0 e2 G, E1 \4 J9 B - #define W25Qx_BUSY ((uint8_t)0x02)% \4 k, u& u, ?- ~) ? g3 e6 Z
- #define W25Qx_TIMEOUT ((uint8_t)0x03)4 h) @* T1 f5 ?* h- ]
- $ D1 J3 ?& C+ v! s
- $ T1 g, d" r( g. l
- uint8_t BSP_W25Qx_Init(void);
3 w3 |' r* x( d& P" @1 J - static void BSP_W25Qx_Reset(void);% y% o" \; Q; x+ y, _; ]- E) B% M! I
- static uint8_t BSP_W25Qx_GetStatus(void);" }% D5 A4 B' f, k
- uint8_t BSP_W25Qx_WriteEnable(void);/ L6 K, n+ Z6 Y6 G, `8 C5 `) m
- void BSP_W25Qx_Read_ID(uint8_t *ID);
0 ^. b: [6 w7 U1 ?& x) x% G" T I - uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size);
`; l2 _; R) m - uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);+ a8 [4 d1 P+ H
- uint8_t BSP_W25Qx_Erase_Block(uint32_t Address);' b; B l( [4 v. l7 ~% R
- uint8_t BSP_W25Qx_Erase_Chip(void);
2 a% o, Z( q' w# w. u7 T/ i, ^7 G
/ C. D5 ?! |8 L, ~$ U3 w3 Y- /**
( h c6 L' m; U+ z* B M( W$ m - * @}. }, b I6 v; V8 s
- */( @* \ Y) T" g: i. J
; r9 U/ m, g7 `) L9 E- /** @defgroup W25Q128FV_Exported_Functions O. H6 R8 T) u( d
- * @{) _3 Z# Z. c$ s7 d9 p" m$ }+ }
- */
/ s$ g$ K. r2 w8 A - /**# w+ l3 v4 F4 P! F$ j3 O0 }& c. t
- * @}
, N9 o% o4 Z" ]: ^ - */
0 Z9 f* Q7 @/ J - & V, _5 Z: o7 B5 D! g, a% T9 U- @
- /**
- p# e, w$ ~0 ~, N' e* t$ z* s+ Z - * @}
1 l8 ?- g+ }8 @1 { - */
g8 v& @+ E! ]$ J& ` y
! K b- i4 k9 S- A- X! E% Y1 L- /**
, U. F8 K5 |( m, x& _2 X1 D - * @}
" |( x1 C7 N& b7 c - */ + ~ A$ }- g7 o- ]% R: ]$ B
- . n) @/ w. K t
- /**7 L/ k% r- ^, ^. x% U( A/ t: I
- * @}, f8 X; r/ H2 K+ n
- */- `$ u6 c1 q( p- a! \! D; V- _& @
- / j% g& M: ~% j% g
- #ifdef __cplusplus
0 z j% v5 ^$ l4 U: c6 D' s& ~* x. P - }
7 |2 U0 }! E0 K5 @ - #endif- h, U- j7 l: X
- + e( V2 |2 ?6 R( ?. Y1 ~
- #endif /* __W25Qx_H */
复制代码 6 H! {9 X# }' F& d$ z0 y( L" V
案例
7 j* T1 G0 N1 _' `向0扇区(0块0扇区),17扇区(1块1扇区),34扇区(2块2扇区)分别写入0x200的数据。4 |# l; ]4 I4 \ U& ^; T$ h$ O3 g9 Z
/ I1 p: M1 y& k! L3 F: b4 e/ G
头文件定义% T9 ?& Q- ?3 @& e- ?
- /* USER CODE BEGIN Includes */8 a& f# H/ x- v3 R% h
- #include "stdio.h"
3 r" k) O+ N+ F* K6 Q; u" F% B - 6 E; {* {* _7 R6 I F
- #include "W25Qx.h"! @" _- U D6 k1 I. L. E
- /* USER CODE END Includes */
复制代码 . @2 t5 A8 t% y/ v0 }1 b, {4 Z6 {
串口接收和flash数组定义2 [% N1 f2 Q) a; P/ B
- /* USER CODE BEGIN PV */
2 S0 J* k3 |+ |3 a# N9 ]8 L- [ - #define BUFFERSIZE 255 //可以接收的最大字符个数 & w! n6 c& L7 F" @
- uint8_t ReceiveBuff[BUFFERSIZE]; //接收缓冲区5 `# Y% G7 o7 a1 v# J
- uint8_t recv_end_flag = 0,Rx_len;//接收完成中断标志,接收到字符长度
& |$ V1 d$ v( V% e - - E6 b$ j6 Z k0 P4 I" v
- uint8_t wData1[0x200];; X. y& z! a* a- V! ~
- uint8_t wData2[0x200];# o! c% w8 n1 k5 }
- uint8_t wData3[0x200];
0 o m+ ~: U0 D- s- y8 e - - |7 n, l0 Y! I; X' R" g
- uint8_t rData1[0x200];
8 I7 @8 z$ ]3 X. ^! U0 W) v - uint8_t rData2[0x200];
4 [0 |' H% @3 W9 y7 E9 T& S2 R+ T/ W - uint8_t rData3[0x200];
# n4 O" H0 R. ?( a2 K - uint8_t ID[4];( J. F0 k# ~, Y2 x/ r
- uint32_t i;5 c+ {2 j: n; i' c( y1 {% Q; t. w; u
3 m) t$ m/ ?) ~& d- uint8_t flag[1] ;3 N# |7 n7 E1 X
- int i_flag = 0;& `. T) {6 S7 u( u& v
- /* USER CODE END PV */
复制代码
: ~2 r2 K: R8 @5 j/ J* K2 K6 W串口重定向: g: N4 Z6 A3 k& z& y8 Y
- /* USER CODE BEGIN PFP */) P* r/ f; s9 Z \6 D9 ?* _. z# e
- void uart2_data(void);8 A( B6 Z3 x E" H4 ~8 [; v
- #ifdef __GNUC__ //串口重定向
. @# A1 l6 n3 o1 i9 R) E+ z - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
$ y% i* R) U, M3 m4 ~9 F' k - #else
$ h2 M+ J" C0 y& S$ s' n' T9 Y9 N - #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)6 W G" K! C$ i/ C/ S
- #endif % |- }' y' [' d% d. [
- PUTCHAR_PROTOTYPE3 Z3 C0 d) d# `( q& G
- {4 S# o, J& u# Y; ~- a
- HAL_UART_Transmit(&huart2 , (uint8_t *)&ch, 1, 0xFFFF);8 t; E* Q+ R# M% I5 T1 w# _ V |
- return ch;2 @3 n7 n: W2 w. C6 B$ B& \
- }
" ^$ F. i0 c7 x# o- ~4 }8 ~ - /* USER CODE END PFP */
复制代码 0 p: j& |7 h6 M2 B' S& ] O) M
串口中断设置
g: P% P" i3 {6 \% |% K- #include "stm32f1xx_it.c"文件中断外部变量引用:
; ?$ ~+ h7 Z1 b( ~
) c! d/ L6 v: `. z- /* USER CODE BEGIN 0 */
& E# g0 P6 \, [ - #define BUFFERSIZE 255 //可接收的最大数据量5 r3 ^6 }$ a1 E5 i) D- W9 {
- extern uint8_t recv_end_flag,Rx_len,bootfirst;
+ F) ]+ j5 [0 [ - /* USER CODE END 0 */
复制代码 2 i- a! F3 t+ }& x( }
串口2中断函数:& V, u/ z; q/ L; D+ X5 ^: n
& F' C9 X1 n: v1 t% ~- /**
( u! y% A7 j) N E( z6 ?6 T - * @brief This function handles USART2 global interrupt.
; p u) a* P2 j+ r2 N4 h - */
$ w5 v5 M# F* W) g, V$ c - void USART2_IRQHandler(void)
5 E6 A! m3 X3 n1 P& [9 [0 d - {
6 D1 q3 m, {. X6 L' [ - /* USER CODE BEGIN USART2_IRQn 0 */
# `2 j9 ]+ e& q8 z - + d. ?' P* p9 y# [3 d$ o! C. N: d+ ]
- /* USER CODE END USART2_IRQn 0 */$ v$ R. e' Z; j1 X6 x7 C
- HAL_UART_IRQHandler(&huart2);
7 E* s: K5 \& h# H* a& ` - /* USER CODE BEGIN USART2_IRQn 1 */
! j* B1 ~. W$ d. _' U" k - uint32_t temp;
! a4 U' N0 t$ J( @2 V( D- z y* }6 \ - if(USART2 == huart2.Instance)//判断是否为串口2中断' z2 Q" `- Y; n* g2 w: O
- 6 n( b# @5 Y& e* U3 y" H
- {
# C# m# Q5 e; k _; U# _7 K - if(RESET != __HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE))//如果为串口2
3 u v' e3 w8 ?0 s: l - {
+ {6 {) ~) _3 w k$ o4 \- n - __HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除中断标志6 M+ f% p7 J# I2 m5 C9 `' P
- HAL_UART_DMAStop(&huart2);//停止DMA接收
# y3 G0 ?9 [5 @. q7 N0 E - temp = __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);//获取DMA当前还有多少未填充
# T8 ]1 H% g& d* |5 m - Rx_len = BUFFERSIZE - temp; //计算串口接收到的数据个数4 F2 Z7 T8 v) X, v8 a6 W
- recv_end_flag = 1;" ]' A. H, G7 }, P# H" `3 D' m
- }
, S! ^" w+ K, v/ |5 U - }
! X* d: S& y* _" f; C% s- T( A
% @2 D& R' }7 U8 W+ {# C- /* USER CODE END USART2_IRQn 1 */
' Y) k9 N k" v. Q3 L0 [/ {5 w' A4 ` - }+ I1 _1 M+ S3 M" l
复制代码
D* m. E) {; c主程序2 a5 V: a& b8 R& \* m [
读取ID和flash数据及擦除。" W1 j# j% {3 [* m4 q9 Q( w8 _
: f. d2 n) a) I- /* USER CODE BEGIN 2 */
- z. p4 Z! Z$ L) j - printf("GD Nor Flash案例\n");, B' J& @& c: B
- __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);//使能串口1 IDLE中断
5 w; O6 ]1 X \ T+ P -
6 b5 ?0 o7 L* Q; }2 A8 e) | - /*##-1- Read the device ID ########################*/
0 K( C; Y2 e# B2 |7 I0 ?2 V4 f - BSP_W25Qx_Init();//初始化W25Q128
' i4 Z9 f: g; o% D. B7 e' A - BSP_W25Qx_Read_ID(ID);//读取ID/ o( n; k/ ]7 i `+ q' I$ W7 o
- $ k- _8 @1 L5 q. t J9 k L
- if((ID[0] != 0xC8) | (ID[1] != 0x16))) |4 D5 b% p6 Z! s9 @1 m
- {
- E1 {1 N0 V; l+ p - Error_Handler();//如果 ID不对打印错误
3 S! A0 x" K r - }8 w* N% u% V5 m* w1 W o7 _
- else//ID正确,打印ID
) C3 `& N, ?$ H$ g: {0 L& h/ o - {) Y- B; e% ^. x/ D
- printf("W25Q64 ID : ");& B1 G2 M$ G! P, o e5 O7 T
- for(i=0;i<2;i++)8 m: t1 f2 a7 c4 u1 [
- {: e' a' K3 Q1 P& p' e, L9 \2 e
- printf("0x%02X ",ID);0 O& r) i4 n: [) j& s
- }3 N5 Q% e9 ?3 l; D$ [
- printf("\r\n\r\n");
4 \" I, e$ c% X6 H! b - }
$ f& Q/ ]% l- I3 O: G) k/ o - : e% _; t* T% y9 p2 h0 b
' \ ^9 ^& I- m, }2 x' A- /**************************读取第0扇区数据**************************************************************/1 r6 ^% H$ Y; W1 f9 z* W# L# T: }4 J% h
/ k" A$ [" P. f& A+ J- /*##-3- Read the flash ########################*/ G0 H% ~! L5 ]- I- W+ P6 T
- /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/
0 Q; m% w5 i: y) z: b d' o0 e+ e - if(BSP_W25Qx_Read(rData1,0x0,0x200)== W25Qx_OK)' d3 L/ K. v4 z5 o7 b, r
- printf("读取原始的0个扇区数据成功!\n");
& t4 B% R9 f- l% ^1 J - else" \# f2 v4 W5 S$ Z4 m
- Error_Handler();" j H9 m R! _2 X
- /*打印数据*/
, [. ?3 K5 x" `6 d# L - printf("读取原始的0个扇区数据为: \r\n");# q! K& k# w6 u; @
-
) _5 D1 R! d: B" R - for(i =0;i<0x200;i++)
* @, P% x* I4 u; [/ z - {+ W( [" m" v4 Q9 j
- if(i%20==0)
2 h+ h, K- Z' Y9 H5 x! r - printf("\n0扇区第%d到%d的数据为:\r\n",i,i+19);' t/ Q) w. n7 ?# T2 X; |" K. f" ~
- printf("0x%02X ",rData1);
4 M' _ n+ [- m# ` - }2 E) D o9 P, M+ P, v+ t# L+ S
" m0 N/ K- i7 z/ t" Y- printf("\n");
) Z- R- g: u8 B1 K: B' O" g h5 I k' a - 3 i% k4 y0 S. s- k4 f) r
- # w3 K5 ]- Q8 Z+ X
- /**************************读取第17扇区数据**************************************************************/
2 d5 X. Q# n; q1 p3 U -
- n/ M% |) `, X$ F7 Z( S" J - /*##-3- Read the flash ########################*/ 0 D8 l0 O k; b2 c
- /*读取数据,rData读取数据的指针,起始地址0x1000,读取数据长度0x200*/
4 X" E- v. h" r" n8 b, O: e - if(BSP_W25Qx_Read(rData2,0x11000,0x200)== W25Qx_OK)" q2 @) h/ p7 V: |/ V
- printf("读取原始的17个扇区数据成功!\n");
( j) z, k+ h* o' ^ - else$ z' W: s) j1 X$ a0 S
- Error_Handler();6 k3 K! x# X8 U; x0 ]! R& G
- /*打印数据*/
0 o: l0 q; ]/ B% M, s - printf("读取原始的2个扇区数据为:");% q' E. X, z; {- L5 Y. D
- 6 v4 c- S: r; G# ]" P& c
- for(i =0;i<0x200;i++)
" H9 Y% _( @' a0 P - {0 c2 R H3 l% P! Y
- if(i%20==0); ]3 U Z" J/ `) b* h# ^
- printf("\n17扇区第%d到%d的数据为:\r\n",i,i+19);6 L+ a6 i9 g& s' W' O
- printf("0x%02X ",rData2);. l% ^* e: B) q7 E# y8 I
- }4 j4 L5 n D' a6 o' {2 l8 ?
- % r& C; o, Q; P' \) R! R
- printf("\n"); : b2 ^9 e3 v$ f i" B
- 4 `7 ^% c5 C; h
-
: J3 ?) v4 v8 S, N; }! U - /**************************读取第34扇区数据**************************************************************/- S2 T/ I2 `; b/ N' Z6 a3 R
- * v" p/ ]: H: A/ m/ D
- /*##-3- Read the flash ########################*/
& L( a3 ~( f2 u8 T* _7 S6 p- i - /*读取数据,rData读取数据的指针,起始地址0x2000,读取数据长度0x200*/
* s1 N5 C* F" W7 D) ] - if(BSP_W25Qx_Read(rData3,0x22000,0x200)== W25Qx_OK)
0 x* N" p* B v& ^$ h* ~ - printf("读取原始的34个扇区数据成功!\n");
2 Y g$ J# K2 {9 a: x - else3 W8 D, ~; {9 n. P2 m! h
- Error_Handler();9 a6 b) U$ c9 k/ `3 k4 i# N
- /*打印数据*/ 4 T+ P* A, ?% j' A1 M
- printf("读取原始的34个扇区数据为: ");
3 v! ~* n4 ]+ u7 g# w" N8 U - & Y: j- ~+ \2 l* g
- for(i =0;i<0x200;i++)3 U5 b8 q! q, S& ~
- {
0 Z& v9 ?: Q* d+ @ - if(i%20==0)( H' T# y& R6 P% w
- printf("\n34扇区第%d到%d的数据为:\r\n",i,i+19);/ U2 g' l4 p2 ]% B! u
- printf("0x%02X ",rData3);
' P& Z; C1 _7 W8 W( y - }6 T/ ]* \3 O2 j, i2 y. W/ Z% s
' l: n( u- t+ l% D) m6 n- printf("\n"); ( H# M. X% N+ o2 B& }
-
+ P1 h) r, j* {8 {& S0 ^2 |8 M -
& p2 t: ~/ f9 F4 P2 U# i - % b" J K+ \, } V% A2 z
- /**************************清除第0扇区数据为0**************************************************************/$ P1 j9 z; M9 O
- / Z- M( z# r0 y% W. l5 s
. \2 P% b% P3 E+ x9 v) K; y* \ N- $ d& j+ |/ _# w* ~$ X+ t5 R# S
- /*##-2- Erase Block ##################################*/
" X( b$ e) \0 p8 W/ A - if(BSP_W25Qx_Erase_Block(0) == W25Qx_OK)
, }8 y3 Z# C* L# q: Q - printf(" QSPI Erase Block ok\r\n");' q( c5 H- N( H% v
- else, w+ Q: E/ ]4 g0 f" {4 m! j4 E+ ^$ y
- Error_Handler();
# j/ U( o( p z9 q -
! Y7 X( Y- [/ q+ Y j$ U0 i8 E - /*##-2- Written to the flash ########################*/
3 t l K1 A" M6 d! |( K - /* fill buffer *// f6 g$ z) L" d1 C: S0 k, ?
- printf(" 初始化数据,清零第0扇区前0x200的数据!\r\n");
: M( V' n% ~# [+ e* x# T0 v - for(i =0;i<0x200;i ++)
2 _- X4 C# T; i. w, N- |: I3 D5 G - {
- U& z( l2 z& H5 _ - wData1 = 0; P/ [, a0 W% X4 T) R3 k! `7 Y" t: R
- rData1 = 0;( o. r% E. _2 l }4 @; x
- }
( o+ x1 D% M, A$ Y$ ]8 H$ W% E - /*写入数据,wData写入数据的指针,起始地址0x00,写入数据长度0x200*/
, M! p. h6 F( H7 B; M3 P/ u3 _ - if(BSP_W25Qx_Write(wData1,0x00,0x200)== W25Qx_OK)- J* d8 Q1 u4 A
- printf("清零第0扇区前0x200的数据成功!\r\n");
" i$ p8 P; e- N - else
- C% I8 G, ~6 v; W8 Y A - Error_Handler();
: Q6 G, c4 G4 B$ w* o
4 h2 _( v' L, [8 F" W- % Z) u* P W$ ~
-
; n7 l- E' o- }' j# a/ }' l - 3 a0 Y9 |+ {3 ? z
- /*##-3- Read the flash ########################*/
( x# V; K! I9 |# V) j/ I - /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/+ C( q: U* J+ Q$ J- q
- if(BSP_W25Qx_Read(rData1,0x00,0x200)== W25Qx_OK) g1 D3 e2 X$ u B$ ~/ q
- printf("读取第0扇区前0x200数据成功!\r\n\r\n");
9 s. G5 p! t" }8 r4 o t0 P% w - else
# ?" m0 y' c W2 f1 e* O - Error_Handler();4 a' Y1 A" T4 v
- /*打印数据*/ J; U$ G, Z' ] ]
- printf("读取第0扇区前0x200数据为: \r\n");, H4 j1 z% V1 T
-
+ y/ b/ D9 R6 B - for(i =0;i<0x200;i++)' x5 b3 Z( T2 ~. r0 t5 h* V
- {
: l; W$ p, j, D1 R2 [ - if(i%20==0)
) l6 V3 O" v* K( h - printf("\n第%d到%d的数据为:\r\n",i,i+19);
8 p3 d& Z( ^6 U% t8 z% J - printf("0x%02X ",rData1);
- F' U( A$ b# N9 f! G - }( Q9 C% b: U- q C; M
9 n$ _) i( T: a' N Y3 ]4 v- printf("\n");
- c% G$ k% u, \2 p7 ~* N* L - $ p* }0 D: F# A% W; p
- / ^* A g- n R" R. {7 d
- /**************************清除第17扇区数据为0**************************************************************/
. i5 ?: ^, y; z" q# g - 8 v7 I% g7 e+ t5 u
- 5 w0 m, h6 k# U- {# t3 H
-
$ E U0 a, K; K8 k& I - /*##-2- Erase Block ##################################*/
1 @4 Q5 g( B2 \6 m2 r - if(BSP_W25Qx_Erase_Block(0x11000) == W25Qx_OK)
: ~, a* M! z% S- l" I) S - printf(" QSPI Erase Block ok\r\n");$ @# I6 z# i6 e8 _; I+ Y
- else
0 R* l$ F* }7 n9 ~ - Error_Handler();! V/ Z' u3 F4 G" Q- j8 n
-
, X# ], Q# M$ ]" F" \ - /*##-2- Written to the flash ########################*/ " K5 d/ L, W& Y' h" v5 N6 p
- /* fill buffer */
4 ]) W1 ]$ Z7 ~* C; ? - printf(" 初始化数据,清零第17扇区前0x200的数据!\r\n");: H( l7 Z3 k3 f& p8 @$ h; Y5 {4 N+ R
- for(i =0;i<0x200;i ++)$ N6 q+ Z8 Q; \: r( @# g
- {
; g. u: N% [# {, z5 s, U - wData2 = 0;0 ~" G, ?; J h, u* x# o; u
- rData2 = 0; \5 v+ ^9 H( j' C6 ]9 F
- } N0 l' C2 H' u$ u7 F0 O
- /*写入数据,wData写入数据的指针,起始地址0x1000,写入数据长度0x200*/0 a8 C/ B/ ^; ~; `
- if(BSP_W25Qx_Write(wData2,0x11000,0x200)== W25Qx_OK)
; n; ^: l! X n - printf("清零第2扇区前0x200的数据成功!\r\n");
$ H7 D. F4 |3 @# L' q* n2 l( Q) `4 _ - else
% W9 X8 I* ?8 [- N$ u- f( \ - Error_Handler();
% [- r6 H B1 s9 V - . x- d$ G% _6 n* x/ d
- 5 ]1 f* V& h* v! V- i* I! l
-
: }% g6 r0 C. p6 n# C/ B7 z -
2 o% l, T' z. ~) j1 P w - /*##-3- Read the flash ########################*/
$ v: Q- ]; o; {5 ^- D1 k1 I9 V - /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/
/ ^: X) D! t% t3 p; X2 } - if(BSP_W25Qx_Read(rData2,0x11000,0x200)== W25Qx_OK)
1 U" |5 L: c. G. f* S c - printf("读取第17扇区前0x200数据成功!\r\n\r\n");
: l9 e5 }* |3 i2 V - else
W- A1 w3 f2 z9 m$ c# {' [* A7 h - Error_Handler();$ W* G. E. ?5 A: U
- /*打印数据*/
6 c' _3 [6 Z' \# N; ^4 b- Y - printf("读取第17扇区前0x200数据为: \r\n");
& e8 u' Z8 y' H) |$ z9 p0 H - 9 q& ~) [. p- D, V2 A: g
- for(i =0;i<0x200;i++)
8 F4 m+ B( ?/ ? - {$ X! O. H7 w5 T5 ]8 {
- if(i%20==0)
3 P. ^' w0 y) Y0 @3 M8 t( f# e2 ] - printf("\n第%d到%d的数据为:\r\n",i,i+19);6 ?8 s0 f) G3 w3 k0 x2 m
- printf("0x%02X ",rData2);: z, |* V9 @% D9 R8 ?" `: a$ R4 o# }
- }7 E7 z: a; }6 U( E, @
# }6 o# H3 ?5 U% S, f: s6 U- printf("\n");- q7 u0 \+ Q- M1 C% `4 l
- * D3 V' p% P/ Y3 K" Z# i* Z6 o
- : X ?# x$ I9 z3 Q& N) D1 I
- /**************************清除第34扇区数据为0**************************************************************/
6 Z5 \! M, G* ?& q) Z
' U, f: S6 n% k0 s
% i( n8 g4 b D2 O$ [-
8 s6 Q( c6 B7 T0 i5 I" V - /*##-2- Erase Block ##################################*/ 3 V" g: g! p8 s' i$ F
- if(BSP_W25Qx_Erase_Block(0x22000) == W25Qx_OK)- i2 O& I% z* Q/ d
- printf(" QSPI Erase Block ok\r\n");/ b* R. { j4 B' B5 ^
- else
: |0 w% Y) g! L; o- n* r$ g8 K1 b - Error_Handler();( Y! T* k! b! b% ^
- % ?$ x; o: Z) G9 U3 q
- /*##-2- Written to the flash ########################*/
8 r* A- O" Z" L7 @ k, v# c1 X - /* fill buffer */, w3 P1 l' {# U
- printf(" 初始化数据,清零第34扇区前0x200的数据!\r\n");% u1 }! ]* K8 J6 ^1 u
- for(i =0;i<0x200;i ++)( i. k% Y/ U9 n J, t+ n4 P
- {
3 m2 h- y7 K" q$ Z$ b - wData3 = 0;5 q2 {1 Z O9 [
- rData3 = 0;
( J$ \0 S" w9 N7 g$ X, ` - }
" M7 _& Z7 n6 W9 a2 D" F; [ - /*写入数据,wData写入数据的指针,起始地址0x22000,写入数据长度0x200*/# y9 G# o8 v- k, X' l, K9 r4 ~, w7 Q
- if(BSP_W25Qx_Write(wData3,0x22000,0x200)== W25Qx_OK)
( b9 T: \! [, O/ w5 j" D' G, { - printf("清零第34扇区前0x200的数据成功!\r\n");
0 S- M9 [% n$ c$ C9 M - else4 Y- o( J2 m2 H: {5 R
- Error_Handler();: P8 I& x" e4 o$ @; }
8 y1 L- t, R$ c6 M- . G( ], A- ]) W+ A
- 1 o. }4 Z- J: e
- " p. C: q! d o9 j
- /*##-3- Read the flash ########################*/ ' I: d! k! b" ?$ G, P
- /*读取数据,rData读取数据的指针,起始地址0x00,读取数据长度0x200*/! {0 S) ~( l' z1 g. q9 S1 |6 y
- if(BSP_W25Qx_Read(rData3,0x22000,0x200)== W25Qx_OK): V9 {' Y! @" t2 t$ U0 J% r9 V
- printf("读取第34扇区前0x200数据成功!\r\n\r\n");
# _( W0 [+ a8 \$ Y6 g - else
% @, X3 q* r% \ - Error_Handler();
5 L, Z) v u1 E) i/ k3 d - /*打印数据*/ ( ^, V1 b& J0 d: o" b/ q- U
- printf("读取第34扇区前0x200数据为: \r\n");
- f0 G3 q8 \: R1 \; I$ G - 9 s6 E+ O# G5 \6 l8 l- d9 r
- for(i =0;i<0x200;i++)8 J8 A# M+ | M7 A7 M5 t' |7 j/ I
- {9 B1 g' [2 \9 w/ W: ?
- if(i%20==0)$ L% p" ^+ D" J6 Z1 J: [
- printf("\n第%d到%d的数据为:\r\n",i,i+19);
3 O0 K W& c$ z: j& D0 d; e - printf("0x%02X ",rData3);6 j& K% j: `, s# r s' ~
- }+ j' o& e9 z1 X8 e) M
- 5 N; `# e% d& Y
- printf("\n");
3 Q& h7 v& Y& E - ' m6 S# B+ x3 \+ p! M8 y k
& H: G6 x" w: y/ w ^- /* USER CODE END 2 */
复制代码
) j, f0 r; J$ a主程序。8 K" h. o9 a* Q
9 y/ w: B# U7 f+ H1 O; w" P, I! K- /* Infinite loop */
& [! M' e$ a5 p' h - /* USER CODE BEGIN WHILE */# n0 ~; }6 ^8 Q+ _; q0 g- J" ^
- while (1)* p& W% x3 @. `+ V" ~
- {
7 w# B% [2 }$ l# ]' U - /* USER CODE END WHILE */
0 k; ]5 M2 X1 U; p# i% t
% S# S7 V) Z$ G- /* USER CODE BEGIN 3 */
4 ]) @( N0 _0 X }" b8 ^ - uart2_data();
9 Q' V1 H3 ]3 ~) @* F - HAL_Delay(100);$ J% T/ Q9 U4 f0 p# w' f* h) ?' O
- : l$ U4 x* R8 ~" \- K" Q3 L
- }" k, y. L& N6 d
- /* USER CODE END 3 */
复制代码
, [/ ]8 ^" Y0 z数据处理
# ^8 C1 G5 }3 G% N: ]2 A- Z- /* USER CODE BEGIN 4 */
5 c4 ` O5 ], W - void uart2_data(void)! j, C8 F( ~1 j# X6 P* ~
- {
+ g7 K8 |( r5 s - if(recv_end_flag ==1)//接收完成标志/ Q/ |& v5 h8 L M# ^4 T
- {* c" b' L, O9 G3 U9 u9 S' n3 h
-
" T! M* R9 X7 k" P p1 t - ! u3 J2 N$ l: P0 V
- if(ReceiveBuff[0]==0x00)
. o$ W4 W0 e. }! o9 e+ r" B - {
1 q) A" N2 |. a - printf("写入数据长度:%d\n",Rx_len-2);
1 h, V4 W( v; C - for(int i =0;i<Rx_len-2;i++)
' D4 F Q7 ~; \2 h+ r - {
7 z7 k' M5 Q) y1 X - wData1[ (i+ReceiveBuff[1]) ] = ReceiveBuff[i+2];9 |5 }2 _& c1 Y8 i
) V. b7 X U4 ~- @$ \) x, x! {7 t" r- }3 K! J- ]9 i/ |. g! h. e" q5 p7 d3 O
-
3 H1 Q, Z0 V1 x9 A/ q6 C7 _! f; E* Y - / Y O2 i' W4 k; u0 D
- /*##-2- Erase Block ##################################*/ 0 {# `5 B3 K8 _$ i; l; Q
- if(BSP_W25Qx_Erase_Block(0) == W25Qx_OK)
. Z# B% r4 ~& l/ k+ T) R# l - printf(" QSPI Erase Block ok\r\n");8 @. r) G* b+ m6 b6 g$ p1 J
- else
" O: s# k4 p3 y, W# f8 B L - Error_Handler();
& c2 d6 D3 \" W& O+ U+ u' _
6 t0 U1 y+ |! a( P8 w) N) l-
5 I% \' ]1 _5 n; G* @! Z6 b, i - /*写入数据,wData写入数据的指针,起始地址0x00,写入数据长度0x200*/
2 {& t2 J/ M- b0 \( W; i' ^6 R2 Z - if(BSP_W25Qx_Write(wData1,0x00,0x200)== W25Qx_OK)) E" d- s/ P, w) l% L u- M9 d
-
/ R5 V, t' l- M - printf("扇区0数据成功~~~~~~~~~~~~~~~~~~~~~~~~~~!\r\n");1 |) [6 K8 }3 B! c6 J- ?1 I
- else
* C3 G$ m' T. Q+ S1 ? - Error_Handler();
! {4 o8 ?0 I3 K- \6 |9 ^; n -
# @9 Q0 d# p+ x1 K3 q; } - if(BSP_W25Qx_Read(rData1,0x00,0x200)== W25Qx_OK)( t {- N* ?9 h' p6 Z1 k
- printf("读取扇区0前0x200数据成功!\r\n\r\n"); h% P, R# r* \3 B+ Q
- else. B6 L' O( |) `; a
- Error_Handler();
) O5 I+ M$ l. i$ t4 e0 e# w - /*打印数据*/
. j7 m" i& \* Q - printf("读取扇区0前0x200数据为: \r\n");2 h, u: n6 F1 D! o
- 8 a, L1 Z$ d# V/ x; V8 V) U2 ^
- for(i =0;i<0x200;i++)
" Y( u) D$ y T: E7 P) T2 G - {9 j: j. A2 n7 l: P3 s( G* t
- if(i%20==0)9 ]2 _' m d5 j7 A
- printf("\n第%d到%d的数据为:\r\n",i,i+19);: z, r* |/ Q+ v; I: F% c5 ~; ?
- printf("0x%02X ",wData1);) x3 y, y6 p$ h$ B4 j
- }
+ F6 \5 ]' N# [7 j - 6 A, g A& M/ m3 R! M7 {( g: A
- printf("\n");
5 F s" j& a- A- B; j0 x6 k4 g -
& d6 N$ E# V7 ?- n - }
. j7 d* j8 U$ e9 J8 I- u4 D -
) _/ V: O l2 P+ D1 ^/ W - ' p5 Z0 s& F) d
-
% T+ e; C2 g" |" o) H - else if(ReceiveBuff[0]==0x17)7 }2 k A( z$ `+ {# r0 ~
- {/ j! R% T, z7 z2 p2 S' A# ]
- printf("写入数据长度:%d\n",Rx_len-2);+ [, c! C; d( |) l8 i3 F
- for(int i =0;i<Rx_len-2;i++)
2 J. s) a5 A( b; ?$ X! {* ^: L - {" N, Y" K- H& N2 c
- // Data=ReceiveBuff[i+2];
9 d/ w1 o- m" k! ]9 N1 {& G - wData2[ (i+ReceiveBuff[1]) ] = ReceiveBuff[i+2];
4 B# l) p$ `- Q3 _& k - }
, Z8 [9 q5 ~& q7 c0 r -
( A# z; b( n3 V) [3 I: D% D0 K
- T4 G$ a! R6 v% V* S- /*##-17- Erase Block ##################################*/ ( @7 h0 |* Y/ G/ t9 A# W: P4 ~( C
- if(BSP_W25Qx_Erase_Block(0x11000) == W25Qx_OK)* h7 Z v8 {$ f S
- printf(" QSPI Erase Block ok\r\n");4 S& B! Z# v. }
- else' q4 j6 f, x" J* E) k6 y& e
- Error_Handler();1 F' d8 \1 d B' d3 W3 V
- 8 {/ t' `3 [( Y; f+ Y4 H" M
-
" e/ W3 z/ a# t2 S; n8 R( m - /*写入数据,wData写入数据的指针,起始地址0x11000,写入数据长度0x200*/
& x7 |7 I9 S7 y7 ~* l. i - if(BSP_W25Qx_Write(wData2,0x11000,0x200)== W25Qx_OK)3 G T9 e) t% E6 H l; M! e
- " Z! \* u P7 c5 K
- printf("扇区17数据成功~~~~~~~~~~~~~~~~~~~~~~~~~~!\r\n");
" h+ K7 M; A1 a: Y0 H - else% O! |; @5 O5 ]: K) D
- Error_Handler();4 c; p- h+ {9 I7 h2 t- @
- ' U B) k9 g- o
- if(BSP_W25Qx_Read(rData2,0x11000,0x200)== W25Qx_OK)
8 e4 o) @7 t: Z - printf("读取扇区17前0x200数据成功!\r\n\r\n");2 B, u/ u& _4 [/ P) q, G" I
- else/ Z. A: L2 V, l
- Error_Handler();
1 ^$ ~/ B* b2 o U" P4 e - /*打印数据*/
9 K& F9 w: v! I- p - printf("读取扇区17前0x200数据为: \r\n");3 s( T$ {3 Q3 n. N4 ^8 [3 S! v/ t
- 7 }8 D/ Q# h0 x Q
- for(i =0;i<0x200;i++)
0 n( j, _9 ^, q0 K) f3 j - {
2 O. O9 X1 f# N- U - if(i%20==0)" R$ H! s( }6 U% S1 c H
- printf("\n第%d到%d的数据为:\r\n",i,i+19);7 o2 l& n" [; Z! P( D- M$ B
- printf("0x%02X ",rData2);! {# h1 Q8 _; b2 i$ X5 x- X6 p
- }# j2 r! d. Y) m) y9 }: B/ y9 [
- ) x2 n9 j0 ?* z1 D: r
- printf("\n");
3 n" R. A2 P u; c! T1 | -
! @2 P) _8 F0 c4 M! ^4 w% R8 i - }
) Y* ]5 S& c, y# i
% f; D0 k+ F( J2 Z+ r2 p- 7 J. a: }7 D9 ^- z% f% V% K
- 9 l9 b8 \1 _0 k, j1 C: K% _. E
- else if(ReceiveBuff[0]==0x34)$ L8 E5 l" F1 k5 r+ Z9 i) U
- {
T& o: l/ C8 Q$ L& S( a& } - printf("写入数据长度:%d\n",Rx_len-2);
G+ f. J0 |8 o% S9 f2 h# o7 g1 k6 N - for(int i =0;i<Rx_len-2;i++)' X# G' H: _ n4 N! ]/ u* J
- {' Q" W9 r3 N2 p, }
- // Data=ReceiveBuff[i+2]; L* s0 p& T5 s" F
- wData3[ (i+ReceiveBuff[1]) ] = ReceiveBuff[i+2];
3 s6 Y q/ j* V - }
5 ^% m& G% `- Y' V/ j - , C- p7 }4 ]$ \
! a, I1 D5 C3 a2 ^- /*##-22- Erase Block ##################################*/
( G: F2 q% u0 X5 i4 o - if(BSP_W25Qx_Erase_Block(0x22000) == W25Qx_OK) {& f" e1 N, K7 j+ G; |9 G' ?7 h; d
- printf(" QSPI Erase Block ok\r\n");
9 ^3 \: C+ \" ^8 |9 p( A2 P8 ^ - else# u( u7 h3 v k/ x9 O
- Error_Handler();: l% K1 G6 [; ?9 r* L
. v E: e! w+ ~* R( Y, X% r5 w+ O& F) p-
: o8 j5 v6 ?6 F a8 r0 _ - /*写入数据,wData写入数据的指针,起始地址0x22000,写入数据长度0x200*/0 p [; p9 @! K! v1 K
- if(BSP_W25Qx_Write(wData3,0x22000,0x200)== W25Qx_OK)0 \- M0 j/ |- x! k
- 7 \6 x: v. e( X1 k: o4 R
- printf("扇区34数据成功~~~~~~~~~~~~~~~~~~~~~~~~~~!\r\n");3 R: I* z5 H2 {, I+ O D
- else
8 c! R. C: Y& `, `- I - Error_Handler();( Y8 [% J7 l7 _
- . l3 [0 }9 i( H6 X) n k7 Q
- if(BSP_W25Qx_Read(rData3,0x22000,0x200)== W25Qx_OK), o! \/ y4 X" c
- printf("读取扇区34前0x200数据成功!\r\n\r\n");) M6 h% x$ Y4 m$ G9 K( {5 O
- else
* Y( u" p7 ~, B1 e - Error_Handler();) C6 d3 Q' O# L9 N7 k
- /*打印数据*/ 7 d) Y% y: D# R/ g) |( M3 r
- printf("读取扇区34前0x200数据为: \r\n");
- q# }$ J, W- \0 y -
- g: i! W& k$ Y9 r; J2 k, U" t - for(i =0;i<0x200;i++)
; g+ J/ Q+ a$ a - {4 [2 @' `8 r' P& b6 ?1 ^
- if(i%20==0)6 q3 w( [6 o" v: H$ ?
- printf("\n第%d到%d的数据为:\r\n",i,i+19);$ Q! q2 p$ j- d! } I
- printf("0x%02X ",rData3);
" _2 L) Z) g" ^ y3 N( L( Z! X - }
8 m |2 K0 c$ G) g% A" B- A5 L - ! q P0 k, Z* N" Q. Z. \ f3 n& d
- printf("\n"); C- z6 H- C- d5 A7 {
-
$ k- j3 F+ P, ]: H; t8 ]0 h - } 9 M% l! ]( L% g3 h* v
3 c4 b7 {/ q3 s/ Y. u* e$ u& Y- w
" K3 q M M" [7 W- 6 l7 a+ O7 {' d1 P7 d* V
-
7 s) |! h5 |, F) o. f$ X - else
! p, ~2 `! Z( ?$ k' f e& Y9 k8 V - printf("输入错误!");
z' `7 \2 f$ N, m7 P( r$ X3 {7 b
# ?0 D. k3 d7 O4 ~- for(int i = 0; i < Rx_len ; i++) //清空接收缓存区( ^; _6 {2 k) |; ]; K; b3 w4 M) ~
- ReceiveBuff=0;//置0! l5 S( W$ P, Z* ~1 j
- Rx_len=0;//接收数据长度清零* D7 J7 `; B5 F5 t7 W. c
- recv_end_flag=0;//接收标志位清零% Q& A' r y2 `% W r5 |% {6 |0 B' v
- //开启下一次接收
7 X. Q- ]& U* T+ a1 Z - HAL_UART_Receive_DMA(&huart2,(uint8_t*)ReceiveBuff,BUFFERSIZE);
2 Y V2 O" z* O1 D1 {' S6 g1 s - }% Z/ s! K1 A' S% j! z
( T; M" y; H* H* D: d: i- }: c0 O. ]# ^! D) y
" w6 B3 \4 v) U; k- /* USER CODE END 4 */
复制代码
! E& s: H3 a) l* U0 S* N演示
- a1 u/ N3 z# v1 T2 n( `W25Q64芯片型号的ID为0XEF17,下方读取为0XC816,所以读取成功。
9 c5 \) C4 x) s0 j5 Z
* r- e2 h9 a e- _5 d8 E/ {
4 S9 J8 w4 {# k, o
7 P3 \9 W# K/ a2 ]6 L
开机会打印出0,17,34扇区的前0x200个数据。% c4 c/ j" e# F4 j" D/ S) }& e5 i
1 F. v$ x. k+ }0 D3 y9 `- j
( i2 A- Y5 Q4 V, E# L# l9 v# X4 k* [3 z
4 x% ]; r7 w3 u' X! F* L3 n打印完原始数据之后将数据全部清零,清零完成如下图所示。
6 X# g' ?3 t0 G5 R4 r% t8 U* K6 {
6 u: Z4 } ?" K0 P0 Y6 K' I5 s, T b1 q1 e0 H% \0 @
串口定义了ReceiveBuff[0]的数据为写入什么扇区,ReceiveBuff[0]为1写入扇区1,ReceiveBuff[0]为2写入扇区2,ReceiveBuff[0]为3写入扇区3,若为其他数据,则打印输入错误;ReceiveBuff[1]则为写入的位置。
6 [/ B+ `$ ?2 \2 r$ l/ \9 b# N F% b2 F输入:00 05 01 02 03 04
7 z8 T t |/ ^5 L% \向扇区0的的05号位置开始写入数据01 02 03 04。. }5 r) \6 U$ J) B% w
/ u \5 U0 U( C- C4 g2 f
7 X! Y9 j* \! a* z, O7 Z+ W8 i8 q' b: y! S) V
输入:00 28 11 12 13 14 15
9 I$ y) s* M% f- E向扇区0的的40(28是十六进制)号位置开始写入数据11 12 13 14 15。
' R; T% @7 g- @! q* _: ^" I' d5 j# k4 H, x% g+ d7 p- V# V
2 ~2 L+ _& k$ m9 N$ x% H" t. h; M" a' H
输入:17 10 aa bb
9 t( O2 K! ]: D7 n0 l9 e) s向扇区17的的16(10是十六进制)号位置开始写入数据aa bb。0 f D1 A2 o- V7 v/ b
7 u& \, k3 q# h: g" s6 W/ z
# c/ x! j, Q2 f: U7 W$ k
- W- U# Z1 z" x4 t————————————————
+ {* {) b) t6 [版权声明:记帖% N- W5 g- h, X. o
) f3 h; n: n& i& i8 u1 u4 H
& b) z5 v% l& Y' n3 O1 l' `8 j/ s' ]6 G
' o2 ^9 |; f; A6 |$ _- @' D4 o5 z |