目录
一、简介
1.概念
SPI(Serial Peripheral Interface)总线协 议是一种全双工的同步串行总线通信协议,用于在 集成电路之间进行数据传输。SPI 总线通常由 一个主设备和多个从设备组成,,每个从设备都 有一个单独的片选信号,最高可以工作 在上百 MHz,一般 SPI 需要 4 根线,但是也可以使用三根线。
2.特点
同步通信:SPI是同步通信协议,数据传输由主设备(Master)提供的时钟信号(SCLK)控制,保证数据同步传输。
全双工通信:SPI支持全双工通信,主设备和从设备可以同时发送和接收数据。
多从设备支持:一个主设备可以连接多个从设备,通过片选信号(Chip Select, CS)来选择具体的从设备进行通信。
简单硬件连接:相比其他协议,如I²C,SPI的硬件连接相对简单,不需要复杂的握手信号。
3.优缺点
优点:
①高速传输:由于没有复杂的握手信号,SPI可以实现高速数据传输,几乎比IIC快两倍。
全双工通信:主从设备可以同时发送和接收数据,提高通信效率。
②灵活性高:可以轻松连接多个从设备,支持多种通信模式,数据传输更加灵活,可以传输任意大小的字。
③硬件结构简单:从站不需要唯一地址(与I2C不同)。从机使用主机时钟,不需要精密时钟振荡器/晶振(与UART不同)。不需要收发器(与CAN不同)。
缺点:
①引脚占用较多:每个从设备需要一个片选信号,如果有多个从设备,需要占用较多的GPIO引脚。
②无流控制和确认机制:SPI协议没有内置的流控制和数据确认机制,需要在应用层实现。
③传输距离短:与RS-232和CAN总线相比,只能支持非常短的距离。
④只允许一个主设备。
4.应用场景
SPI协议广泛应用于需要高速数据传输和可靠性的场景,如:
①显示器驱动
②存储器(如SD卡、Flash存储器)
③传感器数据采集
④音频编解码器
⑤电机驱动
二、通信原理
SPI 一般应用由四个引脚组成(一主一从):
SCLK(Serial Clock):串行时钟,由主机发出。
MOSI(Master Output Slave Input):主机输出从机输入信号,由主机发出。
MISO(Master Input Slave Output):主机输入从机输出信号,由从机发出。
NSS(Slave Selected):选择信号,由主机发出,一般是低电位有效。
不同的芯片厂家命名不同除此之外还有:
SCLK/SCK
MOSI/SOMI/DIN/DI/SDI/SI/SIN
MISO/SIMO/DOUT/SDO/SO/SOUT
NSS/CE/CS/SSEL/PCS
SPI 的主从连接图如图1所示
图1
其通信过程可分为以下几步:
起始条件(Chip Select):主设备通过片 选信号(Chip Select)选择从设备,并发送 低电平信号,表示开始数据传输。
传输方式:主设备和从设备之间使用 MOSI 和 MISO 两根线传输数据。主设备通过 MOSI 发送数据,从设备通过 MISO 接收数据,采集时机要根据模式选择来判定。
时钟信号:主设备通过 SCLK 时钟信号控制 数据传输速率,同时从设备也按照同样的时钟 频率来接收数据。
数据长度:SPI 总线没有固定数据长度的限 制,可以发送任意长度的数据块。
结束条件(Chip Deselect):主设备通过 片选信号(Chip Deselect)取消对从设备的 选择,结束数据传输。
如下图2所示发送0x53为例:主机拉低NSS片选信号,启动通信,并且产生时钟信号,上升沿触发边沿信号,当主机在MOSI信号线一位一位开始发送0x53时(因为0101=0x5,0011=0x3所以根据低位在前先发送应为11001010),在MISO线路一位一位接收数据0X46(此处我也不懂为什么是01100010,有大佬解释一下就好了)
图2
三、通信特性
SPI 是一种非常灵活的通信协议,我们可以配置它的时钟极性、时钟相位等。
1.时钟频率
SPI的时钟频率是指用于同步数据传输的时钟信号的频率。它决定了数据传输的速度。时钟频率的配置需要考虑主设备和从设备的硬件限制以及通信距离等因素。
配置SPI时钟频率主要有以下步骤:
①确定主设备的最大时钟频率:查阅主设备的技术手册,找出SPI模块支持的最大时钟频率。
②确定从设备的最大时钟频率:查阅从设备的技术手册,找出从设备支持的最大时钟频率。
③选择合适的时钟频率:在主设备和从设备的最大支持频率之间选择一个合适的频率。这个频率不应超过任何一个设备的最大支持频率。
示例:以STM32微控制器为例,SPI时钟频率由APB时钟和波特率预分频器(Baud Rate Prescaler)决定。以下是一个配置示例
①假设APB2时钟频率为84MHz。
②波特率预分频器可以设置为2、4、8、16、32、64、128或256。假设我们希望配置SPI时钟频率为5.25MHz:
③SPI时钟频率 = APB时钟频率 / 波特率预分频器
5.25MHz = 84MHz / 16
④因此,波特率预分频器应设置为16。
2.时钟极性(CPOL)
时钟极性用于设置时钟在空闲时的电平状态,
CPOL 为“1”则时钟空闲时为高电平。
CPOL 为“0”,则时钟空闲时为低电平。
如图 3 所示。这就直接导致了第一个信号沿是下降沿还是上升沿,通常 CPOL 和时钟相位(CPHA)配合使用。
图3
3.时钟相位(CPHA)
时钟相位用于设置在第几个时钟沿发生对数据线就行采样,
当 CPHA=1 是表示第二个 时钟沿对数据线进行采样。
当 CPHA=0 时,在第一个时钟沿对数据进行采样。
如图 4 所 示:
图4
4.四种模式
上面我们知道了什么是相位和极性,为此我们可以根据他们之间的不同组合来将SPI分为四种模式主机与从机需要工作在相同的模式下才可 以正常通讯。实际中采用的较多的“模式 0”和“模式 3”。
SPI模式 | CPOL | CPHA | 空闲时CLK时钟 | 采样时刻 |
0 | 0 | 0 | 低电平 | 奇数边沿 |
1 | 0 | 1 | 低电平 | 偶数边沿 |
2 | 1 | 0 | 高电平 | 奇数边沿 |
3 | 1 | 1 | 高电平 | 偶数边沿 |
四种模式的具体解释:
Mode0:CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在上升沿(准备数据),(发送数据)数据发送是在下降沿。
Mode1:CPOL=0,CPHA=1:此时空闲态时,SCLK处于低电平,数据发送是在第1个边沿,也就是SCLK由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。
Mode2:CPOL=1,CPHA=0:此时空闲态时,SCLK处于高电平,数据采集是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。
Mode3:CPOL=1,CPHA=1:此时空闲态时,SCLK处于高电平,数据发送是在第1个边沿,也就是SCLK由高电平到低电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。
具体采样数据如图5所示:
5.多主机模式
前面说到SPI总线必须有一个主机,可以有多个从机,那么具体连接到SPI总线的方法有以下两种多片选和菊花链。
(1)多片选
①通常,每个从机都需要一条单独的CS线。
②如果要和特定的从机进行通讯,可以将相应的CS信号线拉低,并保持其他CS信号线的状态为高电平;如果同时将两个CS信号线拉低,则可能会出现乱码,因为从机可能都试图在同一条MISO
线上传输数据,最终导致接收数据乱码。
(2)菊花链
菊花链(Daisy Chain)是一种常见的连接拓扑结构,用于串行连接多个设备,使得每个设备与前一个设备和下一个设备相连。菊花链连接在许多应用中都有广泛的使用,例如串行通信、计算机总线、音频设备和LED灯串等。
特点:
- 串行连接:每个设备通过输入和输出端口与链上的下一个和上一个设备连接。
- 单一通道:数据通过单一通道传输,依次通过每个设备。
- 简化布线:相比星形拓扑结构,菊花链减少了布线的复杂度,因为不需要从每个设备到中心节点的独立连接。
- 扩展方便:增加或移除设备相对简单,只需连接或断开相应的设备。
优点:
- 简化布线:减少了物理连线的复杂性。
- 扩展方便:可以轻松增加或移除设备。
缺点:
- 延迟累积:每个设备增加了数据传输的延迟。
- 可靠性问题:如果链中的一个设备出现故障,可能影响整个链的通信。
四、编程实现
以国产芯片智芯半导体的Z20K118芯片为例,其例程为了实现使用SPI主机传输和接收数据其具体工程文件放在资源里:
硬件框图如图所示
软件代码如下
1.SPI结构体配置
const SPI_Config_t tSpiMasterCfgStruct =
{
SPI_MODE_MASTER, /* 模式选择 */
32, /* 数据帧的大小 */
SPI_CLK_PHASE_FIRST, /* 时钟相位 */
SPI_CLK_INACTIVE_LOW, /* 始终极性 */
SPI_TMOD_TR, /* 传输模式 */
350, /* 时钟分频 */
2, /* 发送FIFO阈值电平 */
2 /* 接收FIFO阈值 */
};
2.系统初始化
/* 选择osc时钟作为spi0的函数时钟 */
CLK_ModuleSrc(CLK_SPI0, CLK_SRC_OSC40M);
/* 设置spi0函数时钟的分频比 */
CLK_SetClkDivider(CLK_SPI0, CLK_DIV_1);
/* 启用spi0的时钟 */
SYSCTRL_EnableModule(SYSCTRL_SPI0);
/* 使能GPIO口引脚 时钟*/
CLK_ModuleSrc(CLK_PORTB, CLK_SRC_OSC40M);
CLK_ModuleSrc(CLK_PORTE, CLK_SRC_OSC40M);
SYSCTRL_EnableModule(SYSCTRL_PORTB);
SYSCTRL_EnableModule(SYSCTRL_PORTE);
/* 配置各IO口复用*/
PORT_PinmuxConfig(PORT_B, GPIO_2, PTB2_SPI0_SCK);
PORT_PinmuxConfig(PORT_E, GPIO_1, PTE1_SPI0_SIN);
PORT_PinmuxConfig(PORT_B, GPIO_4, PTB4_SPI0_SOUT);
PORT_PinmuxConfig(PORT_B, GPIO_5, PTB5_SPI0_PCS0);
3.使能SPI并下拉PCS选择从节点
/* 初始化结构体配置 */
SPI_Init(SPI0_ID, &tSpiMasterCfgStruct);
/* 下拉PCS0选择从机 */
SPI_SelectSlave(SPI0_ID, SPI_SS_PCS0);
/* 使能SPI */
SPI_Enable(SPI0_ID);
4.发送数据
for(i=0; i<TRANS_LEN; i++)
{
localCnt = 0 ;
/* 发送数据 */
while (RESET == SPI_GetStatus(SPI0_ID, SPI_STATUS_TFNF));
SPI_SendData(SPI0_ID, i);
/* 等待状态寄存器的RFNE标志位被置位 */
while(RESET == SPI_GetStatus(SPI0_ID, SPI_STATUS_RFNE))
{
if(localCnt > 0xFFFF)
{
return RESET;
}
localCnt++;
}
/* 接收数据 */
data[i] = SPI_ReceiveData(SPI0_ID);
}
五、三种SPI比较
三种SPI通常是指标准SPI,Dual SPI,和Queued SPI 三种,标准SPI已经介绍过了不做过多介绍主要介绍后面两种SPI,以及三者的区别。
1.Dual SPI
Dual SPI是一种增强的SPI通信模式,主要用于提高数据传输速率。它增加了数据传输通道,使得每个时钟周期可以传输更多的数据。
Dual SPI只是针对SPI Flash而言,不是针对所有SPI外设。对于SPI Flash,全双工并不常用,因此扩展了mosi和miso的用法,让它们工作在半双工,用以加倍数据传输。也就是对于Dual SPI Flash,可以发送一个命令字节进入dual mode,这样MOSI变成SIO0(serial io 0),MISO变成SIO1(serial io 1),这样一个时钟周期内就能传输2个bit数据,加倍了数据传输。
特点
- 双通道数据传输:使用两条数据线同时传输数据,通常是MOSI和MISO共同传输数据。
- 更高的传输速率:在相同的时钟频率下,Dual SPI可以比标准SPI传输更多的数据。
- 硬件要求高:需要支持Dual SPI模式的主设备和从设备。
2.Queued SPI
Queued SPI是一种高级的SPI通信模式,通常用于需要高效管理多个SPI传输事务的场景。它在标准SPI的基础上增加了硬件队列(Queue)功能,可以预先配置多个SPI传输事务,主设备可以自动依次执行这些事务。
在Dual SPI的基础上增加了两根I/O线(SIO2,SIO3),目的是一个时钟内传输4个bit,而QSPI就是Queued SPI的简写;
特点
- 硬件队列:可以预先配置多个传输事务,并由硬件自动执行。
- 高效管理:减少CPU干预,提高数据传输效率。
- 适用于复杂场景:特别适用于需要频繁且复杂SPI传输的应用,如存储器访问。
Dual SPI和Queued SPI是针对flash的接口,根据flash工作的特性,将全双工改为半双工,提高通信的速率。
3.三者的区别
(1)标准SPI是通用的,Dual SPI和QSPI只适用于flash;
(2)标准SPI:标准4线连接,全双工,同时收和发;
(3)Dual SPI:标准4线连接,半双工,2根数据线,并线发和收,双方向切换;
(4)QSPI:标准4线连接,半双工,4根数据线,并线发和收,双方向切换。
特性 | 标准SPI | Dual SPI | Queued SPI |
数据通道 | 单通道 | 双通道 | 单通道或者双通道 |
数据速率 | 常规 | 更高 | 高效管理 |
硬件复杂度 | 简单 | 需要支持Dual SPI的设备 | 需要支持QSPI的设备 |
传输速率 | 普通 | 更高 | 最高 |
应用场景 | 通用SPI通信 | 高速数据传输 | 复杂、频繁SPI传输 |
代码配置上的区别以stm32f4的HAl库为例:
①标准SPI代码配置
#include "stm32f4xx_hal.h"
SPI_HandleTypeDef hspi1;
void SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
HAL_SPI_Init(&hspi1);
}
②Dual SPI代码配置
配置Dual SPI时,需要额外设置数据线的双通道模式:
#include "stm32f4xx_hal.h"
SPI_HandleTypeDef hspi1;
void Dual_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY; // 双通道接收
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
HAL_SPI_Init(&hspi1);
// 额外的Dual SPI模式配置,根据具体芯片文档进行设置
}
③Queued SPI代码配置
QSPI配置较为复杂,需要配置队列管理和多通道模式
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_qspi.h"
QSPI_HandleTypeDef hqspi;
void QSPI_Init(void)
{
hqspi.Instance = QUADSPI;
hqspi.Init.ClockPrescaler = 1;
hqspi.Init.FifoThreshold = 4;
hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
hqspi.Init.FlashSize = 1;
hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
hqspi.Init.FlashID = QSPI_FLASH_ID_1;
hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
HAL_QSPI_Init(&hqspi);
// 额外的队列和多通道配置,根据具体芯片文档进行设置
}
图片以及部分内容引自:SPI协议详解(图文并茂+超详细)-CSDN博客
标签:通信协议,SPI,Init,-----,Dual,hspi1,设备,时钟 From: https://blog.csdn.net/2201_75342985/article/details/139789971