资讯动态

SPI与QSPI协议详解:从时序原理到嵌入式存储驱动实战

发布时间:2026/10/14 16:50:21 来源:尧图企业网站定制
1. 从两根线到四根线为什么嵌入式存储离不开SPI与QSPI搞过单片机的朋友大概率都有过这样的经历板子上挂了一颗小容量的存储芯片想读点数据结果发现它既不是I2C那种两根线慢悠悠地挪也不是并口那种一拉一大把引脚的阵仗而是介于两者之间——用少数几根线跑出还算能看的速率。这就是SPISerial Peripheral Interface存在的意义而QSPIQuad SPI则是在它的基础上把数据线从一根扩到四根专门伺候那些对速度有要求的Flash存储场景。我最早接触SPI是在做一块数据采集板的时候主控需要外挂一颗Flash存日志当时图省事直接用了普通SPI模式结果采样率一上去写Flash的耗时直接把整个采集周期拖垮了。后来换成QSPI同样的芯片读速率翻了将近四倍采集周期立刻宽裕了。那次之后我才真正意识到协议规约这东西不是背概念它直接决定了你的系统能不能跑得动。这篇内容我打算把SPI和QSPI从协议规约到工作原理掰开揉碎讲一遍重点放在时序细节、模式选择、QSPI的四线扩展机制以及实际写驱动时那些文档里不会明说的坑。适合已经会点单片机、想搞懂底层通信协议的朋友也适合正在选型存储方案、纠结用SPI还是QSPI的工程师。看完你至少能做到拿到一颗SPI Flash的数据手册能自己把读写时序对上知道什么时候该上QSPI以及为什么你的驱动偶尔会读出全0xFF。2. SPI协议规约的核心骨架2.1 四根线的分工与主从架构SPI的物理层非常朴素标准配置就四根线SCLK时钟、MOSI主出从入、MISO主入从出、CS片选低有效。它没有像I2C那样的地址机制也没有应答位主从之间的通信完全靠片选来点名。这意味着一条SPI总线上可以挂多个从设备但每个从设备需要一根独立的CS线主设备拉低谁的CS谁就上工。这种设计的优点是简单直接没有协议开销时钟频率可以拉得很高几十MHz甚至上百MHz都常见。缺点也很明显引脚数量随从设备数量线性增长挂四五个从设备CS线就占掉一堆IO。所以实际项目里SPI总线上通常只挂一两个关键外设比如Flash、显示屏、传感器。主从架构里时钟永远由主设备产生从设备只是被动响应。这一点和I2C不同I2C支持多主SPI基本就是单主多从。理解这一点很关键因为它决定了你在写驱动时时钟配置、时序控制全部由主控侧负责从设备只是跟着节奏走。2.2 时钟极性与相位的四种组合SPI最容易让人绕晕的就是CPOLClock Polarity和CPHAClock Phase这两个参数它们组合出四种模式也就是常说的Mode 0到Mode 3。很多新手调不通SPI十有八九是模式没对上。CPOL决定时钟空闲时的电平CPOL0表示空闲为低电平CPOL1表示空闲为高电平。CPHA决定数据在哪个边沿采样CPHA0表示在第一个边沿即时钟从空闲态跳变的那个边沿采样CPHA1表示在第二个边沿采样。模式CPOLCPHA空闲电平采样边沿典型应用Mode 000低上升沿多数Flash、传感器Mode 101低下降沿部分ADCMode 210高下降沿较少见Mode 311高上升沿部分EEPROM实际项目里Mode 0和Mode 3用得最多。我个人的经验是拿到一颗新芯片先翻数据手册的时序图找到SCLK空闲电平和采样边沿直接对应到模式别凭感觉试。试错成本很高尤其是高速通信时模式错了可能偶尔能读到数据但极不稳定排查起来非常痛苦。注意CPHA0时数据在第一个边沿采样意味着数据必须在第一个边沿之前就准备好CPHA1时数据在第二个边沿采样第一个边沿用来切换数据。这个区别在高速通信时直接影响建立时间和保持时间选错了会导致数据错位。2.3 数据传输的全双工本质SPI是全双工的MOSI和MISO同时工作。主设备在MOSI上发一位从设备同时在MISO上回一位。这个特性经常被忽略很多人以为SPI是发完再收其实不是。你发一个字节的同时从设备也在回一个字节只是你可能不关心它回什么。这个机制在写Flash时特别重要。比如你发写命令从设备在MISO上回的东西可能是状态寄存器的值也可能是无效数据。如果你不读MISO数据就丢了但如果你需要读状态就得在发命令的同时把MISO上的数据接住。很多驱动框架里SPI传输函数会同时传入发送缓冲和接收缓冲就是这个道理。全双工也带来一个副作用你无法只发不收也无法只收不发。想读数据必须发一个哑字节通常是0xFF来产生时钟从设备才会把数据推出来。这个哑字节的概念在QSPI里同样存在后面会再提到。3. QSPI的四线扩展机制与工作原理3.1 从单线到四线IO0到IO3的角色转换QSPI不是一种全新的协议而是SPI的扩展。它在标准SPI的基础上把原本单向的MOSI和MISO扩展成四根双向数据线IO0、IO1、IO2、IO3。在普通SPI模式下这四根线里的IO0当MOSI用IO1当MISO用IO2和IO3可能被用作写保护WP和保持HOLD。一旦切换到QSPI模式四根线全部变成双向数据线一个时钟周期可以传输4位数据。这个切换不是自动的需要主设备先通过标准SPI模式发送特定命令比如0x38进入QSPI模式0x35使能QPI模式从设备收到命令后才把IO2和IO3从WP/HOLD功能切换成数据线。这个命令序列因芯片而异必须查数据手册。我踩过的一个坑是某颗Flash在进入QSPI模式后如果CS拉高再拉低它会自动退回标准SPI模式。这意味着你不能在QSPI模式下随意切换片选必须保持CS持续有效或者每次重新发进入命令。这个细节在数据手册里往往藏在脚注里不仔细看根本发现不了。3.2 单线、双线、四线的速率对比QSPI的速率优势来自并行传输。标准SPI一个时钟周期传1位Dual SPI两线传2位Quad SPI传4位。假设时钟频率都是50MHz标准SPI50M × 1 50MbpsDual SPI50M × 2 100MbpsQuad SPI50M × 4 200Mbps实际有效速率还要扣除命令、地址、空周期等开销。QSPI读操作通常包含命令阶段1线或4线、地址阶段1线或4线、空周期dummy cycles、数据阶段4线。空周期的数量取决于时钟频率和芯片的访问时间频率越高需要的空周期越多。传输模式数据线数每周期位数50MHz下理论速率典型有效速率标准SPI1150Mbps约40MbpsDual SPI22100Mbps约80MbpsQuad SPI44200Mbps约160Mbps这个表格里的有效速率是估算值实际取决于命令开销和空周期配置。但趋势很明显QSPI在同样时钟下吞吐量是标准SPI的四倍左右。对于需要频繁读Flash的应用比如XIP执行代码、图像数据流这个差距是决定性的。3.3 空周期Dummy Cycles的计算逻辑空周期是QSPI里最容易被忽视但又最关键的参数。它的作用是给Flash芯片留出内部访问时间。当你发出读命令和地址后Flash需要一定时间从存储阵列里把数据取出来这段时间主设备不能采样数据线必须等待若干个时钟周期这就是空周期。空周期的数量不是固定的它和时钟频率、芯片的访问时间tACC有关。粗略的计算公式是空周期数 ≥ (tACC × 时钟频率) - 已有周期数举个例子某Flash的tACC是8ns时钟频率100MHz周期10ns那么至少需要1个空周期。但如果tACC是12ns就需要2个空周期。实际配置时数据手册通常会给出不同频率下推荐的空周期数直接查表最稳妥。我遇到过的情况是低频时一切正常一超频就读出乱码。排查半天才发现是空周期没跟着调。所以每次改时钟频率务必重新核对空周期配置这是QSPI驱动里最容易翻车的地方。4. 实操从零配置一次QSPI读操作4.1 硬件连接与引脚复用检查动手之前先确认硬件连接。QSPI的六根线SCLK、CS、IO0-IO3必须接到主控支持QSPI的引脚上。很多主控的QSPI引脚和普通GPIO或其他外设复用需要在寄存器里配置复用功能。这一步如果漏了后面怎么调都不通。我习惯先用万用表确认IO0-IO3没有对地短路再上电测SCLK有没有波形。如果SCLK没波形先查时钟使能和引脚复用别急着怀疑协议。硬件问题占调试时间的一半以上先排除硬件再搞软件。提示IO2和IO3在标准SPI模式下通常是WP和HOLD功能如果硬件上把它们直接接地或接高进入QSPI模式后会导致数据线被拉死。检查原理图确认这两根线在QSPI模式下是悬空或上拉的。4.2 进入QSPI模式的命令序列以常见的SPI Flash为例进入QSPI模式通常需要以下步骤发送写使能命令0x06让Flash接受配置更改。发送写状态寄存器命令0x01设置QE位Quad Enable把IO2和IO3从WP/HOLD切换成数据线。发送进入QSPI模式命令0x38让Flash进入四线模式。这三步的顺序不能乱尤其是QE位不设置的话IO2和IO3永远是WP/HOLD四线传输根本无从谈起。有些Flash的QE位在状态寄存器2里需要发0x31命令具体看手册。// 伪代码示例进入QSPI模式 spi_write_enable(); spi_write_status_register(0x02, 0x02); // 设置QE位 spi_send_command(0x38); // 进入QSPI模式这段代码只是示意实际实现要结合你的主控SPI外设。关键是理解每一步的目的而不是照抄。4.3 读操作的完整时序拆解进入QSPI模式后一次典型的读操作包含以下阶段命令阶段发送读命令如0xEBFast Read Quad I/O可以在1线或4线上发送。4线发送需要命令本身也支持QPI格式。地址阶段发送24位地址同样可以1线或4线。模式阶段部分芯片需要发送模式字节如0xA0用于设置连续读模式。空周期等待若干时钟周期。数据阶段在IO0-IO3上并行读取数据。每个阶段的线宽和周期数都可以配置配置错了就读不出正确数据。我的建议是先用最保守的配置命令和地址都用1线空周期给足确认能读到正确ID再逐步优化到4线、减少空周期。4.4 参数计算与配置实例假设时钟频率80MHzFlash的tACC为10ns读命令0xEB地址24位模式字节8位。命令阶段1线8个周期地址阶段4线24位 ÷ 4 6个周期模式阶段4线8位 ÷ 4 2个周期空周期tACC × 频率 10ns × 80MHz 0.8向上取整为1个周期但实际建议给2-3个周期留余量数据阶段4线每周期4位总开销周期 8 6 2 3 19个周期之后才是有效数据。如果读256字节数据阶段需要256 × 8 ÷ 4 512个周期总周期531个有效利用率约96%。这个开销在高速下可以接受但如果空周期给太多利用率会明显下降。注意不同厂商的Flash对空周期的要求不同有的芯片在80MHz下需要4个空周期有的只需要2个。务必查你手上那颗芯片的数据手册别用通用值。5. 常见问题与排查技巧实录5.1 读出全0xFF或全0x00这是最经典的问题。全0xFF通常意味着MISO/IO1线一直是高电平可能原因包括从设备没被选中CS没拉低、从设备没上电、MISO线断路、模式配置错误导致从设备没响应。全0x00则可能是数据线被拉低检查IO0-IO3有没有短路到地。我的排查顺序是先测CS有没有拉低再测SCLK有没有波形然后测MISO/IO1在传输时有没有跳变。如果MISO一直不动基本是从设备没工作或线没接对。5.2 高速下数据错位低速正常、高速出错八成是时序余量不够。可能的原因空周期不足、建立/保持时间不够、PCB走线太长导致信号完整性下降。先降频确认功能正常再逐步升频找到出错临界点然后在该频率下增加空周期或优化走线。我遇到过一块板子50MHz正常80MHz就错位最后发现是SCLK走线太长加了串联电阻匹配后问题解决。所以高速SPI/QSPI对PCB布局有要求时钟线尽量短必要时加端接电阻。5.3 模式切换后无法回到标准SPI前面提到过有些Flash在CS拉高后会退出QSPI模式。如果你在QSPI模式下操作完想切回标准SPI发其他命令必须先发退出命令如0xFF或者接受它自动退出。如果不确定最保险的做法是每次操作前重新发进入命令虽然麻烦但稳定。5.4 常见问题速查表现象可能原因排查方法全0xFFCS未拉低、从设备未上电、MISO断路测CS、测电源、测MISO波形全0x00数据线短路到地测IO0-IO3对地电阻低速正常高速错空周期不足、走线问题降频测试、增加空周期、检查PCB模式切换失败QE位未设置、命令顺序错查手册确认命令序列偶发数据错误时序余量不足、电源噪声增加空周期、加去耦电容这张表是我自己调试时总结的覆盖了大部分常见情况。实际排查时先用示波器或逻辑分析仪抓波形比盲猜快得多。逻辑分析仪能直接看到命令、地址、数据的每一位哪里出错一目了然。5.5 逻辑分析仪的使用心得调试SPI/QSPI逻辑分析仪是必备工具。我用的是8通道的入门款采样率100MHz以上就够用。抓波形时注意几点采样率至少是时钟频率的4倍以上否则会漏掉细节触发条件设在CS下降沿这样能抓到完整的一次传输解码器选SPI或QSPI直接看解析后的数据比数波形快。有一次我抓到一个偶发错误波形上看数据完全正确但Flash就是返回错误。后来发现是CS在两次传输之间拉高的时间太短Flash还没完成内部操作就被下一次传输打断。这种问题光看数据看不出来必须看CS的时间间隔。所以逻辑分析仪不仅看数据还要看控制信号的时间关系。6. 选型与优化什么时候该上QSPI6.1 SPI与QSPI的适用场景对比不是所有场景都需要QSPI。如果你的应用只是偶尔读写几个配置参数标准SPI完全够用引脚少、驱动简单。但如果你需要频繁读大量数据比如从Flash直接执行代码XIP实时读取图像或音频数据流高速数据记录那QSPI的优势就体现出来了。四倍吞吐量意味着同样的数据量耗时降到四分之一对实时性要求高的系统是刚需。场景推荐方案理由配置参数存储标准SPI数据量小速度要求低固件存储与升级标准SPI或QSPI升级频率低SPI够用XIP代码执行QSPI需要高吞吐、低延迟图像/音频流QSPI数据量大实时性要求高高速数据记录QSPI写入速率决定采样率上限6.2 引脚资源与成本的权衡QSPI比标准SPI多占两根线IO2、IO3对于引脚紧张的小封装主控这两根线可能很宝贵。如果引脚实在不够可以考虑Dual SPI用两根线换两倍速率折中方案。但要注意Dual SPI的命令和地址阶段通常还是1线只有数据阶段是2线实际提升没有四线那么明显。成本方面支持QSPI的Flash和标准SPI的Flash价格差异不大主要成本在主控是否支持QSPI外设。现在很多中高端MCU都内置QSPI控制器硬件成本不是瓶颈关键是软件配置的复杂度。6.3 内存映射模式XIP的配置要点QSPI最强大的功能之一是内存映射模式也叫XIPExecute In Place。配置好后Flash的地址空间直接映射到主控的地址总线CPU可以直接从Flash取指令执行不需要先把代码搬到RAM。这对RAM紧张的嵌入式系统非常有用。配置XIP的关键是设置好读命令、空周期和地址映射范围。一旦进入XIP模式CPU对映射地址的访问会自动触发QSPI读操作硬件自动处理命令、地址、空周期软件层面就像访问普通内存一样。但要注意XIP模式下不能写Flash写操作必须先退出XIP模式写完再重新进入。我做过一个项目代码量比较大RAM放不下用XIP直接从QSPI Flash执行省了一大块RAM。但XIP的读延迟比RAM高对性能敏感的代码段还是建议搬到RAM里跑。所以XIP适合存放不常执行或对延迟不敏感的代码热代码还是放RAM。6.4 后续可以扩展的方向这套SPI/QSPI的底层知识往深了走可以延伸到几个方向一是Octal SPI八线速率再翻倍但引脚更多、时序更复杂二是了解Flash的内部结构比如页、扇区、块的划分以及擦除和写入的时序要求三是研究不同厂商的QSPI实现差异比如有的支持连续读模式有的支持DTR双沿传输这些特性会进一步影响驱动设计。我自己接下来打算把Octal SPI的时序也摸一遍虽然目前项目用不上但存储速率的需求一直在涨早点搞懂没坏处。另外逻辑分析仪抓QSPI波形时八线模式需要更多通道可能得升级设备这也是个成本考量。最后分享一个小技巧调试QSPI时如果手头没有逻辑分析仪可以先用主控的SPI外设回环模式MOSI接MISO验证驱动框架确认发送接收逻辑没问题再接真实Flash。这样能把软件问题和硬件问题分开排查效率高很多。我在没有逻辑分析仪的早期项目里就是这么干的虽然笨但有效。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