文章目录
SPI简介
SPI的信号线
(下面讲述SPI由那几根线组成?)
SPI (Serial Peripheral Interface,串行外围接口) 是一种同步串行通信协议,常用于微控制器与外围设备之间进行数据传输。它使用四条信号线:
- SCK (serial clock):时钟信号由主设备控制,用来同步数据传输。
- MOSI (Master Out Slave In):由主设备发送数据到从设备。
- MISO (Master In Slave Out):由从设备发送数据到主设备。
- SS (Slave Select):由主设备控制,用来选择哪个从设备进行通信。
SPI工作原理
(下面讲述SPI这几根线大致是怎么用的?)
SPI 通信是一种主从式通信,主设备负责发送时钟信号和数据,并控制从设备的选择。从设备则接收时钟信号和数据,并发送数据到主设备。
- 选择从设备: 主设备拉低 SS 信号线,选择特定的从设备进行通信。
- 发送数据: 主设备将数据发送到 MOSI 线,同时提供时钟信号。
- 接收数据: 从设备接收数据并将其存储。
- 发送数据: 从设备将数据发送到 MISO 线,同时接收时钟信号。
- 解选从设备: 主设备拉高 SS 信号线,解选从设备。
下图是一台主机一台从机的硬件接线情况
下图是一台主机三台从机的接线情况,通过IO1/2/3分别选中对应从设备,某个时刻只能选中的从设备可以通信。
SPI的工作模式
(SPI 的不同模式)
SPI使用 CPOL(Clock Polarity 时钟极性) 和 CPHA(Clock Phase 时钟相位) 两个属性来控制工作模式。
- CPOL 用于控制没有传输数据时时钟的空闲状态电平,高或低;
- CPHA 用来控制数据采样的时钟边缘,使用第一个边缘还是第二个边缘。
所以SPI有如下4种工作模式:
- 模式 0: CPOL = 0, CPHA = 0
- 模式 1: CPOL = 0, CPHA = 1
- 模式 2: CPOL = 1, CPHA = 0
- 模式 3: CPOL = 1, CPHA = 1
疑问:我们知道了主机在各种模式中的采样边沿,那主机在各种模式中什么时候开始输出数据呢?
下图是示波器的电平采样图。可以看到在模式0时,在SCLK的上升沿进行采样,在SCLK的下降沿进行输出。
总结:主机在采样边沿的另一个边沿进行数据输出。
SPI的数据帧格式
SPI的每个数据帧可以是 8位 或是 16位。
与其他协议的对比
SPI的几种标准
SPI有 Standard SPI,Dual SPI
Standard SPI
Dual SPI
数据传输速率:Dual SPI使用两条数据线同时进行数据的发送和接收,因此其数据传输速率是标准SPI的两倍
Quad SPI (QSPI):
CLK (Clock): 时钟信号,用于同步数据传输。
CS (Chip Select): 片选信号,用于选择具体的QSPI器件。
IO0-IO3 (Data0-Data3): 四条数据线,用于数据传输。其中IO0和IO1通常用于数据,IO2和IO3通常用于地址和指令,但具体实现可能因器件而异。
GD32的SPI
GD32F30x系列的SPI特性
特性部分可以根据芯片的类型去GD32官方资料下载中心查看对应的官方手册。
笔者使用的是GD32F30x系列的芯片,用户手册链接:GD32F30x_User_Manual_Rev3.0_CN.pdf
下面是SPI的主要特性。
注意:
- SPI是挂在APB总线下的。
- 发送和接收使用的都是同一个移位寄存器
SPI配置的大致步骤
- 配置相关引脚的复用功能,使能SPIx时钟
- 初始化SPIx设置SPIx工作模式
- 使能SPIx
- SPI传输数据
- 查看SPI传输状态
SPI的配置
确定引脚的GPIO口
板子上是使用了SPI0接口,通过改SPI0去读写FLASH,FLASH使用的是 GD25Q64ESIG,其手册地址:嘉立创GD25Q64ESIG
时钟的配置
开启SPI0时钟,功能复用时钟,GPIO口的时钟
SPI引脚的配置
SPI引脚的配置如下图所示
SPI0控制器的配置
主要配置如下内容
- 传输模式
- 设备模式
- 数据位
- 时钟的极性和相位
- 时钟分配系数
- 高位先传输还是低位先传输
SPI读写
阅读用户手册内容如下,得到如下关键内容。
阅读后,我们可知道,发送数据,在TBE为1时可以继续发送。
在全双工主机模式中,接收数据需要发送缓冲区非空时,硬件只接收下一个数据帧。
由于SPI是全双工的,读写是同时进行的。
SPI标志状态
有3个主要的标志状态
- 发送缓冲器空闲标志(TXE)
Transmit Buffer Empty,发送缓冲器空标志,当SPI准备好接受新的待发送数据时置位 - 接收缓冲器非空(RXNE)
Receive Buffer Not Empty,接收缓冲器非空标志,当SPI接收到有效数据并存放在接收缓冲器中时置位。 - 忙标志(Busy)
Busy,忙标志,SPI正在进行数据传输时置位。 - 其他
可能还有其他标志如OVRE(Overrun Error)、CRCERR(CRC错误)等,用于指示SPI在数据传输过程中可能出现的各种异常状况。
GD32 的SPI操作代码
初始化代码
spi_disable(DSP_SPI);
spi_parameter_struct spi_init_struct;
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_SPI0);
//GD_SPI0 --- SCK PB3,MISO PB4,MOSI PB5 ---- 主控板DSP之间SPI通讯
gpio_af_set(GPIOB, GPIO_AF_0, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
spi_i2s_deinit(DSP_SPI);
spi_struct_para_init(&spi_init_struct);
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; //全双工模式
spi_init_struct.device_mode = SPI_MASTER; //SPI主机
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; //8bit模式
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE; //空闲极性为低、第二个边沿采样
spi_init_struct.nss = SPI_NSS_SOFT; //nss软件控制
spi_init_struct.prescale = SPI_PSC_256; //64分频(468K) 128分频(234K)256分频(128K)
spi_init_struct.endian = SPI_ENDIAN_MSB; //高位优先
spi_init(DSP_SPI, &spi_init_struct);
spi_enable(DSP_SPI);
发送数据
spi_i2s_data_transmit(TempSPI,*(TxData + i)); //写入数据
读取数据
*(RxData + i) = spi_i2s_data_receive(TempSPI) & 0xff; //读取数据
SPI操作FLASH代码
GD25Q64E的使用说明
标准SPI模式下的操作方法
文档中显示,可以支持模式0和模式3。可以翻阅 SPI的工作模式 小节,回顾模式0和模式3。
命令
SPI问题
主机与从机的SPI问题:时序问题,怎么重置时序????