接线没错,只是数值大了一倍
一句话总结
SPI 有时钟线,所以不存在速度问题。但在哪个边沿读取仍然留作配置,一旦这个配置错位,读出的值就会差一位。
为什么需要它
用新的闪存芯片读取厂商 ID,却得到了莫名其妙的值。接线检查了三遍,时钟也进来了,芯片也有响应,只是值不对。这种表现通常不是接线问题,而是模式问题。而模式只写在数据手册表格的某一个格子里,很容易被忽略。
SPI 是没有规范文档的事实标准,所以术语也因厂商而略有不同。因此,与其看“文档上写了什么”,不如看“波形说了什么”,后者更快。幸运的是,SPI 波形会自己说明模式。
工作原理
共有四根线:选择线(CS 或 SS)、时钟(SCLK)、主设备发送的 MOSI、从设备发送的 MISO。只有选择线为低期间才是传输,每个时钟边沿传送一个位。双向同时进行,所以即使发送读取命令,MOSI 上也必须载有某些内容。
配置只有两个。CPOL 表示空闲时时钟是高还是低,CPHA 表示在前一个边沿读取还是在后一个边沿读取。把二者组合起来,称为模式 0 到 3。TI 的 SPI 用户指南也把这两个值当作各自独立的设置(SPRUGP2)。sigrok 的 SPI 解码器接受的设置也是五个:cs_polarity、cpol、cpha、bitorder、wordsize(文档)——这个列表说明了哪些东西仅凭波形是无法确定的。
CPOL=0 CPHA=0 (모드 0) CPOL=1 CPHA=1 (모드 3)
SCLK __/‾\_/‾\_/‾\__ SCLK ‾‾\_/‾\_/‾\_/‾‾
읽는 곳 ^ ^ ^ 읽는 곳 ^ ^ ^
상승 모서리 상승 모서리
这里有一个会绊倒初学者的事实:模式 0 和模式 3 在同一个边沿读取。上图中二者都是上升沿。模式 1 和模式 2 也同样使用彼此相同的边沿(下降沿)。所以仅看时钟边沿,无法区分四种模式。另一半信息是空闲时时钟处于什么位置,也就是 CPOL。要从波形判定模式,必须分别看这两件事。
判定 CPHA 的方法更有趣。真实的器件并不会在时钟边沿上立刻改变数据,而是在输出有效延迟之后才改变。所以在波形上,找到 MOSI 开始变动的时刻之前紧邻的那个时钟边沿,那个边沿就是不用于读取的一侧。读取边沿在另一侧,如果它是脱离空闲状态的前一个边沿,则 CPHA=0,否则 CPHA=1。如果在数据变化的边沿读取,就会取到上一位,导致整体错开一格——这就是前面所说的“莫名其妙的 ID”的真相。
选择线的时序也会造成悄无声息的故障。如果 CS 晚于第一个时钟边沿才拉低,那个边沿就不包括在传输中。从设备没有收到第一位,主设备却以为已经发送了。在波形上,表现为 CS 为低期间的采样边沿数不是 8 的倍数。在本课程的采集中,本应是 24 个的边沿只有 23 个,剩下 7 位。有剩余的位,说明字节边界错位了,而且最先说话的是个数,而不是值。
字节顺序也是需要确认的对象。大多数是先发高位,但也有器件先发低位,仅凭波形无法判断是哪一种。这是必须查文档的项目。
最后,时钟频率很少成为故障的原因。SPI 会同时发送时钟线,所以主设备摇得慢,从设备也会慢慢跟着。与 UART 不同,“速度不匹配”这种说法不成立,数据手册里只写了器件能承受的最大频率。所以在 SPI 上,值如果有问题,先看边沿和选择线,而不是速度。
在现场相遇的样子
最常见的报告是“读出的值是两倍或一半”。差一位的值,用十六进制看,恰好就是这种样子。把 0x9F 左移一位是 0x3E,右移一位是 0x4F。看到值时如果产生“差不多是两倍”的感觉,先怀疑模式会更快。
在多个从设备共用一条总线的电路板上,会发生模式混乱的事故。每个从设备都要求自己的模式,如果驱动没有在每次传输时切换模式,就会出现有的芯片能读、有的读不了的情况。“只有这个传感器不行”的报告,相当一部分出在这里。
下一项测验要确认什么
会问到 CPOL 和 CPHA 各自决定什么、为什么仅看边沿无法区分四种模式、如何利用数据变化的边沿判定 CPHA,以及选择线延迟时,波形中的哪个数字最先出现异常。