本文简单介绍一下SPI这个协议,SPI算是众多协议里相对简单的.
本质:串行外设接口(Serial Peripheral Interface Bus,SPI),这些只介绍最基础的SPI,QSPI暂时不做讨论(后续可能会补充)。由于速度快,经常有作大容量E方,SD卡等的通讯方式
第一原则:SPI通讯的核心是,同步发送,交换数据
SPI至少需要占用四个IO口(一主一从的情况):
- SCLK(Serial Clock):时钟信号,由主机发出
- MOSI(Master Output, Slave Input):主机输出,从机输入信号(数据由主机发出)
- MISO(Master Input, Slave Output):主机输入,从机输出信号(数据由从机发出)
- SS(PCS,CS, Slave Select):片选信号,由主机发出,一般是低电位有效(当有多个从机时可以通过将对应SS引脚置低的方式来选择从机)
毕竟速度快,在资源方面就要做出一些让步。相比IIC就多占用两个IO口。
在接线方面是主机的MOSI接从机的MOSI;主机的MISO接从机的MISO;即同名引脚直接相连
下面直接通过云途YCT工具来看相关SPI外设的配置项
PCS是片选引脚,图中选择了PCS0,即在PCS0低电平时,选择对应的从机进行数据通讯
Pcs polarity 为极性
Bits/frame 一帧大小bits,一般来说都是设置成8位,比较常见的还有12位和16位
云途MCU帧长度设置比较灵活
下面就是经典的通过配置SPI的时钟极性(CPOL)和时钟相位(CPHA):来选择四个模式
云途使用的这种表述方式也挺直观的
根据我的经验,选择CPHA==1的情况(偶尔边沿采样)通讯可能会稳定一些
默认是MSB,即高位先行
每次通信时,SPI 必须同时发送和接收数据。如果主机想读取从机数据,需要先发送占位字节(Dummy Data)。发送的数据按位(Bit)在 SCLK 的有效边沿传输。数据在时钟的采样边沿被接收并存储到接收寄存器中
1 | //云途 |
可以看到在有一些MCU的SPI里面send和receive没有独立的API,都是一个transmit
下面我来看一个例子:
同时收发数据通常出现在主设备(Master)在向从设备(Slave)发送某些命令或数据的同时,从设备也将状态或数据返回给主设备。
主设备(比如 MCU)需要从 SPI Flash 存储器中读取数据。
主设备需要发送一条命令来指定要读取的内存地址,同时从设备将指定地址的数据返回给主设备。
- 主设备发送“读取命令”(通常为一个字节,比如 0x03)。
- 主设备继续发送目标内存地址(通常是 3 个字节,比如 0x001234)。
- 同时,从设备在接收命令和地址时会返回无意义的占位数据(Dummy Data)。
- 地址发送完毕后,从设备会根据主设备生成的时钟信号,将存储器中指定地址的数据返回。
在这整个过程中:主设备发送数据时,同时接收数据。
最初接收的数据可能是无意义的占位数据,而后续接收的则是有意义的有效数据。
假设需要读取地址 0x001234
的数据:
1 | 主设备发送: 0x03 0x00 0x12 0x34 0xFF 0xFF 0xFF ... |
- 0x03 是读取命令。
- 0x00 0x12 0x34 是要读取的地址。
- 0xFF 是主设备发送的占位数据,用于驱动时钟。
- 0x45 0x67 0x89 是从设备返回的有效数据。注意看是从设备给的
在阅读国民关于SPI的手册发现一个有趣的点,部分LCD屏通过SPI通讯时需要用到单线模式;其中双线单向模式可以同时使用MOSI及MISO数据线向一个方向传输数据,可以加快一倍的传输速度
我们在逻辑分析仪中取一段来分析一下
可以看到时钟线默认是低,即CPOL为0
在第一个边沿就开始采样了,即CPHA为0
所以会SCK信号的上升沿进行数据采样
MOSI的bits 为 0010 0001,接收到的数据是21,可以看出是高位优先的逻辑
暂时先写到这里,后续可能还会补充。笔者能力有限,有疏漏之处还请指出
参考文献:
1 | 国民技术032 DS,RM手册 |