存储接口信号采样与时序要求
I²C / SPI / SDIO / PPI NAND / PPI NOR 的采样机制、时序约束与工程注意事项 —— 把「什么时候被采样」讲透的一份时序参考 | 编制日期 2026-10-14 | 版本号 Rev 1.0
硬件调试里有一类故障特别难查:波形用示波器看「完全正常」,但数据就是偶尔错一个 bit。看板子的人往往会怀疑器件、看代码、换批次,却很少有人回头问一句——接收方到底是在哪个瞬间把线上的电压读进去的?那个瞬间如果落在信号的跳变区,再漂亮的波形也救不了它。
这份文档不讲怎么接线、怎么写驱动,只讲一件事:信号在什么时刻被采样,以及围绕那个时刻有哪些硬约束。五类接口的机制完全不同:I²C 用线与结构决定必须在 SCL 高电平采样,SPI 用 CPOL/CPHA 明确指定在哪个沿采样,SDIO 有专门的采样窗口,并行接口则是异步握手式采样。把它们放在同一套框架下看,很多原本要靠猜的问题会变得可以直接推导。
结论: 所有数字接口的时序问题,本质上只有一句——接收方的采样点必须落在发送方保证的有效窗口内。 不同接口只是「有效窗口由谁定义、有多大」不同:I²C 的窗口由开漏结构与 SCL 高电平期定义,SPI 的窗口由 CPOL/CPHA 组合出的两个沿定义,SDIO 的窗口由采样点相对数据有效沿的位置定义,并行接口的窗口由读写使能的脉宽定义。 因此调试的顺序永远是先确认采样点,再算余量,最后才怀疑硬件。 所有数值为量级性参考,实际设计一律以器件 datasheet 与所处速率下的时序图为准。
读者路径
- 只想搞懂 SPI 四种模式:直接看第 3 章(四模式逐个拆解 + 对照图)与第 4 章(模式选择与注意事项)。
- I²C 读数据不稳定:第 2 章,重点看 2.2 采样窗口、2.5 时钟拉伸、2.8 排查要点。
- SPI 高速下偶发错位:第 5 章(时序余量怎么被吃掉)+ 第 4.7 节(DMA 约束)。
- 并行接口时序混乱:第 7 章(PPI NAND)+ 第 8 章(PPI NOR),重点是方向切换的禁区。
- 要一份统一方法论:第 9 章(横向对照)+ 第 10 章(三步法与检查清单)。
- 只想要速查表:附录 B(时序参数速查)+ 附录 C(排查手册)就够了。
1. 信号采样与时序的物理基础
这一章不涉及任何具体接口,只建立一个统一的物理图景:信号在什么时刻被读入、这个时刻前后各需要多少余量、余量不足时会发生什么。后面四章的所有时序参数,都是这一章三条原理在具体协议上的投影。
1.1 数字信号在什么时刻被采样
「数字信号」在物理上是连续的电压,它被当作 0 还是 1,完全取决于谁在什么时刻看了一眼线上的电压。这个动作就叫采样。
- 采样点由接收方的电路决定:通常是触发器或寄存器在时钟沿到来的一瞬间锁存引脚电平。这个「时钟沿到锁存」之间的时间,在器件内部是固定但不为零的。
- 发送方只能承诺一个有效窗口:规格书里的建立时间、保持时间、传播延迟,描述的都是「我保证在这个窗口内电压是稳定的,你可以放心采」。
- 窗口之外没有任何承诺:数据手册不会告诉你在跳变区取值会得到什么,因为那里本来就不是有效值。
所以时序设计的全部工作只有一句话:让采样点落在对方承诺的有效窗口里,并且留够余量。
把时序参数理解成「器件之间的差距」是错的。建立时间、保持时间是单个器件引脚对驱动它的那个器件引脚提出的要求:主控输出建立时间 + 走线延迟 + 器件输入建立时间,三者之和必须小于时钟周期。这条不等式里每一项都是独立可测的,任何一项超标都可能导致采样点落进过渡区。
1.2 建立时间、保持时间与采样窗口
用「发送方」与「接收方」两个角色来看,一个时钟周期内的时序约束是最容易画清楚的。设时钟为 CLK,数据为 D:
- 建立时间(tSU):从
D稳定开始,到CLK有效沿到来之间的最小时间。要求D必须在有效沿之前就已经稳定这么久。 - 保持时间(tH):从
CLK有效沿过去,到D允许开始变化之间的最小时间。要求有效沿之后D还得继续稳定这么久。 - 有效窗口:有效沿前后这两个要求夹出来的那段区间,就是可以安全采样的区间。
- 采样点:接收方内部实际锁存的时刻。理想情况下它落在有效窗口正中。
把一行数据的时序周期 T 与这两条要求放在一起,就是最基本的不等式:
周期余量校验:
- 发送方输出延迟 + 走线延迟 + 接收方输入延迟 + 建立时间 < 时钟周期
- 数据在沿后的实际维持时间(发送方最小输出延迟 + 路径延迟差)> 接收方要求的保持时间 tH
这两条同时成立时,采样才有余量可用。当频率提到某个点后突然开始随机出错,几乎一定是第一个不等式被突破了——而突破的位置往往不是最慢的那个器件,而是延迟最长的那条路径加上裕量最小的那个环节。
1.3 亚稳态:采样点落在过渡区的后果
如果采样点落在信号跳变的过渡区,接收电路不会「读出中间值」这么简单,它会进入一种叫亚稳态的状态:输出在短时间内不确定,可能随机输出 0,也可能随机输出 1,还可能沿电路传播到下一级。
亚稳态有三个工程上必须记住的性质:
| 性质 | 含义 | 工程后果 |
|---|---|---|
| 随机性 | 同一条件下多次采样,结果可能不同 | 故障表现为「偶发」「随机」,最难复现 |
| 非零持续时间 | 不稳定态会持续一段时间才被强行收敛到某个电平 | 跨时钟域时可能导致下游电路拿到错误的相位 |
| 可被掩盖 | 下游寄存器可能采到正确值,看起来完全正常 | 故障率远低于理论值,但不为零,因此「测不出来」不等于「不存在」 |
亚稳态最麻烦的地方在于它不会自报错误。SPI 读回的 CRC 或许恰好对上了,I²C 读回的器件 ID 或许恰好是 0x00——所以很多团队会得出「时序问题不存在」的结论,直到量产阶段才被一批坏板打回来。
工程上的正确态度是:时序余量按「一定不能落进过渡区」来设计,而不是按「实测大部分时候是好的」来设计。前者是设计,后者是赌运气。
1.4 时序参数的来源与预算分配
一条从主控到器件的信号路径上,时序延迟由四段串联组成。把它们分开看,才能知道余量被谁吃掉了。
| 延迟段 | 典型来源 | 量级 | 变小的手段 | 变大的风险因素 |
|---|---|---|---|---|
| 主控输出延迟 | 输出驱动级翻转延迟 | 随工艺与驱动能力变化 | 降低速率档、使用更缓的驱动强度 | 电压下降或负载变重 |
| 走线延迟 | 线长与介质 | 与线长成正比 | 缩短走线、同一网络等长 | 过孔与分支、跨层参考不一致 |
| 器件输入延迟 | 引脚到锁存器的路径 | 随器件工艺变化 | 无法直接优化,只能查表 | 器件温度升高、电压偏离 |
| 建立时间需求 | 接收方内部要求 | 随器件工艺变化 | 无法直接优化,只能查表 | 温度升高、电压下降 |
1.5 同步接口与异步接口的根本差别
本文覆盖的五类接口,第一刀就切在这里:有没有一根时钟线。这一条决定了后面所有的分析方法。
| 维度 | 同步接口(SPI / SDIO) | 异步接口(I²C / PPI NAND / PPI NOR) |
|---|---|---|
| 采样点定义 | 时钟的某个有效沿,由模式或采样点位置指定 | 握手信号的定义域(高电平期、使能脉宽) |
| 时序余量来源 | 时钟周期减去延迟与建立时间之和 | 脉宽减去延迟与建立时间之和 |
| 两端速率关系 | 必须匹配,时钟由一方提供并被另一方接受 | 可以不同,慢的一方天然有更大余量 |
| 典型失效表现 | 固定速率以上开始随机错位 | 脉宽不足时数据错、方向切换时读错 |
| 排查手段 | 示波器看沿与采样点位置、逻辑分析仪看位错位置 | 示波器看脉宽与数据重叠、逻辑分析仪看握手顺序 |
| 本文对应章节 | 第 3 ~ 6 章 | 第 2、7、8 章 |
1.6 本文要回答的问题与主线
本文按「机制 → 约束 → 排查」的顺序组织,回答六个问题。
| 问题 | 回答位置 | 一句话答案 |
|---|---|---|
| 信号在什么时刻被采样 | 1.1 ~ 1.2 | 由接收方的锁存电路决定;建立与保持时间共同界定有效窗口 |
| 为什么 I²C 必须在 SCL 高电平采样 | 2.2 | 开漏线与结构决定 SDA 在低电平期不被读取,高电平期才是稳定区 |
| SPI 四种模式怎么区分、怎么选 | 3 ~ 4 章 | CPOL 定空闲电平,CPHA 定采样沿;模式由器件手册决定,不由习惯决定 |
| SPI 为什么上不了高频 | 第 5 章 | 不是时钟快,而是四段延迟之和吃掉周期,或走线振铃吃掉阈值裕量 |
| 并行接口方向切换为什么会错 | 7.4 | 总线换向需要一段双方都释放的禁区时间,禁区不足就会采到旧数据 |
| 遇到时序问题按什么顺序查 | 9.3、附录 C | 先确认采样点,再算余量,最后才换器件或降频率 |
2. I²C 接口的采样与时序
I²C 是本文五类接口里唯一「没有独立时钟线」的。SCL 就是时钟,但它同时也是一根被线与驱动的数据线——这个双重身份决定了 I²C 全部的时序特征。
2.1 I²C 的线与结构与它对时序的决定性影响
I²C 的两根线都是开漏输出:器件只能把线拉低或者释放,拉高靠外部上拉电阻。这一个决定带来了三个直接后果,每一个都写在时序里:
- 逻辑是线与的:任何时刻只要有一个器件拉低,线就是低的。多个器件同时驱动时不会互相打架,而是形成「谁都拉不低也无法拉高」的状态——这就是仲裁的物理基础(2.7)。
- 上升沿由 RC 决定:高电平不是器件主动拉出来的,而是上拉电阻把线充上去。上升时间与总线电容、上拉电阻成正比,这直接影响 I²C 的最高频率与上升沿的时序。
- 低电平期间不能采样数据:器件在拉低 SDA 的过程中,线上电压正在下降,此时读到的值是不确定的。这就是「SCL 高电平期采样」这条铁律的物理来源。
开漏结构换来的是多设备无冲突仲裁与故障容错能力,代价是上升沿不可控:上升时间由 R 与 C 决定,而这两个值往往由板级电容负载与走线决定,不由协议决定。因此在长线或大电容负载下,降频并不能缩短上升沿,上升沿时间仍由上拉电阻与总线电容决定,时序余量未必改善——盲目降频并不总是有效。
2.2 SDA 的采样窗口:为什么 SCL 高电平期间采样
I²C 把 SCL 的每个周期机械地切成两半:低电平期用来改变 SDA,高电平期用来读取 SDA。这不是约定,而是由线与结构唯一确定的。
- SCL 低电平期:发送方可以自由地把 SDA 拉低或释放,让它上升或下降。因为线处于「可能变化」的状态,此时读到的任何值都没有意义。
- SCL 高电平期:SDA 必须保持稳定。上升沿已经在低电平期间完成(充电已完成),下降沿也只能发生在低电平期间——因此在高电平期内 SDA 是一条平直线,采样窗口就是它的全长。
所以 SDA 的时序约束写成两条:数据建立时间相对 SCL 上升沿(数据在上升沿前就已经稳定),数据保持时间相对 SCL 下降沿(数据在下降沿之后还要保持)。
2.3 SCL 的高低周期与频率上限
I²C 的最高时钟频率不是由协议规定的,而是由必须满足的两条约束中较小的那一个决定:
- 低电平时间下限:这段时间内发送方要完成 SDA 的翻转并等待总线稳定。低电平太短会让上一个 bit 的下降沿还没结束,下降沿就会撞进高电平期。
- 高电平时间下限:这段时间内要完成一次采样决策,并且要留出上升沿与建立时间。高电平太短则接收方的内部锁存路径来不及完成。
除这两个下限之外,还有两条实际更常成为瓶颈的约束:
| 约束 | 由什么决定 | 变差的原因 | 排查手段 |
|---|---|---|---|
| 低电平时间下限 | 器件内部把 SDA 拉低到有效低电平所需时间 | 上拉电阻偏大、总线电容偏大 | 示波器量低电平平台是否够宽 |
| 高电平时间下限 | 上升沿时间 + 接收方建立时间 | 上拉电阻偏大或总线电容偏大导致上升沿变缓 | 示波器量上升沿斜率与高电平平台 |
| 上升沿时间 | 上拉电阻与总线电容的乘积 | 总线长、节点多、负载电容大 | 示波器看上升沿是否接近直线 |
| 整体周期 | 以上三项中的最大值 | 三者叠加后超出允许周期 | 在最高速档下逐项测量 |
因为上拉电阻与总线电容决定了上升沿时间,而下降沿由器件的输出能力决定、通常远快于上升沿。当频率降低时,占空比会随之改变:若主控在低电平期停留更久,高电平平台被相应压缩,采样决策可用的时间变短;更重要的是,若降频的同时改变了上拉电阻(很多调试动作会顺手改这个),上升沿时间会跟着变,可能让原本勉强通过的时序彻底失败。
排查时不要随手改上拉电阻,先用示波器量清楚是哪一段不达标,再针对性调整。
2.4 START 与 STOP 的时序判据
START 与 STOP 不是独立信号,而是SDA 相对于 SCL 变化的两种特定组合,所以它们的判据完全来自前面两条铁律:
- START(S):SCL 处于高电平时,SDA 从高变低。这一条来自「高电平期 SDA 必须稳定」——只有高电平期的变化才有意义。
- STOP(P):SCL 处于高电平时,SDA 从低变高。同样只能发生在高电平期。
- 数据 0 与数据 1:SCL 高电平期被采样的 SDA 电平;START/STOP 是 SCL 高电平期内 SDA 的两种特殊跳变,因破坏了「高电平期 SDA 必须稳定」的常规而具有独立含义。
因此,每一位的采样都发生在 SCL 高电平期,而每一个高电平期的 SDA 状态又被额外赋予两种含义——接收方必须靠「这一位是不是第一个周期」来区分,这正是协议需要状态机的原因。
2.5 时钟拉伸:从机如何拖住主机
当从机处理速度跟不上时,它需要主动把 SCL 拉低,强制主机停下等待。这就是时钟拉伸。
- 机制:从机在需要更多时间时输出低电平占用 SCL,主机在检测到 SCL 一直为低后停止推进时钟并进入等待。
- 主机必须支持:主机不能假设自己发出的时钟一定会被跟随。不支持时钟拉伸的主机,遇到慢速从机会直接锁死总线。
- 超时保护:时钟拉伸必须配一个超时,否则从机异常时会无限期拉低总线。
典型故障链是:某次通信中从机因干扰进入某个中间状态并开始拉低 SCL,主机等待超时后放弃总线并复位主机状态机,但从机仍然在拉低 SCL。此时无论主机怎么发 START 都无效,因为总线一直被占。
防范手段有三层:① 主机必须实现拉伸超时并在超时后走一次完整的总线复位(连续手动拉高 SCL 九个时钟再发 STOP);② 从机侧的拉伸必须有硬件或软件上限;③ 排查时先确认总线是否有器件把 SCL 长期拉低,而不是急着换主控驱动。
2.6 应答位本身就是一个采样点
I²C 的每一个字节后面都有 ninth clock,这一位是应答位。它的特殊性在于:这一位是发送方释放 SDA、接收方主动驱动的,方向与前八位相反。
- 接收方在 ninth clock 的高电平期检测 SDA:低电平表示应答(ACK),高电平表示非应答(NACK)。
- 发送方在这一位同样要采样,但它必须释放 SDA 让接收方驱动。如果发送方在此前一位结束时还拉着 SDA 不放,接收方就驱动不了,ACK 会变成 NACK。
- ACK 发生在 ninth clock 的高电平期,与数据位遵循同一条规则。
2.7 多主机的线与与仲裁
仲裁完全建立在线与结构上:发送的是 0 的主机赢,发送 1 的主机输。
- 在传输 SDA 的高电平期,各主机同时观察实际线电平与自己打算发的电平。只要看到「我发 1 但线是 0」,说明有别的发了 0 且线路确实被拉低,自己必须退出发送并转成接收。
- 仲裁期间禁止产生 STOP——所有获胜的主机要等整个字节发完并收到 ACK 后才决定继续还是发 STOP,否则会破坏正在传输的数据。
- 仲裁成立的前提是上升沿足够快。如果上升沿过缓,两个主机的「发送 1」都还没真正到高电平,另一方就判断不了总线状态。
2.8 I²C 时序参数清单与排查要点
下面这张表可以直接作为原理图评审与调试时的检查项。
| 检查项 | 要求 | 不满足时的表现 | 怎么确认 |
|---|---|---|---|
| 上拉电阻取值 | 满足上升沿时间要求,同时保证低电平电流在器件能力内 | 上升沿过缓导致时序余量不足;或灌电流过大 | 示波器量上升沿时间与低电平电压 |
| 低电平平台宽度 | 不小于器件规定的低电平时间下限 | 数据位被截断,START 被误判 | 示波器量低电平平台 |
| 高电平平台宽度 | 不小于器件规定的高电平时间下限 | 采样点靠边,偶发错位 | 示波器量高电平平台与上升沿 |
| SDA 相对 SCL 的建立 | 数据翻转完成于低电平期内 | 读到的值不确定 | 逻辑分析仪看位边界与时钟边界关系 |
| 总线电容与节点数 | 在速率档位下满足上升沿要求 | 高节点数时上升沿变缓 | 减节点做对比实验 |
| 时钟拉伸超时 | 主控必须实现并配超时 | 慢从机导致死锁或总线被占 | 读 SCL 是否有器件长期拉低 |
| 上电默认电平 | SDA 与 SCL 上电后均为高 | 总线被占用,START 发不出 | 上电后先量两线电平 |
| 电平转换方向 | 转换器方向与总线方向一致 | 读回全 0 或全 1 | 分段量电压找断点 |
遇到 I²C 读数据异常时,按这个顺序走:
- 上电量电平:SCL 与 SDA 是否都是高。若有一根一直是低,直接定位到把它拉低的器件。
- 示波器看上升沿:是不是近似直线、有没有平台。这是最容易被忽略也最容易出问题的一段。
- 量高低电平平台宽度:与手册下限对比,不要凭感觉。
- 逻辑分析仪看第 9 位:ACK/NACK 是否正常。这一位不对,问题在应答路径而非时序。
- 最后才动参数:调上拉电阻要一次只动一个并记录。
3. SPI 接口的四种模式
SPI 没有协议、没有统一命令集,它只是把「一位数据在什么时刻被采样」这件事用两个参数固定下来。CPOL 决定时钟空闲时停在哪,CPHA 决定第一位和后续各位分别在哪个沿被采样——两者组合出四种模式。本章把四种模式逐一拆开讲透,因为绝大多数「SPI 读不出数据」的问题都出自对这一章的理解不够,而不是硬件故障。
看完这一章,你应该能回答四个问题,而不只是背下「模式 0 是 CPOL=0 CPHA=0」:
- 时钟空闲时停在高电平还是低电平?
- 第一个数据位在哪个沿被采样?
- 第二个及之后的数据位在哪个沿被采样?
- 数据在哪个沿发生翻转?
很多资料只写前两点,读者看完仍然画不出波形——因为画波形真正需要的是后两点:采样沿决定了读到哪里,变化沿决定了什么时候必须换数。这两个沿必须严格交替,一旦重合,数据就会在翻转过程中被读走。
3.1 为什么 SPI 有四种模式
SPI 协议本身只规定了「有四根线、一根是时钟」,它没有规定双方如何在时钟上达成一致。问题出在两个地方:
- 时钟空闲时停在高还是低?不同厂商的器件在这一点上不统一,Flash 器件大多停在低,而某些传感器与显示控制器停在高。
- 数据在时钟的哪个沿被锁存?有的器件在时钟上升沿锁存,有的在下时钟沿锁存;也有的器件要求先输出再锁存(多半个周期),以保证首 bit 有输出时间。
两个问题各有两种答案,组合起来就是四种模式。四种模式不是四种「性能等级」,而是四种「时序约定」——它们之间不存在谁快谁慢,区别只在采样沿与变化沿的位置。把这一点想清楚,就不会再有「模式 3 比模式 0 快」这类误解。
四种模式中,模式 0 与模式 3 覆盖了绝大多数实际器件:模式 0 是各类存储器件与多数传感器的默认选择,模式 3 因首 bit 建立时间宽裕而在高速场合被推荐。模式 1 与模式 2 只在少数器件上出现,且总是成对出现在同一份手册里。本章后面会逐个拆开这四种模式。
3.2 CPOL:时钟空闲电平
CPOL(Clock Polarity,时钟极性)只回答一个问题:SCLK 在没有数据传输的时候停在哪个电平上。
- CPOL = 0:SCLK 空闲时为低电平,因此 CS 有效期间第一个出现的沿是上升沿。
- CPOL = 1:SCLK 空闲时为高电平,因此 CS 有效期间第一个出现的沿是下降沿。
CPOL 决定的其实是两件事:空闲电平,以及「第一个沿是哪一种沿」。第二件事经常被忽略,但它正是 CPHA 能够独立工作的前提——只有在 CPOL 确定之后,「第一个沿」和「第二个沿」才有确定含义。
从工程角度看,空闲电平的意义在于让总线在 CS 无效期间处于一个确定的状态:模式 0 的低电平是主控上电后的默认输出,模式 3 的高电平则便于用上拉把总线拉到确定电位,避免上电瞬间的毛刺被当成时钟沿。
3.3 CPHA:数据在哪个沿被采样
CPHA(Clock Phase,时钟相位)只回答一个问题:接收方在时钟的第几个沿把线上的电压读进去。
- CPHA = 0:数据在第 1 个沿(也称前沿 / leading edge)被采样。数据必须在第 1 个沿之前就已经稳定。
- CPHA = 1:数据在第 2 个沿(也称后沿 / trailing edge)被采样。第 1 个沿专门用来让发送方把数据放上去,第 2 个沿才读。
把这一条和第 2 节合起来,四种模式的沿分配就是确定的:
| CPOL / CPHA | 模式 | 空闲电平 | 第 1 个沿 | 第 2 个沿 | 采样沿 | 变化沿 |
|---|---|---|---|---|---|---|
| 0 / 0 | 模式 0 | 低 | 上升沿 | 下降沿 | 上升沿(第 1 个) | 下降沿(第 2 个) |
| 0 / 1 | 模式 1 | 低 | 上升沿 | 下降沿 | 下降沿(第 2 个) | 上升沿(第 1 个) |
| 1 / 0 | 模式 2 | 高 | 下降沿 | 上升沿 | 下降沿(第 1 个) | 上升沿(第 2 个) |
| 1 / 1 | 模式 3 | 高 | 下降沿 | 上升沿 | 上升沿(第 2 个) | 下降沿(第 1 个) |
因为变化沿决定了一位数据的有效期从什么时候开始。采样沿与变化沿严格交替、互不重合,这是四种模式共同的底层规则:
- 采样沿之后,接收方已经把这一位读走了;
- 下一个变化沿到来时,发送方才把这一位换成下一位;
- 因此两个沿之间的时间,就是这一位数据的安全余量。
如果采样沿与变化沿重合,接收方读到的就是数据正在翻转时的电压——这个值可能是高、可能是低、可能每次都不一样。这是 3.9 节两类失效形态的共同根源。
3.4 四种模式的完整对照
下面这张表是本章的核心。每种模式都必须读全四件事:取值、空闲电平、首位采样沿、后续位采样沿,缺任何一件都会在画波形时出错。
| 模式 | CPOL | CPHA | 空闲电平 | 首位采样沿 | 后续位采样沿 | 数据变化沿 | 典型使用者 |
|---|---|---|---|---|---|---|---|
| 模式 0 | 0 | 0 | 低 | 第 1 个沿,即上升沿 | 每一个上升沿 | 下降沿 | 绝大多数 SPI Flash、部分传感器与显示控制器 |
| 模式 1 | 0 | 1 | 低 | 第 2 个沿,即下降沿 | 每一个下降沿 | 上升沿 | 少数器件;双边沿采样场合 |
| 模式 2 | 1 | 0 | 高 | 第 1 个沿,即下降沿 | 每一个下降沿 | 上升沿 | 少数器件;与模式 1 常成对出现 |
| 模式 3 | 1 | 1 | 高 | 第 2 个沿,即上升沿 | 每一个上升沿 | 下降沿 | 多数高速 SPI Flash、部分 LCD 控制器 |
- 后续位的采样沿与首位完全相同。四种模式都不存在「首位特殊」的情况。首位之所以常出问题,是因为它的数据来源是片选拉低后的第一次输出,而不是移位寄存器里的下一位。
- 模式 0 与模式 1 都是空闲低,模式 2 与模式 3 都是空闲高。判断 CPOL 时不必看主控手册,看器件手册的时钟示意图第一段停在哪即可。
- 模式 0 与模式 2 的采样沿不同(上升 / 下降),模式 1 与模式 3 的采样沿也不同(下降 / 上升)。所以「都是 CPHA=0」并不意味着可以互换。
- 模式 0 与模式 3、模式 1 与模式 2 是两两配对的。很多器件手册会把模式 0/3 或 1/2 写在同一张时序图里,因为配对内采样沿相同,只是空闲电平不同。
- 没有任何一种模式是「更快」的。频率上限由第 5 章的时序预算决定,与模式选择无关;模式只决定采样沿落在哪里。
- 模式 1 与模式 2 的采样沿相同(都是下降沿),但空闲电平相反。只看采样沿无法区分这两个模式,必须同时确认空闲电平。
- 模式 0 与模式 3 的采样沿相同(都是上升沿),同样只靠采样沿无法区分。如果把模式 0 当成模式 3,或者反过来,从波形上完全看不出差别——因为差别在 CS 拉低之前 SCLK 停在哪。
- 首位的数据台阶起点不等于 CS 拉低的瞬间。模式 0 与模式 2 下,首位在 CS 拉低后就已经由从机准备;模式 1 与模式 3 下,首位要等到第 1 个变化沿才被推上线。
3.5 模式 0:CPOL=0 CPHA=0
模式 0 是覆盖面最广的模式,绝大多数 SPI Flash、部分传感器、显示控制器与 ADC 的默认模式都是它。四件事分别是:
- 取值:CPOL = 0,CPHA = 0。
- 时钟空闲电平:低电平。CS 无效期间 SCLK 停在低。
- 第一个数据位在哪个沿被采样:第 1 个沿,也就是上升沿。首位必须在 CS 拉低之后、第一个上升沿之前就已经被放到线上。
- 第二个及之后的数据位在哪个沿被采样:同样在每一个上升沿,与首位完全一致。数据在下降沿翻转。
也就是说,模式 0 的波形节奏是:低电平期间准备数据,上升沿采样,下降沿换数,然后重复。因为数据在下降沿才翻转,而下降沿落在低电平期,所以每一位数据的有效窗口跨越了整个高电平期——这是模式 0 首 bit 建立时间只有半个周期的原因,也是它在高速下最容易出问题的地方。
| 时刻 | SCLK | 从机(MISO) | 主控(MOSI) | 此时发生的事 |
|---|---|---|---|---|
| CS 拉低 → 第 1 个上升沿 | 保持低 | 把首位推到线上 | 把首位推到线上 | 双方利用这段时间建立首 bit |
| 第 1 个上升沿 | 由低变高 | 被主控采样 | 被从机采样 | 首位被读走 |
| 第 1 个下降沿 | 由高变低 | 切换到第 2 位 | 切换到第 2 位 | 数据翻转,必须在下一个上升沿前完成 |
| 第 2 个上升沿 | 由低变高 | 被主控采样 | 被从机采样 | 第 2 位被读走 |
| 此后每周期重复 | 低→高→低 | 逐位切换 | 逐位切换 | 采样沿始终是上升沿 |
从机在 CS 拉低的那一刻就必须开始驱动 MISO,而主控必须等自己的首个 MOSI 已经准备好才启动时钟。这两个动作之间的时间只有 CS 建立时间那么长,通常是一个很短的值。
常见的后果是:命令的第一个字节里靠前的几位(也就是地址或命令码的高位)在器件还没反应过来时就被采走,读回来的器件 ID 因此少了一两位或多了两位。这类故障的表现是「ID 读出来总差一个固定值」,很容易被误判为接线问题。
3.6 模式 1:CPOL=0 CPHA=1
模式 1 的四件事:
- 取值:CPOL = 0,CPHA = 1。
- 时钟空闲电平:低电平。
- 第一个数据位在哪个沿被采样:第 2 个沿,也就是下降沿。第 1 个沿(上升沿)不采样,只用来让发送方把首位推上线。
- 第二个及之后的数据位在哪个沿被采样:同样在每一个下降沿,与首位一致。数据在上升沿翻转。
模式 1 的节奏是:上升沿换数,下降沿采样。与模式 0 相比,整条波形往后挪了半个周期:首 bit 的建立时间从模式 0 的半个周期变成宽松的一整个周期,这是它唯一的优势。
3.7 模式 2:CPOL=1 CPHA=0
模式 2 的四件事:
- 取值:CPOL = 1,CPHA = 0。
- 时钟空闲电平:高电平。CS 无效期间 SCLK 停在高。
- 第一个数据位在哪个沿被采样:第 1 个沿。此时空闲电平是高,所以第 1 个沿是下降沿。
- 第二个及之后的数据位在哪个沿被采样:同样在每一个下降沿。数据在上升沿翻转。
模式 2 的采样沿与模式 1 完全相同,唯一的差别是 SCLK 停在高电平而不是低电平。因此从「读回来的数据」这一项上看不出任何区别,必须靠测量 CS 有效期间的第一个沿来判断。
它在实践中很少见到,原因有三:一是支持的器件少,手册明确标注支持的往往只有模式 0;二是首 bit 建立时间没有优势(与模式 0 一样是半个周期),而模式 3 同样空闲高却能给出一个完整周期;三是它与模式 1 构成一对——若一个器件族同时支持两个模式,一定是这一对,而不是模式 0 与模式 2。
3.8 模式 3:CPOL=1 CPHA=1
模式 3 的四件事:
- 取值:CPOL = 1,CPHA = 1。
- 时钟空闲电平:高电平。
- 第一个数据位在哪个沿被采样:第 2 个沿。第 1 个沿是下降沿,只负责把首位推上线;真正的采样发生在随后的上升沿。
- 第二个及之后的数据位在哪个沿被采样:同样在每一个上升沿。数据在下降沿翻转。
模式 3 的节奏是:下降沿换数,上升沿采样。由于时钟空闲在高电平,从机在 CS 拉低之后可以先保持输出,等第一个下降沿到来时才把首位正式推上线——从机因此获得了整整一个完整时钟周期的建立时间。
原因很直接:模式 3 的首 bit 建立时间是一个完整周期,模式 0 只有半个周期。在 3.9 节会看到,首 bit 出问题时的表现是「看起来像器件没响应」,而这类故障最难排查。
另外两点工程价值:
- 片选可以在时钟启动之前就拉低并稳定。模式 3 下 CS 拉低时 SCLK 停在高电平,从机有充足时间准备首位;模式 0 下 CS 一拉低就要立刻起时钟。
- 多从机场景下总线状态更明确。CS 无效期间 SCLK 保持高电平,可以用上拉把总线拉到确定状态,避免上电瞬间的毛刺被当成时钟。
需要说明的是:模式 3 的优势只在首 bit 上,对第 2 位及之后的位没有差别。如果数据传输量很大、首 bit 只占很小比例,模式 0 与模式 3 的实际差距会很小;真正决定能不能跑高速的是第 5 章的时序预算。
由于时钟空闲在高电平,从机在 CS 拉低之后可以先保持输出,等第一个下降沿到来时才把首位正式推上线——从机因此获得了整整一个完整时钟周期的建立时间。
3.9 模式不匹配的两种失效形态
模式配错时,故障不会报错、中断或超时,只会安静地给出错误数据。但它的表现可以归为两大类,识别方法完全不同。
| 失效形态 | 典型症状 | 波形成因 | 为什么没有报错 | 识别方法 |
|---|---|---|---|---|
| 形态一:像没响应 | 读回全 0 或全 1;器件 ID、状态寄存器全部异常且完全可重复 | 采样沿与变化沿完全重合,接收方在数据翻转的同一瞬间取值 | 总线时序完全合法,只是采到了一个错误值,主机无从察觉 | 换模式立刻恢复;波形上采样沿与变化沿落在同一点 |
| 形态二:像数据损坏 | 能读到数据但每位错一位、或整体移位、或高低字节颠倒 | 采样沿与变化沿错开半个周期,采到的是相邻位的数据 | 位结构仍然合法,命令字可能刚好被识别为一条有效命令 | 逻辑分析仪逐位对照;检查首 bit 与后续位的相位差是否一致 |
本章排查顺序
把本章压缩成可直接照着走的四步:
| 步骤 | 做什么 | 查什么 | 得到什么结论 |
|---|---|---|---|
| 第一步 | 打开器件手册,找到 SPI 时序图 | SCLK 在 CS 有效期间的第一段停在高还是低 | 确定 CPOL |
| 第二步 | 在时序图上找器件采样 DIN 的那个沿 | 它是第 1 个沿还是第 2 个沿 | 确定 CPHA,得到模式 |
| 第三步 | 对比器件给出 MISO 的变化沿 | 它与采样沿是否严格错开半个周期 | 确认沿的分配没有被误读 |
| 第四步 | 把模式写进主控配置后复测 | 读回的 ID 是否与手册标称值逐位一致 | 确认模式匹配,失败则转第 4 章 |
- 后续位的采样沿与首位相同。不存在「只有首位的采样沿特殊」这种模式。
- 模式 0 与模式 3 的采样沿相同,模式 1 与模式 2 的采样沿相同。区分它们必须看空闲电平,只看采样沿会把两个模式搞混。
- 模式不匹配的两种形态都不是「读不到数据」。如果真的是读不到(一直是同一个固定值),先怀疑片选、连线与供电,模式问题通常表现为「能读到但是错的」。
4. SPI 模式选择与使用注意事项
第 3 章讲清了四种模式本身的时序,本章解决实际工程里的问题:模式该由谁决定、常见器件支持哪些模式、选错了会怎样、片选与时钟怎么配合、全双工与半双工差在哪、多从机共享总线有哪些坑、DMA 会带来什么额外约束。
4.1 模式由谁决定:主控与器件谁说了算
结论只有一句:模式由器件的数据手册决定,主控只是被动跟随。
这个结论看起来理所当然,但工程上被违反的频率很高。常见的错误做法是:先看主控手册的默认配置(几乎总是模式 0),直接照抄,然后再去「试」器件。表面上试出来了,但一旦器件换批次、换型号、或者首 bit 偶发出错,就再也解释不通。
- 器件是时序的被动接受方,它的采样电路、输出驱动、CS 检测电路都是按某一个特定模式设计的。主控改模式不会改变器件的任何行为。
- 主控的 SPI 外设通常只支持模式 0 与模式 3(部分主控支持全部四种)。如果器件要求模式 1 或模式 2,而主控不支持,那么这块板在设计阶段就不应该成立——这是选型阶段要解决的问题,不是调试阶段。
- 唯一的例外是双向半双工与多 I/O 场合:此时主控还需要额外配置数据方向切换的时刻,而这部分是与模式正交的另一组约束。
先按主控默认模式配好驱动,再靠「换模式试」找到能通的那个。这个做法的问题是:你找到的是「能通」,不是「正确」。
很多器件在两种模式下都能给出看似合理但实际错误的读回——比如 ID 读对了但状态寄存器有一位是错的。这类故障在实验室里几乎发现不了,会一直带到量产。
正确的做法是在 原理图评审 阶段就把器件手册的时序图拿出来,逐条对照主控配置,写进评审记录。
4.2 常见器件支持哪些模式
不同类别的器件对模式的支持范围差别很大。下面按类别给出量级性的判断,具体到某个型号必须查它的手册。
| 器件类别 | 常见支持模式 | 通常固定为 | 说明 |
|---|---|---|---|
| 串行 NOR / NAND Flash | 模式 0 与模式 3 | 两者之一或都支持 | Flash 类器件绝大多数支持模式 0,部分同时支持模式 3;其余两种极少 |
| EEPROM | 模式 0 或模式 3 | 多数只支持一种 | 小容量 EEPROM 常只支持模式 0,必须逐型号确认 |
| 传感器(加速度、陀螺、温湿度) | 模式 0 或模式 3 | 多数固定一种 | 少数型号标注支持两种,实际波形时序图里会分别画出 |
| ADC / DAC | 模式 0 或模式 1 | 常与转换周期强相关 | 有些器件把「数据在哪个沿更新」与「转换何时完成」绑定,模式选择会受转换时间约束 |
| 显示控制器 | 模式 0 或模式 3 | 多数支持模式 0 | 带显存高速接口的控制器可能只支持其中一种 |
| RTC 实时时钟 | 模式 0 或模式 1 | 多数只支持一种 | 部分型号以模式 0 为主,同时兼容模式 3 |
| 片内 Flash 启动镜像的烧录窗口 | 由平台规定 | 不可自行更改 | 平台固件已经固化时序,主控配置必须与平台一致 |
器件手册写「支持模式 0 与模式 3」时,说的通常不是「可以任意切换」,而是两种模式下器件的采样沿与变化沿安排是同一套(都是下降沿变化、上升沿采样),差别只在 SCLK 的空闲电平。
这带来一个非常实用的结论:主控配模式 0、器件手册写支持模式 3,时序本身是兼容的——因为采样沿相同。反过来,主控配模式 0 而器件只支持模式 2,则采样沿从上升沿变成下降沿,两者完全错位,必然失败。
4.3 模式选错的典型故障表现
下表把症状、原因与排查动作对应起来。按症状反查是排查模式问题最快的路径。
| 观察到的症状 | 最可能的原因 | 怎么确认 | 处理 |
|---|---|---|---|
| 读回全 FF / 全 1 | 器件未驱动 MISO(CS 未选中、器件未上电、模式完全错位) | 量 CS 是否真的拉低;看 MISO 在 CS 低电平期间是否有波形 | 先确认 CS 与供电,再回到模式 |
| 读回全 00 | 器件未响应命令;或 MISO 被上拉/下拉固定住 | 看 MISO 是高阻被上拉还是被从机主动拉低 | 确认总线是否被占住 |
| 每位错一位 / 整体移位 | 采样沿偏了半个周期,采到相邻位 | 逻辑分析仪逐位对照首 bit 与后续 bit 的采样时刻 | 改模式或改数据相位 |
| 首字节错、后续字节正确 | 首 bit 建立时间不足(模式 0 / 2 常见) | 只看第一个字节的时钟与数据,看首个上升沿前数据是否稳定 | 改模式 3,或加大 CS 建立时间 |
| 命令正确但数据全错 | DOUT 侧采样沿与主控采样沿错位 | 分别检查读命令与写命令;写命令对、读命令错说明是 DOUT 方向问题 | 核对模式与三线/四线配置 |
| 低速正常、高速偶发错 | 余量不足而非模式错误(见第 5 章) | 降频复测;若降频能明显改善,优先查时序预算 | 转第 5 章 |
| 完全无波形 | CS 未拉低 / 引脚复用错误 / 器件未使能 | 量 CS 引脚在软件发起通信时是否有低电平 | 先查软件与引脚配置 |
4.4 片选与时钟的启动与收尾时序
片选 CS 在 SPI 里承担三件事:锁存命令、界定一位数据何时开始有效、指示一次事务的起止。时序上有三个必须关注的量。
| 时序量 | 含义 | 不满足时的表现 | 怎么改 |
|---|---|---|---|
| CS 建立时间 | CS 拉低到第一个时钟沿之间的最小间隔 | 首 bit 还没准备好就被采走,读回值固定差几位 | 换模式 3;或在软件里先拉 CS 再延时起时钟 |
| CS 保持时间 | 最后一个时钟沿到 CS 拉高之间的最小间隔 | 末位数据丢失,字节数少一位或校验不过 | 在软件里多打一个空时钟或延时后再拉高 CS |
| 器件间隔 | 一个器件 CS 拉高到下一个器件 CS 拉低之间的空档 | 两个器件同时驱动 MISO,总线争用,读回随机错误 | 在两路 CS 之间插入固定空档 |
- 模式 0 / 模式 2(采样在第 1 个沿):CS 一拉低就要尽快起时钟。因为从机只有「CS 建立时间」那么长来准备首 bit,这个时间通常很短。
- 模式 1 / 模式 3(采样在第 2 个沿):CS 可以先拉低并稳定,等 SCLK 走过第 1 个沿(只用来换数)之后,第 2 个沿才采样。这就是模式 3 在片选时序上的具体优势落地的地方。
软件层面的对应做法是:不要把「拉低 CS」和「启动时钟」写成同一段紧邻的代码。把它们分开,或者用硬件外设的 CS 管理功能,在时间上留出明确的间隔。
4.5 全双工与半双工的时序差别
前面几章讨论的都是四线全双工 SPI:MOSI 与 MISO 是两根独立的线,主控与从机在同一时刻各自发送与接收。它的时序最简单——两根数据线上的变化沿各自独立,只要模式匹配就一定成立。
三线(半双工)SPI 把 MOSI 与 MISO 合成一根双向线,这会额外引入一个时序维度:方向切换的时机。
| 维度 | 四线全双工 | 三线半双工 | 时序影响 |
|---|---|---|---|
| 数据线 | 两根,单向各一根 | 一根,双向复用 | 同一根线上既有主控输出也有从机输出 |
| 方向切换 | 不需要 | 每次读命令前后都要切换 | 切换期间必须让双方都释放总线 |
| 换向时间 | 无 | 器件手册规定的 turnaround 时间 | 换向不足时读到的是自己刚发出去的数据 |
| 能否同时收发 | 可以 | 不可以 | 读操作必须先发命令再收数据,分两个阶段 |
| 波形复杂度 | 低:CLK / DIN / DOUT 三线对齐 | 高:还要标出方向切换点 | 排查时必须先确认方向切换时刻 |
| 吞吐效率 | 高 | 低(换向期间不发时钟) | 连续读时需要流水线才能接近全双工 |
- 换向期间发了时钟。如果驱动在切换方向后立刻开始发时钟,而器件还没完成总线释放,就会把主控自己的输出当成读回数据。表现是「读回来的第一个字节总等于我刚发的命令字节」。
- 多从机时总线释放不同步。如果某个从机在未选中时仍驱动三线总线,主控切换方向后会被它拉住。半双工比全双工更依赖器件「CS 无效即高阻」的行为。
规避手段是优先使用四线;如果必须用三线,把方向切换写成显式的独立步骤,并在切换后留出确定的空档再起时钟,而不是依赖两个寄存器写操作的隐式延迟。
4.6 多从机共享总线的时序陷阱
多从机时,SCLK、MOSI、MISO 三根线由所有从机共享,只有 CS 各自独立。这带来三条硬约束。
- 未被选中的从机必须保持高阻。这是总线能否工作的前提。高阻由器件的 CS 电路保证,不由软件保证——必须查器件手册确认。
- 若器件在 CS 无效期间不释放 MISO,总线会被占住。此时无论选哪个从机都读不到数据,而且现象是「只要上一个器件被访问过,后面就全错」。
- 所有从机的 CPOL / CPHA 必须一致。因为 SCLK 是共享的,模式不同的从机会在不同的沿上采样,从而读到错位的数据。
| 陷阱 | 现象 | 成因 | 确认手段 | 规避 |
|---|---|---|---|---|
| 总线被占住 | 访问过 A 之后,B 永远读不到 | A 在 CS 无效期间仍驱动 MISO | 看 CS 全高期间 MISO 是否仍有跳变 | 换用 CS 无效即高阻的器件;或在硬件上加缓冲 |
| 切换瞬间争用 | 偶尔错,且错的位置随机 | 两路 CS 之间空档不足,两个从机同时驱动 | 同时观察两路 CS 与 MISO | 在驱动里固定插入器件间隔 |
| 模式不一致 | 某个从机单独访问正常,多从机同时挂上就错 | 共享 SCLK,但各从机要求不同模式 | 核对全部器件手册的模式要求 | 选型阶段统一模式;无法统一时分批使用 |
| MISO 线长差异 | 离主控远的从机更容易错 | MISO 是共享的,各从机支线长度不同导致延迟不一致 | 量各支线长度与实测波形 | 等长处理;必要时用缓冲器 |
| 上电瞬间误选中 | 上电后偶发读到某器件数据一次 | CS 上电电平不确定,或内部上拉未生效 | 量 CS 上电时的电平与爬升时间 | CS 加下拉,确保上电即无效 |
4.7 DMA 场景下的额外时序约束
DMA 解决了「CPU 来不及搬数据」的问题,但它引入了三个新的时序不确定因素。这三点是真实工程里非常容易踩的坑。
| 约束 | 具体问题 | 表现 | 处理方式 |
|---|---|---|---|
| 首字节延迟 | 启动 DMA 之后到第一个时钟真正打出去之间存在不确定延迟 | 器件要求的建立时间可能不满足,首字节错 | 首个字节用软件发送,或在启动后插入确定的空等 |
| 收发双 DMA 的对齐 | 发送与接收两条通道同时启动,两者进入采样的时刻不完全相同 | 全双工下 MOSI 与 MISO 的采样点错开,数据配对失败 | 两条通道用同一触发源;若不能,改为半双工分时 |
| 取数延迟 | 时钟已经发完,但 CPU 或 FIFO 里的数据还没取到 | DMA 完成中断来得比时钟晚,误以为传输失败或读到旧数据 | 以 DMA 完成中断为准,不要在时钟停止后立刻读缓冲 |
| FIFO 深度不足 | 突发长度超过 FIFO 能容纳的量 | FIFO 溢出导致后续字节错位 | 控制突发长度,或在传输中段做一次中断服务 |
| 总线矩阵争用 | DMA 与 CPU 同时访问同一外设寄存器 | 配置写入被打断,模式与分频值错乱 | 启动前完成所有配置,中途不再改寄存器 |
在 DMA 传输中,时钟的最后一个沿已经结束,但接收 FIFO 里的数据可能还没被搬到内存。如果代码用「时钟发完了就去读缓冲」的方式判断,会读到上一次传输的残留。
正确做法是:等待传输完成中断,而不是用任何形式的轮询或延时去猜。如果必须查询状态位,读的是「接收 FIFO 非空」而不是「时钟忙」——两者的时机并不相同。
4.8 模式选择的决策清单
下面这张表可以照着走一遍。前三步在设计阶段就要做完,后两步在调试阶段验证。
| 步骤 | 做什么 | 查什么 | 得到什么结论 |
|---|---|---|---|
| 第 1 步 | 把所有 SPI 器件列出来 | 器件手册的时序图第一段 SCLK 停在高还是低 | 每个器件的 CPOL |
| 第 2 步 | 逐个器件确认采样沿 | 器件在第几个沿锁存 DIN | 每个器件的 CPHA |
| 第 3 步 | 检查所有器件模式是否一致 | 模式不一致时能否分时使用 | 统一的模式,或需要分时的结论 |
| 第 4 步 | 确认主控 SPI 外设支持该模式 | 主控手册的模式支持列表 | 硬件方案成立或需要改选器件 |
| 第 5 步 | 把配置写进代码并复测关键读回 | ID、状态寄存器是否逐位正确 | 模式配置正确,可进入高速与时序余量评估 |
做完这五步,应当得到一份可以进评审的记录,包含三行内容:
- 每个器件的 模式(CPOL / CPHA),以及出处(手册的哪张时序图);
- 主控侧的模式配置值与时钟分频档位;
- 如果存在多从机,器件间隔的实现方式(软件延时、外设自动管理还是硬件保证)。
这三行在未来换料、换主控、升频速时会被反复用到,是排障时最快的索引。