扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

【CW32无线抄表项目】外置FlashW25QFV介绍

9小时前
109
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

W25QFV基础内容

1.SPI通信基础知识

SPI(Serial Peripheral Interface)是同步串行外设接口,它就像一个“全双工”的传送带,单片机和 Flash 之间可以同时收发数据。

四根线逻辑

SCK (Serial Clock):时钟线,由主机(CW32)提供,决定传输节奏。

MOSI (Master Out Slave In):主机输出,从机输入。数据从 CW32 流向 W25Q。

MISO (Master In Slave Out):主机输入,从机输出。数据从 W25Q 流回 CW32。

CS/NSS (Chip Select):片选信号,低电平有效。它是整个通信的“开关”,必须先拉低才能通话。

通信模式:W25Q 系列通常支持 Mode 0 和 Mode 3。 咱们在 CW32 中配置的是 SPI_CPOL_High 和 SPI_CPHA_2Edge(Mode 3),确保在 48MHz 高频下数据采样依然稳定。

W25Q64 存储架构(必须理解)

很多人分不清扇区和块,导致擦除时误删数据。记住这个公式:

1 Page (页) = 256 字节:写入的基本单位。

1 Sector (扇区) = 16 页 = 4KB擦除的最小单位

1 Block (块) = 16 扇区 = 64KB:大面积清空的单位。

总容量:128 个块 = 8MB

核心规则:Flash 的物理特性是“只能把 1 变成 0”。因此,写入新数据前必须先擦除(变为全 0xFF)。

硬件连接与引脚分配

SPI2 接口分配

在 CW32F030 中,我们选择了 SPI2 避开 PAN3031 无线模块的 SPI1。

PB12 (CS):软件控制片选。

PB10 (SCK):时钟。

PB14 (MISO):数据接收。

PB15 (MOSI):数据发送。

注意事项

供电:严禁接 5V,必须接 3.3V

保护引脚:若模块上有 WP 或 HOLD,必须接 3.3V,否则无法擦写。

硬内部闪存结构

1.W25Q64FV 串行闪存(Serial Flash)的内部架构框图(Block Diagram)

2.存储层级结构(右侧部分:仓库的组织)

这部分的图表展示了 W25Q64 的“仓库”是如何划分房间的:

Block(块):整个芯片共有 128 个 Block(从 Block 0 到 Block 127),每个 Block 的容量是 64KB

Sector(扇区):每个 Block 内部又划分为 16 个 Sector(从 Sector 0 到 Sector 15),每个 Sector 的容量是 4KB

这就是为什么你的程序中 SPI_FLASH_SectorErase 是以 4KB 为单位擦除的,因为它对应图中左侧的小方格。

Page(页):在最底层,数据被存放在 Page 中。图中下方的 256-Byte Page Buffer 说明了每次写入(Program)操作的最大单位是 256 字节

地址范围示例

Sector 0 的地址范围是 000000h 到 000FFFh

Sector 1 的地址范围是 001000h 到 001FFFh

3.控制与逻辑(中间部分:管理办公室)

这部分展示了芯片处理你指令的“大脑”:

SPI Command & Control Logic:这是指挥中心。它接收你通过单片机发送的 03h(读)、02h(写)、06h(写使能)等指令,并将其翻译成内部操作。

