4. 多字节连续传输解码:捕获多字节连续写操作、识别数据包边界(CS片选信号)、解析连续数据流(如0x01 0x02 0x03)、理解字节间的高阻态与连续传输

各位同学,咱们今天聊点实战的。

前面几节课,我们都在看单个字节怎么传。但实际项目中,谁只传一个字节啊?你想想看,配置一个寄存器,往往要写地址+数据;刷一个LCD屏幕,更是成千上万个字节往外扔。所以,多字节连续传输才是SPI通信的常态。

这节课,我就带你用逻辑分析仪,把一段连续的数据流抓下来,然后一步步拆解。看看CS片选信号怎么划清边界,字节之间到底发生了什么,以及那个让人又爱又恨的“高阻态”是怎么回事。

4.1 先看波形:一次典型的连续写操作

我习惯把逻辑分析仪的探头夹好,设置采样率到50MHz(对于10MHz的SPI时钟,5倍采样够了)。然后触发条件设为CS下降沿。一按Capture,波形就出来了。

你会看到这样的场景:

  • CS(片选):一开始是高电平,然后“唰”一下拉低,保持低电平,最后再拉高。
  • SCLK(时钟):在CS拉低期间,连续输出8个、16个、24个...脉冲,中间不停顿。
  • MOSI(主出从入):每个时钟沿上,数据线都在变化,连续输出一串比特流。
  • MISO(主入从出):从机也在同时回复数据。

嗯,这里要注意:CS低电平的持续时间,就是一次完整传输的“包长度”。CS拉高,代表这次传输结束,从机开始解析收到的数据。

核心概念:在SPI协议中,CS片选信号就是数据包的“边界线”。CS低电平期间传输的所有字节,属于同一个“数据包”或“帧”。

4.2 识别数据包边界:CS片选信号的妙用

我在项目中遇到过好几次这样的问题:两个同事写的代码,一个发数据时CS拉低后一直保持,另一个发完一个字节就拉高再拉低。结果两边对不上,调试了一整天。

为什么会这样?因为CS的拉高动作,告诉从机:“好了,这批数据我发完了,你赶紧处理吧。”

举个例子,我们想连续写入三个字节:0x01, 0x02, 0x03。正确的做法是:

  1. CS拉低
  2. 发送0x01(8个时钟)
  3. 发送0x02(8个时钟)
  4. 发送0x03(8个时钟)
  5. CS拉高

这样,从机收到的是一个包含3个字节的数据包。如果你在0x01和0x02之间把CS拉高再拉低,那从机就会认为你发了三个独立的数据包,每个包只有一个字节。这在某些协议里是致命的错误。

我的小技巧:用逻辑分析仪解码时,先看CS的宽度。如果CS低电平持续了24个时钟周期,那大概率是3个字节。如果CS低电平只持续了8个时钟,那就是单字节传输。一眼就能看出问题。

4.3 解析连续数据流:从波形到0x01 0x02 0x03

好,现在我们抓到了一段波形。CS拉低,SCLK连续跑了24个脉冲。怎么把MOSI上的数据解析出来?

步骤很简单:

  • 找到第一个SCLK的上升沿(假设是模式0,CPOL=0, CPHA=0)。
  • 采样MOSI电平,得到第1个bit(通常是MSB,高位在前)。
  • 连续采样8个bit,拼成一个字节。比如:0x01 = 0000 0001。
  • 继续采样接下来的8个bit,得到0x02 = 0000 0010。
  • 再采样8个bit,得到0x03 = 0000 0011。

你看,逻辑分析仪自动就帮你算好了。但手动看波形时,我建议你先找到字节的起始点。怎么找?看CS拉低后的第一个时钟沿,那就是第一个字节的bit0(或bit7,取决于相位)。

实战数据:假设你看到MOSI波形是:
CS拉低 -> 0010 1010 -> 0101 0101 -> 1100 0011 -> CS拉高
那么解码结果就是:0x2A, 0x55, 0xC3。连续传输,没有中断。

4.4 字节间的高阻态与连续传输

这个问题,很多新手会忽略。我刚开始用SPI时也踩过坑。

在连续传输中,字节和字节之间,MOSI和MISO线上是什么状态?

  • 连续传输(正常模式):CS保持低电平,SCLK连续输出。字节之间没有间隙,MOSI上的数据是连续变化的。从上一个字节的最后一个bit,直接过渡到下一个字节的第一个bit。没有高阻态。
  • 字节间有间隙(某些实现):有些MCU的SPI外设,在发送完一个字节后,会短暂释放MOSI线(变成高阻态),或者保持上一个bit的电平。这时候,逻辑分析仪上会看到一段“平坦”的波形,或者电平不确定。

我曾经调试一个传感器,发现读回来的数据总是错位。用逻辑分析仪一看,原来主控在字节之间把MOSI拉高了一小会儿(变成了高阻态,被上拉电阻拉高),而传感器误以为那是新的起始位。后来我改了SPI配置,让主控在字节间保持CS低电平且MOSI持续输出,问题就解决了。

注意:高阻态在SPI多字节传输中是个隐患。如果你的从机对时序要求严格,务必确保主控在CS有效期间,MOSI/MISO线始终保持驱动状态,不要出现高阻态窗口。否则,数据包边界可能会被错误识别。

4.5 实战解码步骤总结

好了,说了这么多,我给大家总结一个标准流程。下次你拿到一段SPI波形,就这么干:

  1. 找CS边界:找到CS下降沿(传输开始)和上升沿(传输结束)。
  2. 数时钟:在CS低电平期间,数一数有多少个SCLK脉冲。8个脉冲=1字节,16个=2字节,以此类推。
  3. 逐字节解码:从第一个时钟沿开始,每8个时钟采样一次MOSI,得到字节值。
  4. 检查间隙:观察字节之间是否有“空闲”时钟周期,或者MOSI是否出现高阻态。如果有,说明这不是严格的连续传输。
  5. 验证MISO:别忘了看从机回复的数据。有时候主机发0x01,从机可能回0xAA,这能帮你判断通信是否正常。
我的习惯:在逻辑分析仪软件里,我会把CS设为“帧起始”信号,然后让软件自动按8bit一组解码。这样一眼就能看到整个数据包的内容。如果解码结果里有乱码,十有八九是时钟相位/极性配错了,或者字节顺序(MSB/LSB)搞反了。

嗯,这节课的内容就到这儿。多字节连续传输,说白了就是CS拉低后的一串连续时钟和数据。边界看CS,内容看MOSI,间隙看高阻。记住这三点,你就能轻松驾驭SPI的数据流了。

下一节,我们会聊聊更复杂的场景——SPI双工通信与MISO数据解析。到时候,我们不仅要看主机发了什么,还要看从机回了什么。敬请期待。