目录

设备间数据通信 —— 串行外设接口(SPI)协议

设备间通信

两个设备或者多个设备之间通信时,需要有一份共同遵守的协议,避免鸡同鸭讲。

常见的通信协议有:SPI、USB、UART、I2C、CAN[1][2]。

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311221924751-1130898363.png

图 1:不同的设备间通信协议

不同的协议是为了满足特定场景的要求而制定的,而不是为了好玩。因此应该分析特定应用的要求,并选择合适的协议。

SPI 协议

使用 SPI 协议的场景是全双工、同步传输、一主多从、线少、高速率。

以下是使用 SPI 协议通信的设备群:

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311191157014-1621896305.png

图 2:SPI 一主多从

从图中可以看出一对设备通过 SPI 协议进行通信需要四条线。SPI 四条线分别是:

  • 片选信号线(CS,Chip Select):选设备
  • 主输出从输入数据线(MOSI):传数据
  • 从输出主输入数据线(MISO):传数据
  • 时钟信号线(SCK,Serial Clock):提供采集数据的时机

数据传输线

由于使用同步传输,所以传输一个字节的 8 位二进制不需要八条导线,只需要一条线分 8 个时钟发送就行了。下文的时钟信号线部分会再次提到。

另外由于要支持全双工,即一次传输过程中主设备传输数据到从设备的同时,从设备也可以传输数据到主设备,因此需要两条传输方向不同的线 MOSI(Master Out/Slave In) 和 MISO(Master In/Slave Out)。如下图:

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311191407446-441429328.png

图 3:全双工。蓝色线表示主设备输出,红色线表示从设备输出。

从图 3 可以看出,单向传输的线连接了多个从设备。

注意这里的接线方式:主设备的 MOSI 接从设备的 MOSI,主设备的 MISO 接从设备的 MISO。

此时我们有了疑问:这些从设备都会同时接收数据吗?多个从设备同时发送数据给主设备岂不是冲突了?

片选信号线

主设备会通过控制从设备的 CS 引脚来激活从设备。上面说过从设备的 CS 引脚为低电平的时候,从设备被激活。

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311222746258-1765371721.png

图 4:片选信号线

下图表示从设备被激活后传输数据(NSS 是 CS 引脚的另一个称呼):

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311213848399-1139696150.png

图 5:拉低片选线后才开始传输数据

红框部分表示持续激活从设备,以及采集数据。

注意,主设备用 I/O 线连接到从设备的片选信号线上。

时钟信号线

时钟信号线提供读取数据信号的时机。时钟信号由主设备提供给从设备。

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311204513610-163970667.png

图 6: 时钟信号(中间波浪线表示省略 N 个信号)

时钟线的作用是提供高低电平的变化作为数据采样的信号。根据不同的模式,可以是从高到低的时候采样,也可以是从低到高的时候采样。

SPI 协议有四种通信模式,分别由 CPOL(时钟极性)和 CPHA(时钟相位)来控制。也就是选择采样的时机。

CPOL(Clock POLarity) 表示时钟空闲时的电平。0 为低电平,1 为高电平。如下图表示 CPOL = 0。

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311213910339-404998509.png

图 7:空闲的 SCK 为低电平,即 CPOL 为 0 的情况

CHPA(Clock PHAse) 表示数据有效的时刻的相位,或者说边沿(Edge)。边沿指的是电平变化的时刻,有两种类型:上升沿(Rising Edge)和下降沿(Falling Edge)。0 表示处于第一个边沿类型的时刻数据有效(进行采样),1 表示处于第二个边沿类型的时刻数据有效(进行采样)。

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311213926019-704580723.png

图 8:上升沿和下降沿

下图标出了采样的时机:

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311213145292-1971254984.png

图 9:工作在(0,1)模式的数据采样

四种模式用下表列出:

SPI 通信模式CPOLCPHA特点
000时钟空闲时保持低电平,工作时在上升沿从输入引脚采样,在下降沿改变输出引脚的数据
101时钟空闲时保持低电平,工作时在下降沿从输入引脚采样,在上升沿改变输出引脚的数据
210时钟空闲时保持高电平,工作时在下降沿从输入引脚采样,在上升沿改变输出引脚的数据
311时钟空闲时保持高电平,工作时在上升沿从输入引脚采样,在下降沿改变输出引脚的数据

注:两个通信的设备要配置为同一个模式才能正常通信。

通信双方采样的时机是一致的,改变输出的时机也是一致的。不然 A 在采样的时候,B 把输出改了,那 A 得到的数据可能是修改前的数据也可能是修改后的数据,就乱了。

如何确保主从处于同一模式?应该以从设备的模式为准,再配置主设备的模式。从设备的模式有两种情况[3]:

  • 从设备的 SPI 模式由硬件决定,已经被固定
  • 从设备有 SPI 控制器,则 SPI 模式由软件决定,可配置

在模式相同且片选信号线拉低时,开始通信。通常芯片内部的 SPI 控制器会自动控制在 8 次取样后停止通信,也就是一次传输 8 bit,即一个字节。但也可以使用 I/O 线模拟片选信号,这样一次可以传送多个字节[4]。

https://img2020.cnblogs.com/blog/809218/202103/809218-20210311213145292-1971254984.png

图 10:工作在(0,1)模式的数据采样

图 10 中的 MSB 和 LSB 表示最高权重位(Most Significant Bit)和最低权重位(Least Significant Bit)[5]。权重指的是对这个数值影响程度高,例如十进制的万比千的权重高。

一个字节,即 8 位二进制数据可以从最高位开始发送,也可以从最低为开始发送。

举个例子:

一个字节的数据:1000 0000

MSB------LSB
10000000

从最高位开始发送就是先发 1。

如果通信双方没有达成一致,则接收者得到的数据和发送者的数据的含义不一致。不过这个通常不需要我们配置。

总结

如果要用到 SPI 协议,需要接四条线。

  • 主设备的 MISO 接从设备的 MISO
  • 主设备的 MOSI 接从设备的 MOSI
  • 主设备的 SCK 接从设备的 SCK
  • 主设备任选一个 I/O 接从设备的 CS

主设备在编程的时候需要配置与从设备相同的 SPI 模式。

主设备在编程的时候需要配置第一位(First Bit)[6]先从 MSB 开始发还是 LSB 开始发。从设备会规定第一位是 MSB 还是 LSB。

参考:

1
2
3
4
5
6
[1]: https://zhuanlan.zhihu.com/p/47925844 (常见硬件通信协议介绍)
[2]: https://blog.csdn.net/heda3/article/details/89053635 (IIC、SPI、UART、USART、USB、CAN等通讯协议原理及区别)
[3]: https://blog.csdn.net/u013165704/article/details/81076890 (SPI 接口配置)
[4]: https://blog.csdn.net/qq_25814297/article/details/86190106 (SPI通讯有单字节模式和多字节连续模式)
[5]: https://www.cnblogs.com/shuaifeng/archive/2009/12/23/1630195.html (MSB与LSB)
[6]: https://www.stmcu.org.cn/module/forum/thread-627137-1-1.html ([分享] SPI原理超详细讲解---值得一看)