当前位置: 首页 > news >正文

深入理解SPI四种模式:以STM32读写W25Q64为例的时序图详解

深入理解SPI四种模式:以STM32读写W25Q64为例的时序图详解

在嵌入式系统开发中,SPI(Serial Peripheral Interface)总线因其高速、全双工的特性被广泛应用于各类外设通信。然而,许多工程师在使用SPI时,常被其四种工作模式(Mode 0-3)的时序差异所困扰。本文将以STM32与W25Q64 Flash存储器的实际通信为例,通过详细的时序图分析,帮助读者彻底掌握SPI模式的核心原理与配置技巧。

1. SPI协议基础与四种模式解析

SPI总线通过四根信号线实现全双工同步通信:

  • SCK(Serial Clock):时钟信号,由主机控制
  • MOSI(Master Out Slave In):主机发送,从机接收
  • MISO(Master In Slave Out):主机接收,从机发送
  • SS/CS(Slave Select):从机选择信号(低电平有效)

SPI的四种工作模式由两个关键参数决定:

  1. CPOL(Clock Polarity):时钟极性
    • 0:空闲时SCK为低电平
    • 1:空闲时SCK为高电平
  2. CPHA(Clock Phase):时钟相位
    • 0:数据在第一个时钟边沿采样
    • 1:数据在第二个时钟边沿采样

四种模式组合如下表所示:

模式CPOLCPHA空闲时钟数据采样边沿
000低电平上升沿
101低电平下降沿
210高电平下降沿
311高电平上升沿

注意:不同厂商对CPHA的定义可能略有差异,有些文档描述为"奇数边沿"或"偶数边沿"采样,本质上与上述定义一致。

2. W25Q64的SPI模式特性分析

W25Q64是一款8MB容量的SPI Flash存储器,其数据手册明确规定了支持的SPI模式:

#define W25Q64_SPI_MODE 0 // 默认工作在模式0

2.1 模式0的时序细节

模式0(CPOL=0, CPHA=0)是W25Q64最常用的工作模式,其典型时序特征如下:

  1. 起始条件:SS信号从高变低,此时:

    • MOSI在SS下降沿立即输出第一个数据位(MSB)
    • SCK保持低电平(CPOL=0的空闲状态)
  2. 数据传输

    • 上升沿:从机采样MOSI数据,主机采样MISO数据
    • 下降沿:主机输出下一位数据到MOSI,从机输出下一位到MISO
  3. 终止条件:SS信号从低变高,通信结束

以下为STM32配置SPI模式0的代码示例:

