目录
简介
spi物理层
SPI( Serial Peripheral Interface, 串行外设接口)是一种全双工同步串行通信接口,它用于MCU与各种外围设备以串行方式进行通信以交换信息,通信速度最高可达25MHz以上。SPI 总线具有三种传输方式:全双工、单工以及半双工传输方式。
SPI通常由四条线组成,一条主设备输出与从设备输入( Master Output Slave Input, MOSI),一条主设备输入与从设备输出( Master Input Slave Output, MISO),一条时钟信号( Serial Clock, SCLK),一条从设备使能选择( Chip Select, CS)。与I²C类似,也可以使用GPIO模拟SPI时序
SPI可以同时发出和接收数据,因此SPI的理论传输速度比I²C更快。 SPI通过片选引脚选择从机,一个片选一个从机,因此在多从机结构中,需要占用较多引脚,而I²C通过设备地址选择从机,只要设备地址不冲突,始终只需要两个引脚
连接方式
CS片选线:从设备选择信号线,常称为片选信号线,也称为 NSS、 SS,无论有多少个从设备,都共同只使用这 3 条总线;而每个从设备都有独立的这一条 NSS 信号线,本信号线独占主机的一个引脚,即有多少个从设备,就有多少条片选信号线。当主机要选择从设备时,把该从设备的 CS信号线设置为低电平,该从设备即被选中,即片选有效,为开始信号;被拉高作为结束信号
SCK :时钟信号线,用于通讯数据同步,两个设备之间通讯,速率受限于低速设备
MOSI:主设备输出/从设备输入引脚,即这条线上数据的方向为主机到从机
MISO:主设备输入/从设备输出引脚,即在这条线上数据的方向为从机到主机
框图
①STM32F10x芯片有3个 SPI 外设,SPI1 是 APB2 上的设备,最高通信速率达 36Mbtis/s, SPI2、 SPI3 是 APB1 上的设备,最高通信速率为 18Mbits/s,除了通讯速率,在其它功能上没有差异。因为SPI3 用到了下载接口的引脚,这几个引脚默认功能是下载,第二功能才是 IO 口,如果想使用 SPI3 接口,则程序上必须先禁用掉这几个 IO 口的下载功能。
②波特率发生器根据“控制寄存器 CR1”中的 BR[0:2] 位控制,对 fpclk 的分频结果就是 SCK 引脚的输出时钟频率
配置“控制寄存器 CR”的“CPOL 位”及“CPHA”位可以把 SPI 设置成的 4 种 SPI模式,后续在协议层分析
③通过写 SPI 的“数据寄存器 DR”把数据填充到发送缓冲区中,通讯读“数据寄存器 DR”,可以获取接收缓冲区中的内容。其中数据帧长度可以通过“控制寄存器 CR1”的“DFF 位”配置成 8 位及 16 位模式;配置“LSBFIRST 位”可选择 MSB (高位)先行还是 LSB(低位) 先行
④:负责协调整个 SPI 外设,工作模式根据配置的“控制寄存器(CR1/CR2)”的参数而改变,控制参数包括前面提到的 SPI 模式、波特率、 LSB 先行、主从模式、单双向模式等等;在外设工作时,控制逻辑会根据外设的工作状态修改“状态寄存器(SR)”,我们只要读取状态寄存器相关的寄存器位,就可以了解 SPI 的工作状态了。
一般不使用 STM32 SPI 外设的标准 NSS 信号线,而是更简单地使用普通的GPIO,软件控制它的电平输出,从而产生通讯起始和停止信号。也就是用模拟方式拉低拉高片选信号
协议层:
数据处理
在SCK时钟周期的驱动下, MOSI和MISO同时进行,数据输入输出是同时进行的
主机和从机都有一个移位寄存器,主机移位寄存器数据经过MOSI将数据写入从机的移位寄存器,此时从机移位寄存器的数据也通过MISO传给了主机,实现了两个移位寄存器的数据交换,外设的写操作和读操作是同步完成的。无论主机还是从机,发送和接收都是同时进行的,如同一个“环”
如果主机只对从机进行写操作,主机只需忽略接收的从机数据即可。如果主机要读取从机数据,需要主机发送一个空数据来引发从机发送数据。
传输模式
CPOL( Clock Polarity,时钟极性) 表示SCK在空闲时为高电平还是低电平。 当CPOL=0, SCK空闲时为低电平, 当CPOL=1, SCK空闲时为高电平。
CPHA( Clock Phase,时钟相位) 表示SCK在第几个时钟边缘采样数据。 当CPHA=0, 在SCK第一个边沿采样数据,当CPHA=1, 在SCK第二个边沿采样数据
实际中采用较多的是“模式 0”与“模式 3”
模式0
CPOL=0&&CPHA=0 的时序如下图,可以看到串行时钟的奇数边沿上升沿采样:
CPOL=0:看到对应时序中当数据未发送或者发送完毕, SCL 的状态是低电平;
CPHA=0:即是奇数边沿(第一个边沿)采集,可以看到传输的数据会在奇数边沿上升沿被采集;
MOSI和 MISO :数据的有效信号需要在 SCK 奇数边沿保持稳定且被采样,在非采样时刻(下降沿), MOSI 和MISO 的有效信号才发生变化
起始和停止信号
NSS 信号线由高变低,是 SPI 通讯的起始信号。 NSS 是每个从机各自独占的信号线,当从机在自己的 NSS 线检测到起始信号后,就知自己被主机选中了,开始准备与主机通讯。
void spi_start(void)
{
/*片选线高电平拉低*/
ctrl_cs(0);
}
NSS 信号由低变高,是 SPI 通讯的停止信号,表示本次通讯结束,从机的选中状态被取消
void spi_stop(void)
{
/*片选线低电平拉高*/
ctrl_cs(1);
}
发送和接收数据
/*数据交换(收发)*/
uint8_t spi_swap_byte(uint8_t byte_send)
{
uint8_t i,byte_receive = 0x00;
for(i=0;i<8;i++)
{
/*开始sck默认低电平,现在就可以交换数据*/
ctrl_mosi(byte_send & (0x80 >> i));/*通过控制对应的GPIO进行高位先发*/
ctrl_sck(1);/*控制对应的GPIO拉高sck读取数据*/
if(1 == read_miso())/*读取对应的GPIO接收数据*/
{
byte_receive |= (0x80 >> i);
}
ctrl_sck(0);/*拉低时钟结束*/
}
return byte_receive;/*交换得到的数据*/
}
模式1
CPOL=0&CPHA=1 的时序如下图,串行时钟的偶数边沿下降沿采样:
CPOL=0:所以 SCL 的空闲状态依然是低电平
CPHA=1: 数据就从偶数边沿(第二个边沿)采样,下降沿
模式2
CPOL=1&&CPHA=0 的时序如下图
CPOL=1:SCL 空闲状态为高电平
CPHA=0:奇数边沿采样的情况下,数据在奇数边沿下降沿要保持稳定并等待采样
模式3
CPOL=1&&CPHA=1 的时序如下图
CPOL=1:SCL状态是高电平,奇数边沿的边沿极性是上升沿,偶数边沿的边沿极性是下降沿
CPHA=1:数据在偶数边沿上升沿被采样。在奇数边沿的时候 MOSI 和 MISO 会发生变化,在偶数边沿时候是稳定的。
总结
先看CPHA,时钟相位为0,第一个(奇)边沿采样;为1,第二个(偶)边沿采样;再看CPOL,时钟极性为0,说明空闲的时候是低电平,低电平第一个采样信号肯定是拉高,由此判断是上升沿还是下降沿采样;同理时钟极性为1,说明空闲的时候是高电平,高电平第一个采样信号肯定是拉低,由此判断是上升沿还是下降沿采样