目录
一、SPI总线概念
SPI协议其实是包括:Standard SPI、Dual SPI和Queued SPI三种协议接口。
1、通常我们说的SPI就是Standard SPI,有4根信号线,分别为CLK、CS、MOSI和MISO。数据线工作在全双工;
2、Dual SPI,它只是针对SPI Flash而言,不是针对所有SPI外设。对于SPI Flash,全双工并不常用,因此扩展了mosi和miso的用法,让它们工作在半双工,用以加倍数据传输。也就是对于Dual SPI Flash,可以发送一个命令字节进入dual mode,这样mosi变成SIO0(serial io 0),mosi变成SIO1(serial io 1),这样一个时钟周期内就能传输2个bit数据,加倍了数据传输;
3、Qual SPI Flash增加了两根I/O线(SIO2,SIO3),目的是一个时钟内传输4个bit; 这里我们主要讲解Standard SPI,四根信号线全双工通信。
二、SPI 总线框图
2.1 单一主机单一从机
4线SPI总线有四个信号: 时钟(SPI CLK,SCLK)。 片选(CS)。 主机输出、从机输入(MOSI)。 主机输入、从机输出(MISO)。 产生时钟信号的器件称为主机(MCU)。主机和从机之间传输的数据与主机产生的时钟同步。
2.2 单一主机多从机
SPI多从机工作原理是指SPI主机如何与多个SPI从机进行通信的方法,有以下两种方式:
多NSS方式:每个从机都需要一条单独的SS线,主机通过拉低对应的SS线来选择与哪个从机通信,保持其他SS线为高电平,避免数据线上的冲突。这种方式需要占用更多的引脚,但是可以实现全双工通信。
菊花链方式:所有从机的MOSI和MISO线都连接在一起,形成一个环形链路,主机通过发送一个空字节来引发从机的传输,每个从机都会把接收到的数据向下一个从机传递,直到数据回到主机。这种方式只需要一条SS线,但是只能实现半双工通信,并且传输速度受限于最慢的从机。
三、SPI 模式
SPI的时钟极性和相位的配置通常称为 SPI模式,所有可能的模式都遵循以下约定,具体如下:
SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性CPOL (Clock Polarity)和相位CPHA(Clock Phase)可以配置。CPOL,表示SCLK空闲的时候,其电平值是低电平还是高电平;CPHA,表示数据采样在第一个跳变沿还是第二个跳变沿。
CPHA=0,表示第一个边沿:
对于CPOL=0,SCLK空闲时是低电平,第一个跳变沿就是从低变到高,所以是上升沿; 对于CPOL=1,SCLK空闲时是高电平,第一个跳变沿就是从高变到低,所以是下降沿;
CPHA=1,表示第二个边沿:
对于CPOL=0,SCLK空闲时是低电平,第二个跳变沿就是从高变到低,所以是下降沿; 对于CPOL=1,SCLK空闲时是高电平,第二个跳变沿就是从低变到高,所以是上升沿;
四、SPI 时序图
五、SPI总线调试
STM32 SPI常见问题 虽说SPI相对比较简单,但在实际应用过程中还是会遇到各种问题,下面通过案例来分析SPI常见的一些问题。
问题一:NSS片选问题 有工程师使用硬件NSS控制从机,以为NSS信号是自动控制,导致操作从设备失败。
分析原因:STM32 SPI的NSS信号为片选信号,可“使能”为硬件控制。
但在应用中同样需要软件操作才能控制NSS信号(高低),比如:
SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set);
解决办法:按照通信时序,控制NSS信号高低(通常低有效)。
问题二:SPI引脚复用功能问题 STM32的SPI是一种复用功能,之前使用标准外设库的工程师容易遗漏复用功能的配置导致SPI不能使用。
分析原因:SPI有些引脚对应的是特殊功能的引脚,比如:PB3(MISO)对应的是 JTDO,如果不配置则默认这个引脚的功能就是 JTDO的功能。
以前经常存在这种问题,但现在通过工具STM32CubeMX配置时自动配置了复用功能。
解决办法:参考官方提供在初始化代码中配置复用功能(如下是使用HAL库进行配置)。
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
问题三:时钟速率过高问题 有工程师购买一个通信为SPI的模块,最高通信速率8MB/s,他使用10.5MB/s通信速率也能用,但偶尔会出现通信异常。
分析原因:一个芯片标称的最高速率其实是相对保守的值,在条件比较好的情况下超过了最高值也能用,但不能保证稳定性。
STM32 SPI的时钟频率由系统时钟和分频决定,有的工程师没有深入理解这些参数,发现能用就不管了。 如果修改系统时钟,其实SPI通信速率也会发生相应变化;
解决办法:最简单的办法就是修改分频值。同时,如果环境恶劣,建议使用屏蔽线。(在保证整个产品系统实时性的同时,尽量降低通信速率)。
问题四:时钟相位问题 有不少工程师在调试SPI时会遇到数据“移位”的问题,数据能收发为什么会出现这种问题呢?
分析原因:SPI通信时钟由主机提供,本身上电时(主从)各自的信号就不稳定,如果从机时钟相位也不匹配,就会因为时钟引起数据移位,或者异常的情况。
解决办法:软件上匹配SPI主从设备的时钟相位,使用通信协议,CRC、 checksum校验等。
六、SPI调试神器
记录和显示SPI信号:逻辑分析仪可以通过USB连接电脑,通过探针夹住SPI的MISO、MOSI、SCK、NSS等信号线,记录并显示SPI的数字波形,方便观察和分析。
解码和分析SPI数据:逻辑分析仪可以根据SPI的时钟极性、相位、数据位等参数,自动或手动地解码SPI的数据帧,将数字波形转换为十六进制或二进制的数据,方便查看和对比。
检测和定位SPI故障:逻辑分析仪可以通过观察和解码SPI的信号和数据,检测和定位SPI通信中可能出现的故障,如时钟速率过高、时钟相位不匹配、数据帧格式错误、通信协议不一致等。
逻辑分析仪上位机界面
七、SPI总线pcb layout注意事项
八、软件模拟SPI
/****************************************************************************************
* @名称 void oled_write_byte(u8 dat,u8 cmd)
* @功能 向oled写入一个字节
* @输入参数一 dat - 要写入的数据/命令
* @输入参数二 cmd - 数据/命令标志 0,表示命令;1,表示数据
* @返回 none
****************************************************************************************/
void oled_write_byte(u8 dat,u8 cmd)
{
u8 i;
if(cmd) OLED_DC_H;
else OLED_DC_L;
OLED_CS_L;
for(i = 0;i < 8;i++)
{
OLED_CLK_L;
if(dat&0x80) OLED_DIN_H;
else OLED_DIN_L;
OLED_CLK_H;
dat<<=1;
}
OLED_CS_H;
OLED_DC_H;
}