void SPI_Init_Mode0(void) { SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // CPOL=0 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // CPHA=0 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); }

2.2 其他模式的应用场景

虽然W25Q64主要使用模式0,但了解其他模式对调试兼容不同设备至关重要:

  • 模式1(CPOL=0, CPHA=1):某些ADC器件采用此模式
  • 模式2(CPOL=1, CPHA=0):在SCK空闲为高的系统中可减少功耗
  • 模式3(CPOL=1, CPHA=1):部分RFID读卡器使用此模式

3. 时序图深度解析与实战案例

3.1 模式0下的字节交换时序

以下是一个完整的字节交换时序(主机发送0x55,从机返回0xAA):

SS: \________________/ SCK: _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_ MOSI: 0 1 0 1 0 1 0 1 (0x55) MISO: 1 0 1 0 1 0 1 0 (0xAA) ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ 采样时刻(上升沿)

对应的STM32软件模拟SPI代码实现:

uint8_t SPI_SwapByte(uint8_t txData) { uint8_t rxData = 0; for(int i=0; i<8; i++) { // 下降沿准备数据 MOSI = (txData & 0x80) ? 1 : 0; txData <<= 1; SCK = 1; // 上升沿采样数据 rxData <<= 1; if(MISO) rxData |= 0x01; SCK = 0; } return rxData; }

3.2 W25Q64读写操作时序

以读取设备ID(0x9F指令)为例:

  1. SS拉低开始通信
  2. 发送指令字节0x9F
  3. 连续读取3个字节(制造商ID、存储器类型、容量)
  4. SS拉高结束通信

对应的示波器波形关键点:

  • MOSI在SCK下降沿变化
  • MISO在SCK上升沿前稳定
  • 每个字节传输间隔保持SCK空闲状态

4. 常见问题排查与调试技巧

4.1 数据采样错误排查步骤

当通信出现数据错误时,建议按以下流程排查:

  1. 确认模式匹配

    • 检查主机和从机的CPOL/CPHA设置
    • 验证SCK空闲电平和采样边沿
  2. 时序分析

    • 用示波器捕获SS、SCK、MOSI、MISO信号
    • 测量建立时间(Setup Time)和保持时间(Hold Time)
  3. 信号完整性检查

    • 观察信号过冲/下冲
    • 检查阻抗匹配和走线长度

4.2 STM32硬件SPI配置要点

在STM32CubeMX中配置SPI时需注意:

  1. 时钟极性与相位

    • 模式0:CPOL=Low, CPHA=1Edge
    • 模式3:CPOL=High, CPHA=2Edge
  2. 数据大小与端序

    • 通常选择8位数据(SPI_DATASIZE_8BIT)
    • 默认MSB优先(SPI_FIRSTBIT_MSB)
  3. NSS信号管理

    • 硬件NSS:自动控制片选信号
    • 软件NSS:需手动控制GPIO
// 硬件SPI发送接收示例 HAL_SPI_TransmitReceive(&hspi1, txData, rxData, length, timeout);

4.3 W25Q64特殊时序要求

W25Q64对SPI时序有严格限制:

参数最小值典型值最大值单位
SCK周期25--ns
保持时间3--ns
建立时间3--ns

当通信速率超过10MHz时,需特别注意PCB布局:

  • 缩短SPI走线长度
  • 避免信号线跨分割平面
  • 必要时添加端接电阻

5. 高级应用:SPI模式动态切换

某些应用场景需要主机适配不同从机的SPI模式。以下是STM32动态切换模式的实现方法:

void SPI_ChangeMode(SPI_HandleTypeDef *hspi, uint8_t mode) { hspi->Instance->CR1 &= ~(SPI_CR1_CPOL | SPI_CR1_CPHA); switch(mode) { case 0: // CPOL=0, CPHA=0 break; case 1: hspi->Instance->CR1 |= SPI_CR1_CPHA; break; case 2: hspi->Instance->CR1 |= SPI_CR1_CPOL; break; case 3: hspi->Instance->CR1 |= (SPI_CR1_CPOL | SPI_CR1_CPHA); break; } // 重新使能SPI __HAL_SPI_ENABLE(hspi); }

实际项目中,我曾遇到需要同时连接模式0的Flash和模式3的传感器的情况。解决方案是在访问不同设备前动态切换SPI模式,并在切换后添加足够的延时(通常>100ns)确保设置生效。

http://www.jsqmd.com/news/761142/

相关文章:

  • Docker Compose 运行大量容器如何优化系统文件描述符限制
  • 运维效率翻倍:手把手教你制作并复用银河麒麟V10 SP2的离线Yum仓库包
  • AutoSar新手避坑:用Vector工具链配置1字节NV Block的完整流程(含CRC校验)
  • 别再用IDEA备考了!聊聊NCRE二级Java为啥还在用NetBeans 2007,以及如何高效利用它
  • Llama-3.2V-11B-cot多模态推理效果展示:高精度视觉理解+分步思维链案例集
  • 从嵌入式开发到算法优化:C语言 | 位运算符的5个高效应用场景
  • Pezzo:开源AI应用开发平台,集中管理Prompt与模型参数
  • Python自动化脚本环境变量安全配置:.env管理详解
  • 4,ROS 2 TF 坐标变换实践教程(Python + C++)—— 手眼坐标变换(Hand-Eye)完整示例 + 调试工具 + 数据记录
  • 会务圈的“去手工化”:告别Excel焦虑,用眨眼猫把精力留给创意
  • 团队协作必备:用CLion+Gitee管理你的C++项目(含动态库版本控制实战)
  • 手把手教你用STM32F103C8T6的模拟I2C驱动AD5593R DAC模块(附完整工程代码)
  • 基于SSE的流式对话实现:提升AI应用用户体验的核心技术
  • 量子态混淆技术:原理、局限与未来方向
  • 创意总监技能树解析:从商业洞察到团队领导的全方位能力模型
  • 别再傻傻全文解析了!用PDFBox 2.0.1精准抓取发票金额和日期(附坐标测量小技巧)
  • PCB设计-器件:1.电容
  • 自修改策略与PAC学习边界的动态优化实践
  • 多智能体系统架构设计:从隔离沙箱到编排引擎的工程实践
  • 别只画板子了!用KiCad做RGB彩灯项目,这些焊接与调试的‘隐藏关卡’你通关了吗?
  • 别再用文件名搜图了!用ResNet50+Milvus手把手教你搭建自己的AI相册(附完整代码)
  • 【嵌入式Linux-02】SSD20X 平台网关开发环境搭建与开发全流程指南
  • 2026钢材加工应用白皮书采购选型深度解析:镀锌槽钢/H型钢/圆钢/工字钢/镀锌方管/钢材加工/钢结构/镀锌角钢/选择指南 - 优质品牌商家
  • 快速验证Ollama模型:在快马平台5分钟搭建本地AI原型应用
  • 2026年高端滋补品排行:燕窝十大品牌/燕窝品牌/东南燕都/官燕苑常温鲜炖燕窝/官燕苑燕窝/官燕苑现炖燕窝/官燕苑生态燕窝/选择指南 - 优质品牌商家
  • 2026届必备的五大降AI率助手推荐榜单
  • 别再只盯着Modbus了!聊聊RS-485总线在工业物联网中的那些‘坑’与实战避坑指南
  • Remult框架:全栈TypeScript开发中模型驱动与类型安全的新范式
  • Maven打包太慢?除了多线程,这3个-D参数(skip test/fork compile)才是隐藏加速器
  • AI辅助开发:让快马AI大模型为你编写树莓派视觉追踪机器人代码