Status Register(状态寄存器:这就是我们之前用来解除“写保护”的地方。它连接着 Write Control Logic,控制着芯片是否允许被擦除或写入。

High Voltage Generators:Flash 存储需要高电压来“泵”电子进入存储单元。这个模块负责产生擦除和编程所需的高压。

4.外部接口(左侧部分:大门)

这是你连接单片机的 6 根线:

/CS, CLK, DI(IO0), DO(IO1):标准的 SPI 通信引脚。

/WP (Write Protect) 和 /HOLD:硬件保护和挂起引脚。图中显示它们直接连向控制逻辑。正如我们之前讨论的,如果模块上没有这些引脚,它们通常在 PCB 内部被连到了高电平

芯片初始化与协议逻辑

1.上电与初始化 (Power On & Initialization)

起始点:当芯片接通电源(Power On)后,它并不能立即工作,而是先进入 设备初始化(Device Initialization) 阶段。

默认模式:初始化完成后,芯片会默认进入 标准 SPI(Standard SPI)模式。在这个模式下,它同时支持你之前提到的双线(Dual SPI)和四线(Quad SPI)指令。

2.模式切换:SPI ↔ QPI

图中的中间部分展示了如何在两种主要的通信协议之间转换:

进入 QPI (Enable QPI):通过发送指令 38h,芯片可以从 SPI 模式切换到 QPI(Quad Peripheral Interface)操作 模式。

注:QPI 模式下,指令本身也通过 4 根线发送,速度比标准 SPI 更快。

退出 QPI (Disable QPI):通过发送指令 FFh,芯片会退回到标准的 SPI 模式。

3.软件复位机制 (Reset)

图中两条回环的曲线展示了软件复位的逻辑:

复位指令串:无论是处于 SPI 还是 QPI 模式,只要连续发送 66h (Reset Enable) + 99h (Reset) 这一组指令,芯片就会强制退回到“设备初始化”状态。

意义:如果你在代码运行中发现芯片“卡死”或不响应(比如你之前遇到的 JedecID 读出全为 0xFF 的情况),可以通过这组复位指令尝试让芯片重新初始化,而无需物理断电。

4. SPI 与 QPI 操作模式 (6.1 节)

这部分定义了单片机(主机)与 Flash(从机)之间“对话”的物理方式。

标准 SPI (Standard SPI)

Mode 0:空闲时 CLK 为低电平。

Mode 3:空闲时 CLK 为高电平。

信号线:使用 CLK、/CS、DI (数据入) 和 DO (数据出) 四根线。

时序:在 CLK 上升沿写入数据,在下降沿读取数据。

模式支持:支持 Mode 0 和 Mode 3

多线增强模式 (Dual / Quad SPI)

Dual SPI:将 DI 和 DO 变成双向引脚(IO0, IO1),速度翻倍。

Quad SPI:利用所有四根数据线(IO0-IO3),速度提升 4-6 倍。需要先设置状态寄存器中的 QE 位 才能开启。

QPI 模式

一种极速模式,连“指令码”都通过 4 根线发送(原本需要 8 个时钟,现在只需 2 个)。通过 38h 指令切换进入。

5.硬件辅助功能 (6.1.5 节)

暂停功能 (Hold Function)

当 /CS 为低(选中状态)时,拉低 /HOLD 引脚可以暂停当前的 SPI 通信。

应用场景:如果 SPI 总线上挂了多个设备,而单片机突然需要处理更高优先级的任务,可以先“挂起”Flash,处理完后再恢复,无需重新发送指令。注意:此功能在 Quad/QPI 模式下不可用。

6.写入保护机制 (6.2 节)

这是你之前遇到“写不进去”问题的理论根源。为了防止由于噪声或意外掉电导致数据损坏,芯片设计了多层“锁”:

上电自动锁

VCC 门限:电压低于阈值时,芯片自动复位并禁止所有操作。

启动延迟:上电后有一段延迟时间 (tPUW),期间禁止编程和擦除指令。

写使能锁 (WEL)

关键点:上电后默认是“写禁止”状态。

逻辑:在执行页编程、扇区擦除或写状态寄存器前,必须先发送 Write Enable (06h) 指令。

自动回锁:完成一次编程或擦除后,芯片会自动回到“写禁止”状态。

软件/硬件组合锁

软件锁:通过状态寄存器中的 BP0-BP2 位,可以锁定特定区域(甚至整片区域)为只读。

硬件锁:配合 /WP 引脚。如果软件锁被激活且 /WP 为低,则状态寄存器无法被更改。

7.开发者 Tips

关于时钟:确认你的 CW32 SPI 极性配置与手册中的 Mode 0 或 Mode 3 匹配。

关于速度:虽然标准 SPI 简单,但对于 500 个节点的大数据上报,未来可以考虑开启 Dual/Quad 模式提速。

关于稳定:在重要擦写操作前,务必检查状态寄存器的 WEL 位。

关于防死机:如果通信紊乱,建议发送软件复位指令序列 (66h + 99h)。

8.W25Q64FV 状态寄存器

8.1 实时状态位:芯片在干什么?

这两位是你编写底层驱动函数(如 WaitForWriteEnd)时必须频繁读取的。

BUSY (S0 - 只读)

功能:当芯片正在执行页编程、扇区/块擦除或写状态寄存器时,该位为 1

注意:此时芯片进入“闭关模式”,除了读取状态和暂停指令外,会忽略其他所有指令。

实战意义:在48MHz 系统中,如果两次写入操作之间不检查 BUSY 位,由于 CPU 跑得比 Flash 写入快得多,会导致数据丢失。

WEL (S1 - 只读)

功能:写使能锁存位。执行完 06h 指令后变为 1

复位逻辑:在掉电、执行完写入/擦除指令后,该位会自动归 0

实战意义:这解释了为什么你每写入之前都必须重新发送一次写使能指令。

8.2 存储保护位:哪些数据不准改?

这就是遇到“读 ID 正常但写不进数据”的根本原因。

BP2, BP1, BP0 (S4, S3, S2)

功能:定义 Flash 阵列中受保护(只读)的范围。默认值为 0(不保护)。

TB (S5) & SEC (S6)

TB (Top/Bottom Protect):决定从芯片的“头”开始锁,还是从“尾”开始锁。

TB = 0:从顶部(Upper)地址开始保护。

TB = 1:从底部(Lower)地址开始保护。

SEC (Sector/Block Protect):决定锁定的精度。

SEC = 0:以 64KB 的“块” 为单位进行保护。

SEC = 1:以 4KB 的“扇区” 为单位进行精细保护。

CMP (S14)

当 CMP = 0 时(默认状态):你设置的位代表“哪一小块被保护”。

例如:设置 SEC=1, TB=1, BP=001,则只有地址 000000h – 000FFFh 这 4KB 区域被锁死,其余地方都能写。

当 CMP = 1 时:逻辑完全反转,你设置的位代表“哪一小块不被保护”。

例如:同样的配置在 CMP=1 时,除了那 4KB,剩下的 8,188KB 全部变只读。这非常适合用来锁定整个数据库,只留出一个小窗口写当前配置。

8.3 系统配置与安全:高级功能

SRP0 & SRP1 (S7, S8)

功能:定义状态寄存器本身的保护方式(软件、硬件、掉电锁定或永久锁定)。

实战对照表

SUS (Suspend Status)

功能:暂停指示灯。

状态标识:这是一个只读位

触发条件:当你发送 75h (Erase/Program Suspend) 指令后,该位会被硬件自动置为 1

清除条件:当你发送 7Ah (Resume) 指令,或者芯片掉电重启后,该位会归 0

LB1-LB3 (S11-S13)

功能安全寄存器锁定位。这是一次性编程(OTP)的。一旦锁定,对应的安全寄存器将永久变为只读。

QE (S9 - Quad Enable)

功能:开启四线 SPI/QPI 模式的“开关”。

代价:一旦开启 QE,芯片上的 WP 和 HOLD 引脚功能会被禁用,转为数据线 IO2 和 IO3。

1.SPI 线数的演变:从“单车道”到“四车道”

标准的 SPI 确实是通过 DI(数据入)和 DO(数据出)进行单位(1-bit)传输的,但 W25Q64FV 支持多种“提速”模式:

标准 SPI (Standard SPI):使用 DI 和 DO。 每次时钟周期只传 1 位数据,就像单车道。

双线 SPI (Dual SPI):将 DI 和 DO 变成 IO0 和 IO1,两根线同时传数据。 速度提升 2 到 3 倍。

四线 SPI (Quad SPI):这是最关键的突破。 它把原本用来写保护的 WP 和暂停通信的 HOLD 引脚也“征用”了,变成了 IO2 和 IO3。 这样就有 4 根线同时跑数据,速度提升 4 到 6 倍。

 

2.什么是“极速” QPI 模式?

QPI(Quad Peripheral Interface)是 Quad SPI 的“完全体”。

在普通 Quad SPI 模式下,你发送“指令”(比如读取数据)时,仍然得通过 IO0 这一根线慢慢发 8 个时钟周期。 但在 QPI 模式 下:

指令也要并传:连“指令码”和“地址”都是 4 根线一起发。

效率翻倍:发送 1 字节指令原本要 8 个时钟,现在只需要 2 个时钟

适用场景:非常适合你的网关在短时间内需要从 Flash 读取大量 500 个从机节点配置的场景。

3.为什么必须手动设置 QE 位?

这就是手册里那个 QE (Quad Enable) 位的核心作用:

引脚功能切换:默认情况下,WP 是用来防止误擦除的,HOLD 是用来暂停 SPI 的。

激活四线:当你把 QE 位置 1 时,芯片内部逻辑会彻底关掉写保护和暂停功能,把这两个引脚的控制权交给数据传输引擎,变成 IO2 和 IO3。

不可逆风险:手册警告,如果你的电路板上 WP 或 HOLD 是直接接死在 GND 上的,一旦你强行开启 QE 位,会产生硬件短路冲突!

WARNING:如果你的 WP 或 HOLD 引脚直接接了地(或者没接),严禁将 QE 位置 1,否则会引发硬件冲突。

8.4  系统配置与安全:高级功能

PROTECTED BLOCK(S)(受保护的块)

它指出了被锁定的物理块编号

物理结构:W25Q64 共有 128 个块(编号从 0 到 127),每个块的大小固定为 64KB

含义:表格中的这一项会列出具体哪些块变成了“只读”。例如,显示 124 thru 127 表示第 124、125、126、127 这四个块被锁定了。

PROTECTED ADDRESSES(受保护的地址)

它给出了被锁定区域的十六进制地址范围

寻址空间:W25Q64 的总地址范围是 000000h 到 7FFFFFh(总计 8MB)。

作用:它能让你在编写程序时,直观地通过地址判断某个变量存放在这里是否安全。例如,如果地址显示 7C0000h – 7FFFFFh,那么任何针对这个范围内地址的擦除或写入指令都会被芯片忽略。

PROTECTED DENSITY(受保护的容量)

它描述了被锁定区域的总存储大小

单位:通常以 KB 或 MB 为单位。

数值:它是受保护块数量的累加值。例如,如果保护了 4 个块,受保护容量就是 4 *64KB= 256KB;如果全片保护,则显示为 8MB 或 ALL

PROTECTED PORTION (2)(受保护的部分/比例)

它是一个描述性的标签,用来说明受保护区域在整片芯片中的位置和占比

L (Lower):代表从芯片的底部(低地址,即 0 地址处)开始向上保护。

U (Upper):代表从芯片的顶部(高地址,即 7FFFFFh 处)开始向下保护。

比例:例如 Upper 1/32 表示芯片顶部 1/32 的容量被保护。

BP2 BP1 BP0 受保护块范围 (Blocks) 受保护地址范围 (Addresses) 受保护容量 保护比例/备注
0 0 0 NONE NONE NONE 无保护(出厂默认)
0 0 1 126 和 127 7E0000h – 7FFFFFh 128 KB Upper 1/64
0 1 0 124 到 127 7C0000h – 7FFFFFh 256 KB Upper 1/32
0 1 1 120 到 127 780000h – 7FFFFFh 512 KB Upper 1/16
1 0 0 112 到 127 700000h – 7FFFFFh 1 MB Upper 1/8
1 0 1 96 到 127 600000h – 7FFFFFh 2 MB Upper 1/4
1 1 0 64 到 127 400000h – 7FFFFFh 4 MB Upper 1/2
1 1 1 0 到 127 000000h – 7FFFFFh 8 MB ALL(整片锁死)

示例1:

例如,如果你想保护最开始的 $$4text{KB$$ 扇区(存 500 个从机的配置),你需要设置:

SEC = 1 (扇区级保护)

TB = 1 (从底部地址开始)

BP[2:0] = 001

结果:地址 000000h – 000FFFh 被永久锁定,除非再次修改状态寄存器。

根据 W25Q64FV 手册的位定义图,我们要配置的是 Status Register-1

位 (Bit) 标识 设定值 功能描述
S7 SRP0 0 软件保护模式
S6 SEC 1 开启扇区级保护(让保护粒度细化到 4KB)
S5 TB 1 保护底部 (Bottom) 区域(从地址 0 开始向上锁定)
S4 BP2 0 块保护位 2
S3 BP1 0 块保护位 1
S2 BP0 1 块保护位 0(结合 SEC/TB,锁定 1 个 4KB 单元)
S1 WEL 0 写使能位(只读位,由硬件指令控制)
S0 BUSY 0 忙标志位(只读位)

当 SRP0 = 0 (默认值):软件保护模式。 只要你发送了 Write Enable (06h) 指令,你就可以通过 SPI 指令随意修改状态寄存器(包括那些保护位 BP0-BP2)。这时候,引脚 /WP 是不起作用的。

当 SRP0 = 1:进入“准硬件保护”状态。 此时看 /WP 引脚的电平:

如果 /WP 为高电平:依然是软件保护,可以改。

如果 /WP 为低电平硬件锁定模式。状态寄存器被“焊死”了,任何 SPI 指令都改不了它。

SRP0 就像是保险柜的“电子锁使能”。SRP0=0 时,你有密码就能开;SRP0=1 且 /WP 拉低时,相当于不仅要密码,还得插一把实体钥匙才能开。

TB = 1 (从底部 Bottom 开始保护)

保护范围: 从地址 000000h 开始向上覆盖。

适用场景: 你要把 500 个从机的配置存放在最开始的 4KB 扇区。

优势: 大多数单片机的 Bootloader 或核心配置参数习惯放在地址 0 附近。如果你把这部分锁死,程序最核心的“根”就安全了。

TB = 0 (从顶部 Top 开始保护)

保护范围: 从芯片最高地址(比如 8MB 芯片的 7FFFFFh)向下覆盖。

适用场景: 如果你把 Flash 的末尾用来存字库、固件包或者不经常变动的大型静态资源。

二进制组合0110 0100十六进制转换0x64

/** * @brief  锁定 Flash 底部第一个 4KB 扇区 (0x000000 - 0x000FFF) * @note   用于保护 500 个从机配置不被误操作擦除 */void FLASH_Lock_Config_Sector(void){    // 1. 发送写使能指令 (06h)    // 修改状态寄存器前必须先开启写使能锁存器 (WEL)    SPI_FLASH_WriteEnable();     // 2. 写入状态寄存器 1 (01h)    // 写入计算值 0x64,对应手册表 7.1.11 中的 4KB Lower 1/2048 保护    SPI_FLASH_WriteStatusReg1(0x64);     // 3. 等待内部写入周期完成    // 写入非易失性寄存器需要一定的硬件处理时间 (tW)    SPI_FLASH_WaitForWriteEnd(); 
    printf("rn[系统] 500节点配置区 (0x0000) 已永久锁定!rn");}/** * @brief  解除全片锁定 (在需要批量更新从机名单时调用) */void FLASH_Unlock_All(void){    SPI_FLASH_WriteEnable();    // 将 BP0-BP2, SEC, TB 全部清零    SPI_FLASH_WriteStatusReg1(0x00);     SPI_FLASH_WaitForWriteEnd();
    printf("rn[提醒] Flash 已进入全区读写模式。rn");}

示例2:

列举一个在网关开发中非常实用的场景:锁定最后 256KB 的区域用于存放“固件备份”或“OTA 升级包”

在 多节点的网关中,如果远程升级失败,则必须确保 Flash 中存有一份绝对安全的“出厂固件”。

根据7.1.11 映射表,我们要实现的是保护芯片最高地址处的 4 个块。

SEC = 0:使用 64KB 块级保护

TB = 0:从 顶部 (Upper) 开始向下锁定。

BP2=0, BP1=1, BP0=0:对应 Upper 1/32 比例(即 256KB)。

状态寄存器 1 (SR1) 位排列

SRP0(0) | SEC(0) | TB(0) | BP2(0) | BP1(1) | BP0(0) | WEL(0) | BUSY(0)

二进制0000 1000十六进制0x08

 

/** * @brief  配置 Flash 存储区的写保护范围 * @param  ConfigValue: 写入状态寄存器 1 的十六进制值 */void W25Q_Set_Protection(uint8_t ConfigValue){    // 1. 发送写使能指令 (06h)    // 所有的擦除、编程、写状态寄存器操作前必须发此指令    SPI_FLASH_WriteEnable();     // 2. 写入状态寄存器 1 (01h)    // 此操作会将保护配置写入非易失性存储单元    SPI_FLASH_WriteStatusReg1(ConfigValue);     // 3. 等待写入完成    // 写入状态寄存器需要硬件处理时间 tW    SPI_FLASH_WaitForWriteEnd(); }/** * @brief  实战:保护水表配置区与固件备份区 */void Flash_Security_Init(void){    // 场景 A:保护底部 4KB (存 500 个从机 ID)    // 对应位:SEC=1, TB=1, BP=001 -> 0x64    W25Q_Set_Protection(0x64);    printf("Config Area (Bottom 4KB) Protected.rn");    // 场景 B:保护顶部 256KB (存固件镜像)    // 对应位:SEC=0, TB=0, BP=010 -> 0x08    // W25Q_Set_Protection(0x08); }

注意:

WEL 位自动清零:一旦 WriteStatusReg1 指令完成,芯片会自动把 WEL 位清零。这意味着下一次想修改保护范围,必须再次调用 WriteEnable()

写指令被忽略:如果你的 4G 模块代码尝试向受保护的 0x7C0000 地址写入数据,Flash 会正常接收 SPI 信号但不执行任何动作。这会导致 Buffercmp 校验失败并报错 Error 1

寄存器锁定 (SRP0/1):如果你不小心把 SRP0 或 SRP1 设置成了硬件保护模式且 WP 接了地,那么即使在代码里发出解锁指令也无法更改保护范围了。

五W25Q64指令系统与通讯规约

5.1 身份验证:Manufacturer and Device ID

在正式读写数据前,第一步永远是“对暗号”。

核心指令9Fh (JEDEC ID)。

识别码分析

Manufacturer IDEFh (代表 Winbond 华邦)。

Memory Type40h (代表 SPI 模式)。

Capacity17h (代表 64Mb 容量)。 64Mb 位容量 (Mb)  8 MB字节容量 (MB)

意义:你在调试时读出的 0xEF4017 就是由这三个字节组成的。如果读不到这个数,说明 SPI 物理链路或时钟极性(Mode)配置有误。

5.2 核心指令集 (Standard SPI Instructions)

A23-A16A15-A8A7-A0 组合起来就是一个完整的 24 位物理地址

为什么是 3 个字节? 2^24 次方等于 16,777,216。这意味着用 3 个字节的地址,最大可以管理 16MB 的存储空间。

A23-A16 (Byte 2):地址的高位字节(最重要的一段门牌号)。

A15-A8 (Byte 3):地址的中间字节。

A7-A0 (Byte 4):地址的低位字节。

这就像你寄快递。Byte 1 是“寄东西”;Byte 2 是“省”;Byte 3 是“市”;Byte 4 是“区”。只有这四个字节加在一起,快递员(Flash 硬件)才知道具体要把东西送到哪。

维度 理解 实际底层逻辑 理由
指令 (Instruction) 8 位 8 位 (1 Byte) 表中 Byte 1 的固定长度。
地址 (Address) 24 位 24 位 (3 Bytes) 对应 A23-A0,决定了 16MB 的寻址空间。
数据宽度 (Data) 16 位 8 位 (1 Byte) SPI 物理上是串行的(1位),逻辑上以 8位 为一帧。

第一类:光杆司令(只有 Byte 1)

例子Write Enable (06h)Write Disable (04h)

原因:这些是“全局开关”。比如“准许写”,它不需要指定地址,只要说一声就行。所以 Byte 2 之后全是空的。

第二类:查岗指令(Byte 1 + 寄存器数据)

例子Read Status Register-1 (05h)

后面跟的是 (S7-S0):这代表你发出 05h 后,Flash 会在接下来的 Byte 2 时间里回传它的状态位

原因:你想看它的健康报告,不需要地址,直接读就行。

第三类:精准打击(Byte 1 + 3字节地址)

例子Sector Erase (20h)Page Program (02h)

后面跟的是 A23...A0

如果你说“擦除”,Flash 会问:“擦哪儿?”

所以你必须在 Byte 2、3、4 告诉它具体的 24 位地址。

Page Program (02h) 后面还有 D7-D0:那是你要写入的真实数据(Data)

SPI_ReadWriteByte(0x02);               // Byte 1: 指令 (动词:页编程)SPI_ReadWriteByte((Addr >> 16) & 0xFF); // Byte 2: 地址高 8 位 (A23-A16)SPI_ReadWriteByte((Addr >> 8) & 0xFF);  // Byte 3: 地址中 8 位 (A15-A8)SPI_ReadWriteByte(Addr & 0xFF);         // Byte 4: 地址低 8 位 (A7-A0)

将 Table 7.2.2 中的指令按功能分类介绍:

控制类

06h (Write Enable): 写使能。这是所有擦除和写入操作的“开门指令”,执行后状态寄存器的 WEL 位会置 1。

01h (Write Status Register): 写状态寄存器。这就是我们用来实现“底座 4KB 永久锁定”的关键。

擦除类

20h (Sector Erase 4KB): 以扇区为单位擦除。 你的 500 个节点配置信息通常占用一个或多个扇区。

读写类

02h (Page Program): 页编程。一次最多写入 256 字节。

03h (Read Data): 普通读取

5.3 指令发送的“字节流”逻辑

你需要解释手册表格中 BYTE 2 到 BYTE 6 的含义,这对写代码非常关键:

地址发送:大多数指令(如 02h, 03h, 20h)后面都紧跟三个字节的地址(A23-A16, A15-A8, A7-A0)。

Dummy Byte (哑字节):像 0Bh (Fast Read) 这种指令,中间需要一个 Dummy 字节(通常发 0xFF)给芯片内部留出反应时间。

数据流:指令和地址发完后,紧接着就是连续的数据字节流。

注意:

1. “页卷回”风险(Note 3)—— 开发者最容易掉的坑

内容:Page Program 最多支持 256 字节。如果发送超过 256 字节,地址会卷回(Wrap)到当前页的开头并覆盖之前的数据。

技术影响: 假设一次性存入 500 个水表的 ID(假设每个 ID 8 字节,共 4000 字节),你不能只发一个 02h 指令。

对策: 你必须编写一个“自动分页写入”函数。每写 256 字节,必须重新发送起始地址并检测 BUSY 位。

2. 安全寄存器的物理隔离(Note 5)

内容: 芯片额外提供了 3 个各 256 字节的 Security Registers(安全寄存器),它们有独立的地址空间(001000h、002000h、003000h)。

建议: 建议把网关的核心出厂配置(如网关唯一的通信密钥、4G 模块的授权码)存在这里,而不是主存储区。因为这里支持 OTP(一次性编程)锁定,一旦锁定,物理上无法改写,防黑客效果极佳。

3. 双线/四线模式下的“位分片”(Note 6 - 11, 14)

内容: 详细描述了在 Dual/Quad/QPI 模式下,地址位和数据位是如何分布在 IO0-IO3 上的。

关键点: 在 QPI 模式下(Note 14),指令码(C7-C0)也是通过 4 根线并传的。

对策: 如果你发现切换到 QPI 后读出的 ID 变了,多半是 SPI 控制器的字节序或位序配置与 Note 14 的时钟周期(CLK #0, 1)对不上。

分类 涉及注释 核心要点
数据传输 Note 1 必须 MSB First(最高有效位在前)。
效率提升 Note 2 读取状态寄存器或 ID 时,CS 不拉高数据会一直重复,适合做死循环查询(Polling)。
寻址限制 Note 12, 13 执行 Word Read 必须 2 字节对齐(A0=0);执行 Octal Word Read 必须 16 字节对齐。
模式控制 Note 15, 16 QPI 模式下的“哑时钟”(Dummy Clocks)数量和“卷回长度”是可以通过参数 P7-P0 编程修改的。

4. 关于地址对齐(Note 12/13)

在你的水表数据结构体设计时,建议将结构体大小设置为 16 字节的倍数。这样在调用高速读取指令时,地址永远是自然对齐的,不会触发 Note 12/13 的限制。

5. 于页边界写入

很多开发者认为 02h 指令可以从地址 0 一直写到地址 8MB,这是错误的。受 Note 3 限制,写入一旦超过页边界(256字节),数据会像“贪吃蛇撞墙”一样回到页首。在处理 比如500 个节点的数据上报时,务必在代码中加入页边界判断逻辑。

5.4 指令时序图分析

Mode 0 (CPOL=0, CPHA=0)

状态:时钟线(CLK)平时休息时是低电平。

动作:CLK 一旦从低变高(第一个边沿),单片机和 Flash 就立刻抓取数据。

特点:反应最快,效率极高。

Mode 1 (CPOL=0, CPHA=1)

状态:时钟线平时也是低电平。

动作:CLK 从低变高时,大家先“准备”一下数据;等到 CLK 从高变低(第二个边沿)时,才真正抓取数据。

特点:给了硬件半个时钟周期的缓冲时间。

Mode 2 (CPOL=1, CPHA=0)

状态:时钟线平时休息时是高电平

动作:CLK 一旦从高变低(第一个边沿),立即抓取数据。

特点:采样发生在下降沿。

Mode 3 (CPOL=1, CPHA=1)

状态:时钟线平时也是高电平。

动作:CLK 从高变低时准备数据,等 CLK 从低变高(第二个边沿)时抓取数据。

特点这是 W25Q64 最常用的模式之一。因为它在上升沿采样,且平时 CLK 为高,抗干扰能力较强。

W25Q64 的时序主要分为以下几类模板:

单字节模板:只有指令,没有地址和数据。如 Write Enable (06h)Reset (99h)

指令 + 地址模板:先发指令,再发 24 位地址。如 Sector Erase (20h)

指令 + 地址 + 数据输出模板:发完指令和地址,Flash 开始往外吐数据。如 Read Data (03h)

指令 + 地址 + 哑周期 + 数据输出模板:中间多了一个缓冲。如 Fast Read (0Bh)

Write Enable (06h) 指令

左图分析:标准 SPI 模式 (Standard SPI)

第一步:拉低片选 (CS)

图中看到 CS从高电平跳变到低电平(下降沿),这代表单片机告诉 Flash:“准备好,我要下令了”。

第二步:确认时钟 (CLK) 模式

注意图中虚线标出的 Mode 3 和 Mode 0。无论空闲时是高还是低,数据都是在 CLK 的上升沿被 Flash 采样的。

第三步:发送指令 (DI  IO_0)

在 8 个时钟脉冲内,单片机在 DI 线上依次送出二进制位。

指令是 06h,换算成二进制是 0000 0110

你看图中 DI 线的波形:前 5 位是低电平,第 6、7 位跳高,最后一位变低。这就是典型的串行发送。

第四步:忽视输出 (DO / IO_1)

你会发现 DO 线上写着 High Impedance(高阻态)。因为这是“写使能”指令,Flash 只需要听,不需要回答,所以它的输出引脚处于断开状态。

右图分析:极速 QPI 模式

这就是你之前好奇的“四线模式”。

核心区别:带宽翻了 4 倍

在左图中,发一个 06h 需要 8 个时钟周期

在右图中,单片机同时利用 IO_0, IO_1, IO_2, IO_3 四根线发数据。

指令 06h (0000 0110) 被拆分了:第一个时钟周期传前 4 位,第二个周期传后 4 位。

结果:只需 2 个时钟周期 就发完了。对于 500 个节点频繁写入的场景,这种模式能显著降低 CPU 占用。

Read Status Registere (50h) 指令     读取状态寄存器

左图分析:标准 SPI 模式 (Standard SPI)

第一步:拉低片选 (CS)

图中看到 CS 从高电平跳变到低电平(下降沿),这代表单片机告诉 Flash:“准备好,我要下达一条临时配置 使能指令了”。

第二步:确认时钟 (CLK) 模式

依然兼容 Mode 0 和 Mode 3。数据在 CLK 的上升沿被 Flash 稳定采样,这保证了在高频通讯下的指令准确性。

第三步:发送指令 (DI / IO_0)

在 8 个时钟脉冲内,单片机在 DI 线上依次送出二进制位。 指令是 50h,换算成二进制是 0101 0000。 观察图中 DI 线的波形:第 1 位低,第 2 位高,第 3 位低,第 4 位高,随后连续 4 位保持低电平。这种“跳变”波形就是 50h 指令的唯一特征。

第四步:忽视输出 (DO / IO_1)

DO 线上显示为 High Impedance(高阻态)。因为 50h 只是一个声明类的“使能”动作,Flash 此时只需要听指令,不会返回任何数据。

右图分析:极速 QPI 模式

这就是为了在追求极致效率的场景下设计的“并行模式”。

核心区别:位宽翻了 4 倍

在左图中,串行发送一个 50h 指令需要 8 个时钟周期。 在右图中,单片机利用 IO_0 到 IO_3 四根数据线同时发力。 指令 50h (0101 0000) 被拆分成了两个部分:第一个时钟周期并行传输高 4 位 (0101),第二个周期并行传输低 4 位 (0000)。

结果:只需 2 个时钟周期

指令传输耗时缩短到了原来的 1/4。在多任务高并发的环境下,这种节省能有效降低总线占有率,让 CPU 有更多时间处理其它业务逻辑。

50h 不会置位 WEL 位。它仅仅是为了紧随其后的 Write Status Register (01h) 指令服务,使其修改后的寄存器值在断电后自动消失(易失性)。这在需要动态调整内存保护范围、但又不希望频繁擦写硬件寄存器的应用中非常有用。

Write Status Register (01h) 指令  写状态寄存器

上图分析:标准 SPI 模式 (Standard SPI)

第一步:拉低片选 (/CS) 图中看到 /CS 从高电平跳变到低电平(下降沿),开启通讯。注意:在执行此图操作前,你必须已经先发送过 06h(写使能)指令,否则这一整张图的操作都会被 Flash 忽略。

第二步:确认时钟 (CLK) 模式 支持 Mode 0 和 Mode 3。数据在 CLK 的上升沿 被采样。对于写寄存器这种关键操作,时序的稳定性直接决定了你的 500 个水表节点名单是否会被“锁死”。

第三步:发送指令 (DI / IO0) 在第 0 到 7 个时钟脉冲内,单片机送出二进制位 0000 0001 (01h)。这是告诉 Flash:“我要改写你的状态寄存器了”。

第四步:顺序写入寄存器数据

Status Register 1 in:在第 8 到 15 个脉冲,单片机送入 8 位数据(S7-S0)。这是你设置 BP、SEC、TB 位的地方。

Status Register 2 in:在第 16 到 23 个脉冲,紧接着送入第二个 8 位数据(S15-S8)。这是设置 QE(四线使能)或 CMP 位的地方。

关键细节:图中星号(*)标注了 MSB(最高位)在前

第五步:忽视输出 (DO / IO1) DO 线上依然是 High Impedance(高阻态)。因为此时是单片机向 Flash “下达命令”,Flash 只负责记录,不回话。

下图分析:极速 QPI 模式

核心区别:极高的写入效率 在 SPI 模式下,改写两个寄存器总共需要 24 个时钟周期(8 指令 + 8 SR1 + 8 SR2)。 而在 QPI 模式下:

发送指令 (01h):仅需 2 个时钟(IO0-IO3 同时传位)。

写入 SR1:仅需 2 个时钟

写入 SR2:仅需 2 个时钟

结果:总共只需要 6 个时钟周期 就能完成配置。这对于在 FreeRTOS 任务中需要快速切换保护状态的操作来说,极大地减少了 CPU 的阻塞时间。

MSB(Most Significant Bit) 就是最高有效位

LSB (Least Significant Bit)    翻译过来叫 最低有效位。

举例说明:发送数字 0x41 (二进制 0100 0001)

假设我们要把这个数据从单片机发给外设:

情况 A:MSB First (SPI 模式)

电线上出现的顺序是:0 -> 1 -> 0 -> 0 -> 0 -> 0 -> 0 -> 1

结果:对方收到后按原样拼好,还是 0x41

情况 B:LSB First (某些传感器或串口)

电线上出现的顺序是:1 -> 0 -> 0 -> 0 -> 0 -> 0 -> 1 -> 0

结果:如果你用 MSB 的逻辑去读,读出来的数就变成了 1000 0010 (即 0x82)。数据彻底错了!

进阶概念:大端与小端 (Endianness)

这是教小白时最容易混淆的。MSB/LSB 关注的是一个字节内部的位顺序,而大端/小端关注的是多个字节组合时的顺序。

大端模式 (Big-Endian):高位字节存在低地址。

小端模式 (Little-Endian):低位字节存在低地址(STM32/CW32 内部通常用这个)。

Page Program (02h) 指令  页编程

上图分析:标准 SPI 模式 (Standard SPI)

第一步:拉低片选 (CS) 图中看到 CS 从高电平跳变到低电平(下降沿),开启一次写入会话。 注意:在执行此操作前,必须先发送过 06h (写使能),否则写入无效。

第二步:确认时钟 (CLK) 模式 支持 Mode 0 和 Mode 3。数据在 CLK 的上升沿 被采样。对于大数据量(256 字节)写入,稳定的时钟边沿是防止数据位偏移的关键。

第三步:发送指令与地址 (DI / IO0)

在第 0 到 7 个时钟脉冲内,单片机送出二进制位 0000 0010 (02h)。

紧接着发送 24 位地址 (A23-A0)。这决定了数据从哪个位置开始存。

第四步:顺序写入数据流 (Data Byte 1 to 256)

地址发完后,紧接着送入数据字节。

Data Byte 1:在第 32 到 39 个脉冲送入。

持续写入:只要不拉高 CS,可以一直往后发数据,最高支持 256 字节。

图中星号(*)再次强调了 MSB(最高位)在前

第五步:忽视输出 (DO / IO1) DO 线全程处于 High Impedance(高阻态),因为写入过程中 Flash 只需要接收信息。

下图分析:极速 QPI 模式

核心区别:吞吐量质的飞跃 在 SPI 模式下,写满一页(256 字节)需要发送大量的时钟脉冲;而在 QPI 模式下:

发送指令 (02h):仅需 2 个时钟

发送地址:仅需 6 个时钟

发送数据:每个字节仅需 2 个时钟

结果:数据传输速度提升了 4 倍。对于 500 个节点并发产生的大量数据,QPI 模式能极大缩短总线占用时间。

Sector Erase (20h)指令   扇区擦除

左图分析:标准 SPI 模式 (Standard SPI)

第一步:拉低片选 (/CS) 图中看到 /CS 从高电平跳变到低电平(下降沿),开启擦除会话。注意:执行此操作前,必须先发送过 06h (写使能),确保状态寄存器的 WEL 位为 1

第二步:确认时钟 (CLK) 模式 支持 Mode 0 和 Mode 3。数据在 CLK 的上升沿 被采样。对于擦除地址的传输,时序的精准决定了你是否会“误抹除”其它重要数据。

第三步:发送指令 (DI / IO0) 在第 0 到 7 个时钟脉冲内,单片机送出二进制位 0010 0000 (20h)。这是告诉 Flash:“我要擦除一个 4KB 的扇区”。

第四步:发送 24 位地址 (DI / IO0) 在第 8 到 31 个脉冲,单片机送出目标扇区的起始地址(A23-A0)。图中星号(*)标注了 MSB(最高位)在前。Flash 会根据这个地址锁定对应的 4KB 空间。

第五步:忽视输出 (DO / IO1) DO 线全程处于 High Impedance(高阻态)。擦除指令是单向命令,Flash 在此阶段不返回数据。

右图分析:极速 QPI 模式

核心区别:指令与地址传输极速化 在 SPI 模式下,发送“指令+地址”需要 32 个时钟周期。而在 QPI 模式下:

发送指令 (20h):仅需 2 个时钟(IO0-IO3 并行)。

发送地址:仅需 6 个时钟

结果:总共只需 8 个时钟 即可启动擦除任务。这在 500 节点高并发、任务切换频繁的 FreeRTOS 环境下,能显著降低总线占用率。

Fast Read (0Bh) 指令

左图分析:标准 SPI 模式 (Standard SPI)

第一步:拉低片选 (/CS) 图中看到 CS 从高电平跳变到低电平(下降沿),开启读取会话。与写入指令不同,读取指令不需要先发“写使能”。

第二步:确认时钟 (CLK) 模式 支持 Mode 0 和 Mode 3。数据在 CLK 的上升沿 被采样。

第三步:发送指令与地址 (DI / IO0)

指令:单片机送出 0Bh

地址:紧接着送出 24 位地址。到这里为止,它和普通读取(03h)长得一模一样。

第四步:引入“哑时钟” (8 Dummy Clocks) 这是最关键的区别!在地址发完后的第 32 到 39 个时钟周期,DI 线上发什么都无所谓(Don't care)。

意义:这 8 个节拍是给 Flash 内部电路留出的“取货时间”。

第五步:数据输出 (DO / IO1) 从第 40 个时钟开始,Flash 准时在 DO 线上吐出第一个字节。只要你不拉高 CS,它会一直按顺序吐出 500 个节点的所有数据。

右图分析:极速 QPI 模式

核心区别:带宽与灵活度

极速传输:指令仅需 2 个时钟,地址仅需 6 个时钟。

可调哑时钟:QPI 模式下,你可以通过 C0h 指令设置哑时钟的数量(2, 4, 6 或 8 个)。

IO 切换:在 Dummy 阶段结束后,IO0-IO3 会立即从输入模式切换为输出模式,四线同时“开火”吐数据。

资料链接:

https://telesky.yuque.com/bdys8w/01/zr02y6vd0r7mnzcl?singleDoc# 《W25Qxx存储模块》


扫码加入QQ群3群| 610403240

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

以开放、共享、互助为理念,致力于构建武汉芯源半导体CW32系列MCU生态社区。无论是嵌入式MCU小自还是想要攻破技术难题的工程师,亦或是需求解决方案的产品经理都可在CW32生态社区汲取营养、共同成长。