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