01 SPI简介
SPI,全称为Serial Peripheral interface,即串行外围设备接口。由摩托罗拉率先在产品上使用。SPI是一种高速全双工,同步(full duplex synchronous)的通信总线协议,且占用硬件端口只有4个(SO,SI, SCLK 和CSN),所以出于这种简单易用的特性,越来越多的芯片开始将该总线协议集成在了芯片中。在工作中如果涉及到底层软件编写,大概率会经常用到SPI通信。打开英飞凌官网,直接搜索一个工作中比较常用到的芯片TLE75080,对应着相应章节结合实际开发来学习。
02 协议详解
⚫ SPI采用主从模式的控制方式
SPI协议规定必须由主设备(Master)控制从设备(Slave),首先通过CS片选信号选中特定的从设备,然后通过SCK引脚给Slave设备提供时钟。Slave 设备本身不能产生或控制 Clock, 没有 Clock 则 Slave 设备不能正常工作。理论上,主设备可以控制无限多个从设备,(实际上,从设备挂载的个数也受限于具体的硬件环境)。如图:
⚫ SPI采用同步传输方式进行通信
当通信发生时,主设备会生成相应的时钟脉冲信号,在每个时钟的上升沿或者下降沿,时钟信号会驱动设备内部的移位寄存器,使得主设备的数据从移位寄存器中移出后移入从设备的移位寄存器中,同时从设备也会有数据从SO引脚移出到主设备中。这样就保证了数据的同步传输。一般来说,SPI并没有读和写的说法,本质上,数据的通信其实也是数据交换的过程。
SPI 设备间的数据传输之所以又被称为数据交换, 是因为 SPI 协议规定一个 SPI 设备不仅能在数据通信过程中充当一个 "发送者(Transmitter)" 或者 "接收者(Receiver)". 在每个 Clock 周期内, SPI 设备都会发送并接收一个 bit 大小的数据, 相当于该设备有一个 bit 大小的数据被交换了。
03 工作原理
⚫ 两个寄存器SSPBUF , SSPSR
SSPBUF:Synchronous Serial Port Buffer, 泛指 SPI 设备里面的内部缓冲区, 一般在物理上是以 FIFO 的形式, 保存传输过程中的临时数据;
SSPSR,:Synchronous Serial Port Register, 泛指 SPI 设备里面的移位寄存器(Shift Regitser), 它的作用是根据设置好的数据位宽(bit-width) 把数据移入或者移出 SSPBUF;
SPI 设备在进行通信的过程中, Master 设备和 Slave 设备之间会产生一个数据链路回环(Data Loop), 就像上图所画的那样, 通过 SDO 和 SDI 管脚, SSPSR 控制数据移入移出 SSPBUF, Controller 确定 SPI 总线的通信模式, SCK 传输时钟信号。
⚫ 时序说明
以TLE75080为例,从上图中可以获取的信息有:
✔ 16bits SPI
✔ 以MSB模式传输数据
✔ 数据在时钟的下降沿移入TLE75080芯片中,在时钟下降沿移出
✔ 时钟在空闲时为低电平
⚫ 极性和相位
在SPI中有个很重要的参数即极性和相位,比较常见的缩写为CPOL,CPHA。就是在上一节中TLE75080交换数据的方式,数据在时钟的下降沿移入TLE75080芯片中,在时钟下降沿移出。所以极性和相位都是相对于时钟来说的。
再此需要插一段边沿(edge)的概念,在每个脉冲里,都有一个上升沿和一个下降沿,对于Leading edge来说就是第一个边沿,对于开始电压是1,那么就是1变成0的时候,对于开始电压是0,那么就是0变成1的时候;Trailing edge是第二个边沿,对于开始电压是1,那么就是0变成1的时候(即在第一次1变成0之后,才可能有后面的0变成1),对于开始电压是0,那么就是1变成0的时候;
所谓极性SPI的CPOL,表示当SCLK空闲idle的时候,其电平的值是低电平0还是高电平1:
CPOL=0,时钟空闲idle时候的电平是低电平,所以当SCLK有效的时候,就是高电平,就是所谓的active-high;
CPOL=1,时钟空闲idle时候的电平是高电平,所以当SCLK有效的时候,就是低电平,就是所谓的active-low;
相位CPHA对应于数据采样是在时钟的第几个边沿,0为第一个边沿,1为第二个边沿。(1) CPHA=0,表示第一个边沿:✔ 对于CPOL=0,idle时候的是低电平,第一个边沿就是从低变到高,所以是上升沿;✔ 对于CPOL=1,idle时候的是高电平,第一个边沿就是从高变到低,所以是下降沿;(2) CPHA=1,表示第二个边沿:✔ 对于CPOL=0,idle时候的是低电平,第二个边沿就是从高变到低,所以是下降沿;✔ 对于CPOL=1,idle时候的是高电平,第一个边沿就是从低变到高,所以是上升沿;
那么相位,极性配合起来,就有4中情况,如图(图片来自网络)。
⚫ 再聊SSPSR
SSPSR 是 SPI 设备内部的移位寄存器(Shift Register). 它的主要作用是根据 SPI 时钟信号状态, 往 SSPBUF 里移入或者移出数据, 每次移动的数据大小由 Bus-Width 以及 Channel-Width 所决定。
Bus-Width 的作用是指定地址总线到 Master 设备之间数据传输的单位.
例如, 我们想要往 TLE75080 设备里面的 SSPBUF 写入 16 bits 大小的数据: 首先, 将mcu相关寄存器设置 宽度 为 16bits; 然后配置为MSB传输模式。
再在相应的寄存器中设置相位和极性。到此,主设备mcu的spi主要属性已经配置完毕。
然后往 mcu 设备的 Tx-Data 移位寄存器在地址总线的入口写入数据, 每次写入 16bits 大小的数据(使用 writeb 函数); 写完之后, mcu设备里面的 Tx-Data 移位寄存器会自动把从地址总线传来的16bits数据移入 SSPBUF 里。
Channel-Width 的作用是指定 Master 设备与 Slave 设备之间数据传输的单位. 与 Bus-Width 相似, Master 设备内部的移位寄存器会依据 Channel-Width 自动地把数据从 Master-SSPBUF 里通过 Master-SDO 管脚搬运到 Slave 设备里的 Slave-SDI 引脚, Slave-SSPSR 再把每次接收的数据移入 Slave-SSPBUF里.通常情况下, Bus-Width 总是会大于或等于 Channel-Width, 这样能保证不会出现因 Master 与 Slave 之间数据交换的频率比地址总线与 Master 之间的数据交换频率要快, 导致 SSPBUF 里面存放的数据为无效数据这样的情况。
04 调试结果
以TLE75080为例,SPI通信是由ss(cs)、sck、sdi、sdo构成,总线上挂载了2片TLE75080,其时序其实很简单,主要是在sck的控制下,两个双向移位寄存器进行数据交换。根据上文手册中的spi属性配置如图:
从上图可以看出,从设备只有在片选选中的时候,才会对移入移位寄存器的数据进行处理并同时返回给主设备相应数据。这样就可以实现两个芯片交替通信。
然后放大后,可以看到数据是在下降沿的时候进行采样,时钟会在空闲时置低。极性相位一目了然。
至此SPI的主要原理就暂告一段路了。
编辑:Zhang Jinwei
部分图片来自网络
往期文章:
CMake简介
走进IP
Linux下Socket通信
聊聊汽车诊断刷新那点事