SPI( Serial Peripheral Interface )串行外围设备接口是许多不同设备使用的通用通信协议。例如, SD卡模块, RFID卡读取器模块和 2.4 GHz无线发送器/接收器 均使用SPI与微控制器通信。
SPI的一个独特优势是可以无中断传输数据 。可以在连续流中发送或接收任意数量的位。使用I2C和UART,数据以数据包形式发送,限制为特定位数。开始和停止条件定义了每个数据包的开始和结束,因此数据在传输过程中被中断。
通过SPI通信的设备处于主从关系。主机是控制设备(通常是微控制器),而从机(通常是传感器,显示器或存储芯片)从主机获取指令。SPI的最简单配置是一个主机,一个从机系统,但是一个主机可以控制多个从机(下面有更多介绍)。
MOSI(主机输出/从机输入) –主机将数据发送到从机的线路。

MISO(主机输入/从机输出) –从机将数据发送到主机的线路。

SCLK(时钟) –时钟信号线。

SS / CS(从站选择/芯片选择) –主站用于选择向其发送数据的从站的线路。
实际上,从站的数量受到系统负载电容的限制,这降低了主机在电压电平之间准确切换的能力。

SPI如何运作

时钟信号将主设备的数据位输出同步到从设备的位采样。每个时钟周期传输一位数据,因此数据传输的速度取决于时钟信号的频率。由于主机配置并生成时钟信号,所以SPI通信 始终由主机启动

设备共享时钟信号的任何通信协议都称为 同步 SPI是一种同步通信协议 。还有一些 异步 方法不使用时钟信号。例如,在UART通信中,将双方都设置为指示数据传输速度和时序的预配置波特率。

可以使用 时钟极性 时钟相位 的属性来修改SPI中的时钟信号。这两个属性共同定义何时输出位以及何时对其进行采样。主机可以设置时钟极性,以允许在时钟周期的上升沿或下降沿输出和采样位。可以设置时钟相位,以便在时钟周期的第一沿或第二沿进行输出和采样,而不管它是上升还是下降。

从设备选择

主机可以通过将从机的CS / SS线设置为低电压电平来选择要与之通信的从机。在空闲,非传输状态下,从选择线保持在高电压电平。主机上可能有多个CS / SS引脚,这允许多个从机并行连接。如果仅存在一个CS / SS引脚,则可以通过菊花链将多个从机连接到主机。

多个从设备

可以将SPI设置为与单个主机和单个从机一起运行,也可以与由单个主机控制的多个从机一起设置。有两种方法可以将多个从站连接到主站。如果主站有多个从站选择引脚,则从站可以按以下方式并联:
如果只有一个从设备选择引脚可用,则可以通过以下方式菊花链连接从设备:

MOSI和MISO

主机通过MOSI线以串行方式将数据发送到从机。从机通过MOSI引脚接收主机发送的数据。从主机发送到从机的数据通常先发送最高有效位。

从机还可以通过MISO线串行将数据发送回主机。从从机发送回主机的数据通常首先以最低有效位发送。

SPI的读像是发一个数据那样简单,整个总线需要的时钟信号是由主机端提供的,也就是说不论是给从机发数据或者从从机读数据,时钟信号都需要由主机来产生,主机要读数据的时候需要给从机时钟信号,这个信号只能是在主机发数据的时候产生,这样就需要主机发一个数据,这样就产生了时钟信号,从机就会把数据放到总线上来了。为了避免这个假发出去的数据让从机误动作,一般都是让主机为高电平。

