一、W25Qxx系列芯片----简介- }( M1 D! r5 [/ i2 H/ D q: H& c) S; t
W25Qxx 系列 Flash 存储器可以为用户提供存储解决方案。擦写周期多达10W次,可将数据保存达20年之久,支持2.7~3.6V的电压,支持标准的SPI,还支持双输出/四输出的SPI,最大SPI时钟可达80Mhz。& x# _. r7 ?( p0 [7 G, E W
W25Qxx 系列 Flash 存储器是为系统提供一个最小空间、最少引脚,最低功耗的串行Flash存储器,比普通的串行Flash存储器更灵活,性能更优越。
1 O+ U) P& ?8 k. e7 m6 c功耗低,正常工作状态下电流消耗0.5mA,掉电状态下电流消耗1uA。
( I" d4 y j% E& e6 n* T4 r: m
. m, f/ d( l% B, p* i1 t/ x1. 存储结构 x H4 g1 C; \
W25Qxx 系列 Flash 存储器的存储结构. c1 r8 m4 Y: K& z d/ c4 m
相同点:/ ~% t5 J6 g+ p& [: Z
" c7 X2 h1 h8 V+ ` W: L7 d
1块 = 16扇区 = 64k字节,1扇区 = 16页 = 4k字节,1页 = 256字节。1 o: Z/ [; i. g: ?6 x) b
只有三种擦除方式:扇区擦除 、 块擦除 和 全片擦除。
+ }1 b8 o5 L: [* W& S写操作一次可以写1~256字节,最多一次写一页256字节。' K3 ?; M6 U) x, t
不同点: 容量和内存空间地址不同,具体如下表所示:
4 f& b2 u2 ]& q. H* v
; z: e) j9 ]& a' o
+ n8 j! x+ n7 [
5 y6 g7 }! T8 y% {5 Z6 I
2. 引脚接口6 V9 J: m4 \6 N5 U
下面只介绍标准SPI接口,接口如下图所示:3 Q# P' S& R) P- D
2 u0 Z' |+ w& q( @: r
, [7 A5 i) A8 r9 s) W. Y3 t
; y+ @6 ^3 O6 _
片选引脚:/CS. C4 A3 `3 V' B! G6 H
(1)当CS引脚为高电平时,芯片被禁能,DO引脚高阻态,不能进行读写操作。
! A+ F/ U4 h2 k$ r m(2)当CS引脚为低电平时,芯片被使能,能进行读写操作。
) E. a( u3 }/ g3 g 上电后,执行一条新指令之前必须使CS引脚先有一个下降沿。
+ r+ ]( a+ s4 ~2 _
5 w7 k, a* ~% f3 H3 J数据输出引脚:DO(IO1)
, I D- G% T% o9 t) ?标准SPI模式: CLK上升沿捕获地址和命令,下降沿输出数据。
2 K2 F0 G9 E5 f+ LQSPI模式: 双向数据传输 IO1。
E5 d' v0 X) a' `+ ^/ b0 g& F2 ]4 F$ B9 g4 d7 o# o5 l
写保护引脚:/WP(IO2)0 N% B4 b- b% |1 u$ Z
标准SPI模式:
0 s) d- [7 N# D4 w- Q- M写保护引脚可以被用来保护状态寄存器不被意外改写。
) B; N+ {8 x; P: ~/ b0 n- Y(1)当WP引脚为高电平时,芯片写保护失能,可以正常写入数据。
2 }7 E6 Y0 p5 U# X, B(2)当WP引脚为低电平时,芯片写保护使能,不可以正常写入数据。% h7 l8 A% ^0 o+ ^
QSPI模式: 双向数据传输 IO2。
8 T5 U9 P* d1 S! x9 I& G! ]. E. q4 g0 p3 Y$ m% H
地:GND. |) _; Y/ E f$ m$ U: `: n
电源地2 u5 R! c; j* X: w5 X
9 y1 z# {. @; _
数据输入引脚:DI(IO0)
% d+ J+ i6 Y- p+ E9 k标准SPI模式:4 R. [1 @% C! k5 I2 [
数据、地址和命令从DI引脚送到芯片内部,在CLK引脚的上升沿捕获。7 x$ O9 f d; h7 o7 @0 t% ]
QSPI模式: 双向数据传输 IO0。
( ~ x+ }% `0 J6 c7 x! D; ^% P4 T
3 z* h0 B9 n: b' Z- S. v串行时钟引脚:CLK& y5 T4 T' n; \, H6 x
SPI时钟引脚,为输入输出提供时序。
8 n# I. T2 @' y6 d' d, I3 K: @9 }8 x* |; M9 @3 K) ?, u
保持引脚:/HOLD(IO3)
* J+ e4 n' c4 e T, w, I8 P/ e标准SPI模式:, ~1 y4 p @# g9 k W) O
当CS引脚为低电平时
2 R, L9 y1 g, a+ J2 `4 \7 K(1)当HOLD为低电平时,DO引脚处于高阻态状态,而且也会忽略DIO和CLK引脚上的信号。
2 z) V9 z! O" r* e: N8 \1 U, V(2)当HOLD为高电平时,芯片恢复正常工作。
K; h- N) R0 _- P% E- LQSPI模式: 双向数据传输 IO3。
5 l1 [6 [* j- b6 X$ q. W
: p, y& t, ?' a1 E) G' B电源:VCC
8 n9 u! X1 q' U4 U电源正极: O# g5 r9 S3 Q" C% |. M
d( n8 \. N) V" j" Y0 e
3. 原理图( v. v' x0 T: Y0 O6 v6 {
* }* R/ E) }; f+ I" P
2 N2 I4 k. w0 u) J; o2 @
; H( I7 u4 Y8 U$ E" C) G4. 内部结构框架图
2 O* F; m$ ^/ f0 q. Z+ g) Z5 n) X5 D2 F+ x
* S6 {$ l) R/ {7 R5 N- S
0 @: d& M# l4 F* ^8 D" J
5. 型号ID9 @* m. ]7 q' i* V
W25Qxx 系列 Flash 存储器支持 JEDEC 标准,具有唯一的 64 位识别序列号,方便区别芯片型号,具体如下表所示:
; m+ H, S `- Y7 z+ [9 g
$ p+ R' N% S8 P0 j% J6 l/ [) V( z Z
1 P1 z- c0 R/ `3 A; `+ K, _+ R6 X. K, }$ C
二、W25Qxx系列芯片----工作原理
; J8 U4 [" V7 ~* t& c" F' N0 z) P. N' F1. SPI 运行方式
% i, A8 A6 }2 l' L! IW25Qxx系列芯片支持以下两种SPI通信方式:7 J% B9 B: m, V
模式0: CPOL = 0,CPHA = 0. }& O( _; p% s9 g+ c; A. B# k, T! w5 g
模式3: CPOL = 1,CPHA = 1
f3 X( M4 ^. l X* S! `! R. c; y# k
2. W25Qxx系列芯片----状态寄存器& ]% T+ M9 d4 a$ u$ w, D# a
注:这里是记录所有W25Qxx系列芯片的状态寄存器,有些型号的状态寄存器,没有全部功能。0 L. t: w4 p. T* Y* h0 u9 a* i
: Z9 ]! J! h R! m
状态寄存器1
7 X. _2 g: H6 X0 }) \# m0 y) b/ \; c7 Y$ \& Z
7 U4 M. n7 [6 R" ^0 ~, q% M4 c
) b+ q$ j( W6 b4 g/ a! X: KS0----总线忙标志位(BUSY). Y7 ]* h- x2 F. |- ?3 f! o
在执行页编程、扇区擦除、块区擦除、芯片擦除以及写状态寄存器指令时,该位被硬件自动置1。这时候,除了读状态寄存器指令外的所有操作指令都会被芯片忽略。
! d5 n' h* f; U. Y当芯片执行完这些指令后,硬件会自动将该位清0,表示芯片器件可以接收其他的指令。( @7 _) c7 U, f0 V: j. C) K6 P
4 N# n$ X6 _7 ? r7 c+ ^+ [
S1----写保护位(WEL)
( Q4 C( \, f2 k2 i3 _% q执行完写使能指令后,该位置1
- \* L$ V& j# b* ?+ W. C O: n7 t当芯片掉电后和执行写禁能、页编程、扇区擦除、块区擦除以及芯片擦除指令都会进入写保护状态,该位置0
" m: V% b1 t2 G8 p. E) z5 ?7 l! p
/ L( ~- G& T+ R9 k% HS2、S3、S4----块区保护位(BP2、BP1、BP0)
$ O7 i% Z% H ^6 H这3个位默认状态为0,即块区处于未保护状态。可以利用“写状态寄存器”指令对这几个位进行置1来达到块区保护的目的。块区保护状态为:没有保护、部分保护和全部保护状态。) B- }) E& S" O8 M
当状态寄存器的SRP位为1或读写保护管脚(/WP)为低电平时,这3个位不可被更改。
* Q7 O/ G: o0 y) [7 E* Z! E1 B# `7 ^) T4 M6 l+ S2 d2 V! D
S5----底部和顶部块保护位(TB)
$ q W) {" o9 L" g6 A! Q( N% k% u此位默认值为0,可以利用“写状态寄存器”指令对这个位进行置1或清零。9 W2 ~5 q3 D: E0 U3 ]6 h' i4 T
当TB = 0时,表示保护位从顶部开始;
( r3 [& k3 F2 ]; w) k+ h当TB = 1时,表示保护位从底部开始。
+ W' l# P/ [( u& I当状态寄存器的SRP位为1或读写保护管脚(/WP)为低电平时,这个位不可被更改。- z0 N+ u+ j. t4 g% Q
7 C+ ]) {; |; G' I! ]S6----扇区/块保护(SEC)
9 L9 r$ _; t$ T! a, m# U3 [1 M$ s& j此位默认值为0,可以利用“写状态寄存器”指令对这个位进行置1或清零。
M* p) E& x- ^" \, M7 c$ ~4 U当SEC = 0时,表示每次保护的区域大小为4K;
" `& ~. S# a3 N8 x" h6 R9 a% L当SEC = 1时,表示每次保护的区域大小为64K。
, Z: z6 A3 F* T3 X' d" X% b3 Z w: V; T! {
状态寄存器2
s N8 O' v' E- \% P1 A
2 n8 m6 z3 v O3 V
2 o) {3 K+ r! Z3 H2 M
s. J( }1 T% m2 p# j b, @S7、S8----状态寄存器保护位(SRP、SRL)
" w! J1 h. z" w' n这两个位的默认值为0,可以利用“写状态寄存器”指令对这个位进行置1或清零。4 _9 {1 v" [ T6 g
这两位和读写保护管脚(/WP)决定了状态寄存器写保护的方式。
" u. m* `# B4 x状态寄存器写保护的方式有:软件保护,硬件保护、电源锁定或一次性可编程(OTP)保护。
: h S2 p+ |, Z7 e6 d
i" C. [7 ~5 ~; zS9----快速SPI通讯使能(QE)
. |/ }) F# ~( V6 E X4 k3 N1 k此位默认值为0,可以利用“写状态寄存器”指令对这个位进行置1或清零。
# ?) N0 B/ m1 i) T7 K当QE = 0时,设置为标准速度模式或快速模式,保持管脚(/HOLE)和读写保护管脚(/WP)启用;2 T" n$ Q6 X/ ^! F3 I5 [ K9 l
当QE = 1时,设置为高速模式,保持管脚(/HOLE)和读写保护管脚(/WP)被设置为IO2和IO3功能使用。+ b0 w2 z% t# W. C- e3 m* ^
1 f+ Q+ H3 X6 b9 O% ~! n- ]- E
S10、S11、S12、S13----安全寄存器锁位(LB3、LB2、LB1)$ h# ] h/ u3 N6 ?: d
LB3-1的默认状态为0,安全寄存器被解锁。 O8 b8 ^; l3 n# k
可以使用写状态寄存器指令将LB3-1单独设置为1。* i# B. s8 R% z% I X
LB3-1是一次性可编程(OTP),一旦它设置为1,相应的256字节安全寄存器将成为永久只读。" T8 d" i! D. ? C
, ?8 }+ b& s+ }S14----补码保护位(CMP)& [: C2 K& R- R( q
它与SEC、TB、BP2、BP1和BP0位结合使用,为阵列保护提供更大的灵活性。
: M0 [, D! T1 R) } l$ w! M1 R一旦CMP设置为1,之前SEC、TB、BP2、BP1和BP0设置的阵列保护将被逆转。例如:' G" w: X# o& J
当CMP=0时,一个最高64KB的块可以被保护,而数组的其他部分则不受保护;: k& N1 E% B7 V7 H. M [1 W
当CMP=1时,最上面的64KB块将成为不受保护的,而数组的其余部分将成为只读的。
3 a/ D% \" g& ^6 |- ~- X, j8 F- c) Y默认设置为CMP=0。
$ r! z+ V5 }+ [0 `7 D( R ^; B' p- T* @/ @" X
S15----暂停状态位(SUS)- O7 ] K& K. Z" C' k) V
在执行**擦除/程序暂停(75h)指令后设置为1。' t- F4 y- S9 w- t0 L% x1 i
通过擦除/程序恢复 (7Ah)**指令以及下电、上电周期将SUS状态位清除为0。, n- w7 q; |- I' ?9 |+ ?% Z" M
/ ^8 v+ }- M/ t a. c6 o5 N
状态寄存器3
0 R* j5 w$ v- D2 R1 V1 k- J$ W1 Y% E2 @
0 j u7 e& d4 t' Y6 a) Q6 R8 k3 m. I8 c) ^9 q9 y i& l
S16----当前地址模式(ADS) Q) L6 q; ]" n9 y! f
表示设备当前运行的地址模式。" | S3 a( W! f4 m" l3 T: b
当ADS=0时,设备处于3字节地址模式,! s, A2 _; H6 q: ]3 E% \- o0 h) d
当ADS=1时,设备处于4字节地址模式。. e, `3 I6 j" C7 Y4 p3 }. ]
- C4 y/ u W" Z) ? CS17----启动时地址模式(ADP)
T9 i* v# h0 A: m& G决定设备上电或复位时的初始地址模式,该位仅在上电或设备复位初始化期间使用。: x: K8 @5 f, J3 ]# W& B& o
当ADP=0(出厂默认)时,设备将启动到3字节地址模式,扩展地址寄存器必须用于访问超过128Mb的内存区域。当ADP=1时,设备将直接启动到4字节地址模式。
! @! n2 {. ]- ?- d% z2 R
- U1 \8 ]5 k2 }9 Y/ r$ oS18----写保护方案(WPS) [/ I4 f0 E( g/ g7 d- U" d
当WPS=0时,设备将使用CMP、SEC、TB、BP[2:0]位的组合来保护存储阵列的特定区域。 d- p8 H, z7 s
当WPS=1时,设备将使用单独块锁来保护任何单独的扇区或块。
# q3 F6 c& l; ?; Z3 @设备上电或复位后,所有单个块锁定位的缺省值为1。
8 h# U4 h0 P/ r' M
+ I; r2 k0 \6 v0 Q3 J) _" TS22、S21 ---- 输出信号强度(DRV1、DRV0)
9 z/ p, \7 `/ u2 D* \
3 f$ U1 e- N8 T8 `$ Q
4 i0 p6 J1 e9 _, D9 X
: N0 {' q4 T: TS23----HOLD/RST引脚功能选择
7 R$ v3 q4 _0 O当HOLD/RST=0(出厂设置)时,引脚为/HOLD。$ z% @$ j: d6 m' Q8 [/ a
当HOLD/RST=1时,引脚为/RESET。
' D( p* K4 D4 D3 d! n' y. o但是,只有当QE=0时,/HOLD或/RESET函数才可用。
4 L2 x8 l" N1 q8 z( G3 E+ NQE设置为1时,关闭/HOLD和/RESET功能,引脚为专用数据I/O引脚。& q! ]# f8 s8 ` l7 W' c
4 G+ O; k, f$ r4 k) r7 V4 W3. W25Qxx系列芯片----常用操作命令
' _3 Q. Q/ K4 |7 W4 C% }0 M(1)单字节操作7 D3 z( n( Q9 g0 A
单字节操作,只往芯片中写入1字节的操作命令,具体代码如下:+ T- d$ F$ k! O- L9 ~5 S
5 R( ]$ T" D. C5 X9 v
- void W25QXX_Write_Enable(void) //写使能 4 m2 L1 E* N9 N, w/ Y% J
- {' V* }1 j* k, S$ X6 ?5 H! l
- W25QXX_CS(0); //拉低片选CS引脚---使能芯片7 t& m* I; V" _4 c, V a5 C
- W25QXX_ReadWriteByte(0x06); //写入1字节操作命令
3 ^+ U4 U9 x: c- A3 V - W25QXX_CS(1); //拉高片选CS引脚---关闭芯片
: x/ e6 Z) c' D: W, L$ w4 m( W - }
复制代码 . ?! f( K% {4 X
操作命令 如下表所示:9 z- u" J/ I& h: j$ W
2 }& I0 k; ~( h: X, `' e
6 P5 ~7 Q8 N: x: L% S
+ A5 q6 F! O! a
9 _ n+ {% I% ]. ]注:如果想要实现其他功能,替换操作指令数据,便可实现功能。
9 [9 R$ C' S4 f* z, R: t9 P: Y/ W6 s. Q# L; R0 D' Z
(2)双字节操作
' t3 i& C& d( n2 _( e3 M$ ~双字节操作,先往芯片中写入1字节的操作命令,接下来是读取/写入的字节数据。. y7 W! F' E& y$ O0 ~/ h0 ]+ x
具体代码如下:2 B- ]4 C D. V
5 T" \- r9 u$ y- //读取1字节数据3 f* v( ~! r& {: j6 r: O$ {
- uint8_t W25QXX_ReadSR(void)//读取状态寄存器
+ E" w0 P' g B& {& Q% C - {
) F0 t Z, m! f. q' g/ _ - uint8_t data=0;
7 }. V x, y4 c o/ J - W25QXX_CS(0); //拉低片选CS引脚---使能芯片3 S7 R# b$ t; [- |, X' O% m Q
- W25QXX_ReadWriteByte(0x05); //写入1字节操作命令
$ G$ }/ X/ F# U: Z8 `3 \* \! H( Z! Z, w - data=W25QXX_ReadWriteByte(0Xff); //读取1字节数据+ L0 r- K0 D$ z# t7 }% d
- W25QXX_CS(1); //拉高片选CS引脚---取消片选
( g$ Y8 T3 I t - return data;4 o" g8 ^3 A' {; V- @1 c, u
- }
' ?) R& F) I: P0 w4 B8 }5 L - $ }- ~# x0 F$ O' v' V* _+ E# S- {
- //写入1字节数据% X2 f5 w+ Q% I K, Y4 k) N. g
- void W25QXX_WriteSR(uint8_t data)//写状态寄存器
/ K1 q4 Y: v1 A - {
) l3 n0 @& U$ Z - W25QXX_CS(0); //拉低片选CS引脚---使能芯片
F/ Y4 P' }( R" n' Z - W25QXX_ReadWriteByte(0x01); //写入1字节操作命令# Y/ I2 n/ e, o3 z) {/ B1 T
- W25QXX_ReadWriteByte(data); //写入1字节数据9 o" T& M8 d8 Q! C$ I
- W25QXX_CS(1); //拉高片选CS引脚---取消片选( F$ q4 O0 q+ V" O
- }+ A3 t4 W$ `/ \ Q, m
复制代码
2 K% A$ c/ p- I操作命令 如下表所示:- U: J3 |- |& m8 _0 D) P5 V
$ _( h" e+ e2 R& M
5 i, F1 A: J; S
5 m7 ^5 h* x) z. C8 Q注:如果想要实现其他功能,替换操作指令数据,便可实现功能。
' T+ z, ~3 S( t$ k
$ n- d* q5 D6 `7 o(3)读取ID操作
* i2 S$ [) ^% w: ~2 p9 d/ ?具体代码如下:
5 J0 h' `! k# U. k, t6 Z8 z9 W+ o/ Z0 ~) z ?* i n
- uint16_t W25QXX_ReadID(void)//读取芯片ID! ]# g; @, f2 a! v7 Q! i
- {
* e8 \- D, O& j - uint16_t ID = 0; 9 g& v. t7 h' h6 ]8 s- q
- W25QXX_CS(0); //拉低片选CS引脚---使能芯片 ) O/ m5 x& r0 r3 c
- W25QXX_ReadWriteByte(0x90); //发送读取ID命令
8 Y6 _: Y3 n. X' A* y - W25QXX_ReadWriteByte(0x00);
1 V; J8 ^- u- P" X2 y- x - W25QXX_ReadWriteByte(0x00);
8 H2 I& K) m, ^ - W25QXX_ReadWriteByte(0x00); ) }) V$ u3 ^+ }. x
- ID|=W25QXX_ReadWriteByte(0xFF)<<8; 4 d# u( m; r- f9 T' J0 v+ D3 m" n
- ID|=W25QXX_ReadWriteByte(0xFF);
0 _) ^0 B4 T7 h - W25QXX_CS(1); //拉高片选CS引脚---取消片选
% j) _5 a2 W! a" [ - return ID;+ |, Q" w4 Z' ~- [% m
- }
复制代码 - S8 j; L0 f% R7 L
操作命令 如下表所示:
4 p- w4 e1 V0 c; V
3 X/ ?4 ^! Z, U3 q
1 v/ R- V. P* h" F- \. ~* y/ K. o3 j" h# K& |
指令名称 指令数据(hex) 字节1 字节2 字节3 字节4 字节5 功能
1 x) I) A" w V2 r! G) T& ADevice ID 0xAB 0x00 0x00 0x00 (ID7-ID0) 读取设备ID4 Y" F8 u: Z9 O4 G8 W) V8 q
Manufacturer/Device ID 0x90 0x00 0x00 0x00 (MF7-MF0) (ID7-ID0) 读取制造商+设备ID0 [; h3 s- n& z1 \' w" D6 S& M! m
JEDEC ID 0x9F (MF7-MF0) (ID15-ID8) (ID7-ID0) 读取全部ID5 |1 S }7 ?3 W0 y+ `& h" X* w
Read Unique ID 0x4B 0x00 0x00 0x00 0x00 (UID63-0) 读取唯一ID号
- l7 z4 J% o `* i注:如果想要实现其他功能,替换操作指令数据,便可实现功能。
8 r/ ?6 j c8 u3 y1 ^8 E6 B$ B4 L5 G4 d) q3 Q! w
(4)带地址操作' g) z( @- ^7 Q( ]
带地址操作主要分两种:) f1 R& x/ k1 O5 `" L* x& D
3字节地址:W25Qxx系列芯片都可以使用。; w9 U: a, _, p7 z: Y0 R+ R6 X
4字节地址:只有W25Q256和W25Q512可用。
8 h& Z5 ~( t4 e3 d" h! T. p9 Q
3 n. i4 U! K' C3 k* a3字节地址" I4 {, d; g8 n2 I# X
具体代码如下:, N2 q; x8 y7 \8 \) F% F8 Z
- //读取数据4 J# i& f. E/ W1 y/ c: Q" i
- void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead) " ~4 i6 S$ g1 J: h) k5 S
- {
- J" N' u0 v& Q1 l) M - W25QXX_CS(0); //拉低片选CS引脚---使能芯片! f Y" o* A' Y
- W25QXX_ReadWriteByte(0x03); //发送读取命令 7 T' l+ F4 _9 _
- W25QXX_ReadWriteByte((uint8_t)((ReadAddr)>>16)); //发送24bit地址 / i' ^+ C6 O; n8 m" D- P- b+ V
- W25QXX_ReadWriteByte((uint8_t)((ReadAddr)>>8)); # s: _3 P9 j! @$ j' G
- W25QXX_ReadWriteByte((uint8_t)ReadAddr); " J+ M7 u8 E* U' M/ h' o
- for(uint16_t i=0;i<NumByteToRead;i++)//可读多个数据
2 F, \5 ?/ Q; S - { ) t) K; H$ H) Z- D& M# [
- pBuffer<i>=W25QXX_ReadWriteByte(0XFF); //循环读数
9 w2 D1 `+ {3 G" y6 Y7 @ - }3 I! I; L9 t+ c; w# G) @0 F
- W25QXX_CS(1); 6 R; r' O9 M$ v5 D/ D% o9 ?1 V+ z
- } 2 G; V; p( H& x D) B$ }
- 5 M, D$ C7 c9 v' E- C' R
- //写入数据
0 [7 W) [! A1 U$ K9 y - void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)) Y8 Y: N- t+ M0 v" p! H6 [
- {
- Y$ H" q: K4 f; c- l3 y: w& k' t - W25QXX_Write_Enable(); //写使能8 _$ J. [- `' [& ^: M4 k
- W25QXX_CS(0); //使能器件
" B/ u6 Z1 Z/ L4 `9 T2 [8 Z - W25QXX_ReadWriteByte(0x02); //发送页写命令 J: }$ l4 ^! r8 U6 }# }4 u
- W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址
* r3 {3 o6 }/ l7 g - W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>8));
9 t# h4 A9 `/ S4 ~) T1 W* n - W25QXX_ReadWriteByte((uint8_t)WriteAddr);
8 J; ~+ O0 W; {1 |9 j, w6 _/ N* @ - for(uint16_t i=0;i<NumByteToWrite;i++)//可写多个数据,最多256个字节一页数据
4 t* B1 W! K1 r2 J6 U - {
* L1 i3 b, c$ W8 C - W25QXX_ReadWriteByte(pBuffer<i>);//循环写数
+ c' I) G- Q5 |7 a( n - }' Z1 ^' P& R3 g6 L& a
- W25QXX_CS(1); //取消片选 / @" t5 P3 `4 y# V4 T
- W25QXX_Wait_Busy(); //等待写入结束, w& {; Y9 I/ x; r& j; V4 E
- } </i></i>
复制代码
/ i# U) v8 S: K( d# r3 P操作命令 如下表所示:4 P6 h5 [+ Y& F: A' d1 W) P. ?5 o
$ H( L; E4 u9 S6 m3 V* A# c+ C
) K8 f! K1 W0 d+ V2 _, ~7 D3 C; ?" {, a* p) T. ~
4字节地址
6 x1 X. s8 F H" D, p) B) O: @! V具体代码如下:
& G: b+ ~* D0 ?8 |- //启用4字节地址模式 ' ^2 h7 [$ l! @
- void W25QXX_Enter_4Byte()
8 k1 k' H1 T, t# N - {
0 h2 o Z" f8 x" G9 T - W25QXX_CS(0); //拉低片选CS引脚---使能芯片
0 [& u& _7 C0 }! c I$ y) Q - W25QXX_ReadWriteByte(0xB7); //写入1字节操作命令" W# i" E9 q5 A
- W25QXX_CS(1); //拉高片选CS引脚---关闭芯片
" I: V/ P! {# B0 r4 c - }: E" h7 F2 f3 J, g8 h0 j ?
; a2 ]5 u$ F/ p* _4 m- //退出4字节地址模式
+ H5 @5 ~; `0 L4 f3 p% Y, w8 Z - void W25QXX_Exit_4Byte()
3 @- w4 r( }, s* `/ r0 ~# n2 z - {
. h, c. Z* n0 t& [! H; q) Q0 ~" m$ T - W25QXX_CS(0); //拉低片选CS引脚---使能芯片) i# a8 j/ o! T d0 D- B
- W25QXX_ReadWriteByte(0xE9); //写入1字节操作命令! ]) N: Z1 c" |- G- o# Z
- W25QXX_CS(1); //拉高片选CS引脚---关闭芯片
' F% k- @2 j3 X# B - }
& n B. Q" ^4 ^% D( J2 k7 V! ] - / V: `/ }! {7 |& Z5 t7 C- h- h1 T! |
- //读取数据
1 W- u% `, D! n, U - void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)
5 A6 S4 F* ?% } - {
: F( }( N; s+ r+ v# C' q* U- I5 N - W25QXX_CS(0); //拉低片选CS引脚---使能芯片
0 }! y" ]% w- O. I: h& l U" f - W25QXX_ReadWriteByte(0x13); //发送4字节地址读取命令
. p2 h# s# B6 S- I - W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>24));//发送32bit地址
( V* _8 D/ o4 T/ |5 W% w1 B - W25QXX_ReadWriteByte((uint8_t)((ReadAddr)>>16)); * _2 o( I- y1 Q- n, b: d1 Z
- W25QXX_ReadWriteByte((uint8_t)((ReadAddr)>>8)); 8 \, [! F; z# e7 V4 Y# n. k
- W25QXX_ReadWriteByte((uint8_t)ReadAddr);
Z" @+ ^4 @ E' P: t* ] - for(uint16_t i=0;i<NumByteToRead;i++)//可读多个数据
+ L; k! ?. h2 [ - {
& c8 c, s7 g$ k8 E9 s - pBuffer=W25QXX_ReadWriteByte(0XFF); //循环读数 [9 r; G, V+ a7 p7 ~; ^
- }5 M5 w( A( R. k$ z& ^0 u
- W25QXX_CS(1); P+ k2 E5 k3 z' _: b8 c2 T, _! H0 m
- }
+ u2 h# }' z+ P$ z - : Z+ \2 l8 t0 l3 K }
- //写入数据
3 a3 {' ?4 F8 f1 P8 q1 b( q - void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite): g2 a3 f( X3 e
- {
L) ~3 }( f3 d s6 q - W25QXX_Write_Enable(); //写使能
" D, Y& e6 k! [3 |) T - W25QXX_CS(0); //使能器件
4 B, j. u! P* Y# w1 @: U* g - W25QXX_ReadWriteByte(0x12); //发送4字节地址页写命令
, B, S' S; Y, _ a) a4 I8 ` - W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>24));//发送32bit地址
( `" c) _ P5 I7 c - W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>16));
( u) i* c) o2 m' e) b - W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>8));
6 ~/ ~# v0 ]9 y2 ? - W25QXX_ReadWriteByte((uint8_t)WriteAddr);
+ A# G( J+ i" ^% e5 [: O" L* \% ` - for(uint16_t i=0;i<NumByteToWrite;i++)//可写多个数据,最多256个字节一页数据
) _) b9 V: }$ i, g7 ~ - {
+ @' s( S s M @ - W25QXX_ReadWriteByte(pBuffer);//循环写数
) U9 I* w- N/ B2 Y& x - }
* h f8 z/ m! d+ Z F) f9 P; r - W25QXX_CS(1); //取消片选
' G/ v" |5 e) o- U' U% U5 c6 e: k - W25QXX_Wait_Busy(); //等待写入结束" N- [6 M5 L& [) R* G! B" a. g. V. S
- }
复制代码 6 M2 L! K5 _2 r9 _) w! y
注:如果想要实现4字节地址,需要启用4字节地址模式。
Z& h8 ~* l& J6 T0 o" [* C/ p
4 w/ R; v3 h% m4 m) d操作命令 如下表所示:. G9 |- v' q8 y3 D' p
, w+ F' i+ \% m5 u5 g( n( a H
6 v* w0 A8 Q; G5 f, q2 k/ [————————————————
0 D6 {2 |; p' `& Q% }版权声明:根号五
, @# M0 {4 S9 Q: C' a1 c) s, H
- e% G+ g8 Y- C! M6 K( U) c: E+ Z& w; S& R; `
G S9 X* \* f, w3 s. U5 J. T* o |