本文是对国外优秀技术文章的翻译,采用意译方式。原文链接如下:
Serial Peripheral Interface (SPI),原文作者为:MIKEGRUSIN
译者注:我最近也在学习嵌入式,正处于入门阶段,原本想着学了51和32就能上手工作了,但实际上工作中遇到的可能是各种各样的芯片,往往只是给定了一个软件手册和数据手册,所以最重要的不是学习了多少种芯片,而是掌握快速上手芯片的技巧,同时,对于底层的通信协议及其应用也要有较为深入的了解。
介绍
串行外设接口(SPI)是一个接口总线,常被用于在微控制器和小型外设间收发数据。这些外设包括:移位寄存器、传感器、SD卡。它有独立的时钟和数据线,也有一个特定的线去选择想传输数据的设备。
串口存在什么问题?
形如TX线和RX线这样的通用串口,被称为是“异步的”,因为它没有控制数据收发的时刻,也不能保证通信双方的运行速率完全一致。自从计算机普遍依赖单一时钟来保持同步以来,当两个系统的时钟存在轻微差异时,就会成为它们间通信的一大问题。
为了解决这个问题,可以通过在每个字节上增加额外的开始和结束位来帮助接收方实现数据的同步,与此同时,双方都必须提前在传输速率上达成一致(比如9600)。当然,传输速率上的细小差别不会造成大问题,因为接收方在每个字节的开始都会重新同步。
但为什么收发速率不一致会导致收到的数据变成垃圾呢?这是因为接收方是在特定时间对接收到的位进行采样,如果它在错误的时间采集这些位,就会得到错误的数据。
值得注意的是,如上图所示:串行协议首先发送的是数据的最后一个位,所以看到的数据11001010实际上是01010011,也就是0x53。
译者注:如上图所示,数据从一端的TX发送至另一端的RX,所以使用串口通信时这两根线在两端要交叉。
同步的解决方案
SPI的工作方式稍有不同。
它是一个“同步”的数据总线,这也意味着它使用分开的线来管理数据和时钟以保持两端完美同步。时钟信号是一个波动的信号来告诉接收方具体在什么时刻在数据线上进行数据位采样,这可能是时钟信号的上升沿或下降沿,芯片具体采用哪一种情况可以参考对应的数据手册。当接收方检测到信号沿时,它会立即查看数据线去读取下一位。
由于时钟和数据是和数据一起发送的,所以指定数据发送速率就显得不是那么必要了(尽管设备会有一个可发送的最高速率)。
为什么SPI协议如此受欢迎呢?因为它的接收方甚至可以是最简单的移位寄存器,硬件成本低。
接收数据
注意:类似于主从这样的说法已经过时了,现在都用控制器、外部设备这样的说法,以下是名词术语对照表:
Obsolete Name | Replacement Name |
---|---|
Master | Controller |
Slave | Peripheral |
MISO | POCI |
MOSI | PICO |
SS | CS |
命名约定可能因制造商、编程语言、公司或组织而异,要具体情况具体分析。
回传数据
从反方向将数据回发会稍微复杂一些。
在SPI中,只有一端会产生时钟信号,这一端被称为控制器,而另一端则被称为外设。控制器总是只有一个(一般就是你的微控制器),但可以接很多外设。
当数据从控制器发送到外设时,是从一根叫PICO(Peripheral In / Controller Out)的数据线发送的。如果外设需要返回响应数据给控制器,控制器就会继续产生一定数量(事先已确定数额)的时钟周期,而外设会将数据放到第三根被称为POCI的数据线来传输。
前面提到回传数据时时钟周期是“事先已确定数额”的,这是因为控制器总是会产生时钟信号,所以它必须提前知道一个外设何时会返回数据、以及返回多少数据。这一点和异步串行十分不同,异步串行是在任意时刻、任意方向都可能会有任意数据在传输。
实际上这不是什么问题,因为SPI通常被用于告诉传感器这有个特定的命令结构。举个例子:当你发送了一个“读取数据”的命令给设备时,你知道设备总是会把数据发给你的,有时候你还会指定一下数据段的长度等等。
注意,SPI是全双工的,也就是有独立的收、发线,所以在确定的场景中可以实现同时收发数据。
关于芯片选择(CS)
还有一条线叫CS线,全称是chip select,是决定控制器要和哪一个外设进行通信的。
当不连接外设的时候,它是高电平;低电平反而表示外设处于活跃状态。
多外设连接方式
- 每条外设都连接一条独立的cs线
通常用于链移位寄存器和可寻址LED驱动器。
- 多条外设共用一条cs线,PICO线将不同外设串起来
通常用于只输出数据的情况。