SPI数据传输步骤

  • 主机输出时钟信号:
  • 主机将SS / CS引脚切换到低电压状态,从而激活从机:
  • 主机沿着MOSI线路一次将数据发送到从机。从站读取接收到的位:
  • 如果需要响应,则从机沿着MISO线一次向主机返回一位数据。主机读取接收到的位:

    SPI的优缺点

    使用SPI有一些优点和缺点,如果在不同的通信协议之间进行选择,则应根据项目要求知道何时使用SPI:

  • 没有起始位和停止位,因此可以连续传输数据而不会中断
  • 没有像I2C这样复杂的从站寻址系统
  • 数据传输速率比I2C更高(几乎快两倍)
  • 分开的MISO和MOSI线路,因此可以同时发送和接收数据
  • 使用四根线(I2C和UART使用两根线)
  • 没有确认已成功接收数据的确认(I2C拥有此确认)
  • 没有任何形式的错误检查,如UART中的奇偶校验位
  • 只允许一个主机
  • UART代表通用异步接收器/发送器( Universal Asynchronous Receiver/Transmitter )。它不是像SPI和I2C这样的通信协议,而是微控制器中的物理电路或独立的IC。UART的主要目的是发送和接收串行数据。

    关于UART的最大的优点之一是它 仅使用两条线在设备之间传输数据

    在UART通信中,两个UART直接相互通信。发送UART将来自控制设备(如CPU)的并行数据转换为串行形式,以串行方式将其发送到接收UART,然后接收UART将接收到的串行数据转换回并行数据。只需要两条线就可以在两个UART之间传输数据。数据从发送UART的Tx引脚流到接收UART的Rx引脚:

    UART 异步传输数据,这意味着 没有时钟信号 将发送UART的位输出与接收UART的位采样同步。发送UART代替时钟信号,将 开始 停止位 添加到正在传输的数据包中。这些位定义了数据包的开始和结束,因此接收UART知道何时开始读取这些位。

    当接收UART检测到起始位时,它将开始以称为波特率的特定频率读取输入位。波特率是数据传输速度的度量,以每秒位数(bps)表示。 两个UART必须以大约相同的波特率工作。在位的时序变得太远之前,发送和接收UART之间的波特率只能相差约10%。

    还必须将两个UART配置为发送和接收相同的数据包结构。

    UART如何运作

    将要发送数据的UART从数据总线接收数据。数据总线用于通过其他设备(例如CPU,内存或微控制器)将数据发送到UART。数据以 并行形式从数据总线传输到发送UART(电路实现参考数字电路多功能移位寄存器) 。发送UART从数据总线获取并行数据后,它将添加起始位,奇偶校验位和停止位,以创建数据包。接下来,数据包在Tx引脚上 逐位串行输出 。接收UART在其Rx引脚上逐位读取数据包。然后,接收UART将数据转换回并行形式,并删除起始位,奇偶校验位和停止位。最后,接收UART将数据包并行传输到接收端的数据总线:
    UART传输的数据被组织成 数据包 。每个数据包包含1个起始位,5至9个数据位(取决于UART),一个可选的奇偶校验位以及1个或2个停止位:

    UART数据传输线通常在不传输数据时保持在高电压电平。为了开始数据传输,发送UART在一个时钟周期内将传输线从高电平拉低到低电平。当接收UART检测到高到低电压转换时,它开始以波特率的频率读取数据帧中的位。

    数据帧包含正在传输的实际数据。如果使用奇偶校验位,则可以是5位,最多8位。如果不使用奇偶校验位,则数据帧的长度可以为9位。在大多数情况下,数据首先以最低有效位发送。

    奇偶性描述数字的偶数或奇数。奇偶校验位是接收UART判断传输期间是否有任何数据更改的方式。电磁辐射,不匹配的波特率或长距离数据传输会改变数据位。接收UART读取数据帧后,它将对值为1的位数进行计数,并检查总数是偶数还是奇数。如果奇偶校验位为0(偶数奇偶校验),则数据帧中的1位应总计为偶数。如果奇偶校验位为1(奇校验),则数据帧中的1位应合计为奇数。当奇偶校验位与数据匹配时,UART知道传输没有错误。但是,如果奇偶校验位为0,则总数为奇数;或奇偶校验位为1,且总数为偶数,则UART知道数据帧中的位已更改。

    为了用信号通知数据包的结束,发送UART将数据传输线从低电压驱动到高电压至少持续两位时间。

    UART传输步骤

  • 发送UART从数据总线并行接收数据:
  • 发送UART将起始位,奇偶校验位和停止位添加到数据帧:
  • 整个数据包从发送UART串行发送到接收UART。接收UART以预先配置的波特率对数据线进行采样:
  • 接收UART丢弃数据帧中的起始位,奇偶校验位和停止位:
  • 接收UART将串行数据转换回并行数据,并将其传输到接收端的数据总线:

    UART的优缺点

    以下是一些利弊,可帮助您确定它们是否适合您的项目需求:

  • 仅使用两根电线
  • 无需共用时钟信号
  • 具有奇偶校验位以允许进行错误检查
  • 需要双方都设置好数据包的结构
  • 文档可查并应用广泛
  • 数据帧的大小最大为9位
  • 不支持多个从属系统或多个主系统
  • 每个UART的波特率必须在彼此的10%之内
  • 如果您参与过使用OLED显示器,气压传感器或陀螺仪/加速度计模块的项目,则可能会发现自己使用的是I2C。

    I2C结合了SPI和UART的最佳功能。使用I2C,您可以将多个从机连接到单个主机(如SPI),并且可以有多个主机控制一个或多个从机。当您希望有多个微控制器将数据记录到单个存储卡或将文本显示到单个LCD时,此功能非常有用。

    与UART通信一样,I2C仅使用两条线在设备之间传输数据:

    SDA(串行数据) –主站和从站发送和接收数据的线路。

    SCL(串行时钟) –传送时钟信号的线。

    I2C是串行通信协议,因此数据沿着单条线(SDA线)单个比特地传输。

    像SPI一样,I2C是同步的,因此位输出通过主机和从机之间共享的时钟信号同步到位采样。 时钟信号始终由主机控制。

    I2C如何运作

    使用I2C,数据以消息形式传输 。消息被分解 为数据帧。每条消息都有一个包含从站的二进制地址的地址帧,以及一个或多个包含正在发送的数据的数据帧。该消息还包括每个数据帧之间的开始和停止条件,读/写位和ACK / NACK位:

    启动条件: 在SCL线从高电平切换到低电平之前 ,SDA线从高压电平切换到低压电平 。

    停止条件: SCL线从低切换到高后, SDA线从低电压切换到高电压 。

    地址帧: 每个从属设备唯一的7位或10位序列,用于在主设备要与其通信时标识该从属设备。

    读/写位: 一位,指定主机是向从机发送数据(低电压)还是向从机请求数据(高电压)。

    ACK / NACK位: 消息中的每个帧后均带有一个确认/不确认位。如果成功接收到地址帧或数据帧,则会从接收设备向发送方返回ACK位。

    I2C没有像SPI这样的从设备选择线,因此它需要另一种方式来让从设备知道正在向其发送数据,而不是另一个从设备。它通过寻址来实现。地址帧始终是新消息中起始位之后的第一帧。

    主机将要与之通信的从机的地址发送给与其连接的每个从机。然后,每个从站将从主站发送的地址与其自己的地址进行比较。如果地址匹配,它将向主机发送一个低电压ACK位。如果地址不匹配,则从站不执行任何操作,并且SDA线保持高电平。

    地址帧的末尾包含单个位,该位通知从设备主机是否要向其写入数据或从中接收数据。如果主机要向从机发送数据,则读/写位为低电压电平。如果主机正在从机请求数据,则该位为高电压电平。

    主机检测到从机的ACK位后,即可发送第一个数据帧。

    数据帧始终为8位长,并以最高有效位优先发送。每个数据帧后紧跟一个ACK / NACK位,以验证是否已成功接收到该帧。在发送下一个数据帧之前,主机或从机必须接收ACK位(取决于谁发送数据)。

    发送完所有数据帧后,主机可以向从机发送停止条件以停止传输。停止条件是SCL线上从低到高的转换之后,SDA线上的电压从低到高的转换,而SCL线保持高电平。

    I2C数据传输步骤

  • 在将SCL线从高电平切换到低电平之前,主机通过将SDA线从高电平切换到低电平来向每个连接的从机发送启动条件:
  • 主机向每个从机发送要与之通信的从机的7位或10位地址,以及读/写位:
  • 每个从机将主机发送的地址与其自己的地址进行比较。如果地址匹配,则从机通过将SDA线拉低一位返回一个ACK位。如果来自主机的地址与从机自身的地址不匹配,则从机将SDA线拉高:
  • 主机发送或接收数据帧:
  • 传输完每个数据帧后,接收设备将另一个ACK位返回给发送方,以确认已成功接收到该帧:
  • 为了停止数据传输,主机将SCL切换为高电平,然后再将SDA切换为高电平,从而向从机发送停止条件:

    单个主机具有多个从机

    由于I2C使用寻址,因此可以从一个主机控制多个从机。使用7位地址时,可以使用 \(2^7=128\) 个唯一地址。使用10位地址并不常见,但是会提供 \(2^{10}=1024\) 个唯一地址。要将多个从机连接到单个主机,请使用 \(4.7K\Omega\) 上拉电阻将它们连接,将SDA和SCL线连接到Vcc:

    多个主机具有多个从机

    多个主机可以连接到一个或多个从机。当两个主机尝试通过SDA线路同时发送或接收数据时,会出现同一系统中多个主机的问题。为了解决这个问题,每个主机都需要在发送消息之前检测SDA线是低电平还是高电平。如果SDA线为低电平,则意味着另一个主机可以控制总线,并且主机应等待发送消息。如果SDA线为高电平,则可以安全地发送消息。要将多个主机连接到多个从机,请使用下图,其中 \(4.7K\Omega\) 上拉电阻将SDA和SCL线连接到Vcc:

    I2C的优缺点

  • 仅使用两根电线
  • 支持多个主机和多个从机
  • ACK / NACK位用于确认每个帧都已成功传输
  • 硬件不如使用UART复杂
  • 众所周知且应用广泛
  • 数据传输速率比SPI慢
  • 数据帧的大小限制为8位
  • 需要实现比SPI更复杂的硬件
  • 图片来源于: https://www.circuitbasics.com/