参考资料

笔记之STM32F0芯片S0PI_DMA的使用(HAL库)_stm32 spi dma-CSDN博客

一、SPI简介

SPI英文全称Serial Peripheral Interface,即串行外围设备接口,是一种高速、全双工同步串行通信总线。

二、 信号线

  • SCK(Serial Clock):串行时钟线,由主设备产生,用于同步数据传输。
  • MOSI(Master Output Slave Input):主机输出从机输入线,主设备通过这条线发送数据给从设备。
  • MISO(Master Input Slave Output):主机输入从机输出线,主设备通过这条线接收从设备发送的数据。
  • CS(Slave Select)(NSS或SS):从机选择线(每个从机一根选择线),用于选择与主设备进行通信的从设备。通常情况下,SS线为低电平有效,即当SS线为低电平时,选中对应的从设备进行通信

image-20250511102329794

三、 开始与结束

当SS从高电平拉低到低电平,这个算是起始的一个时序。而SS从低电平拉高到高电平,就算是结束的时序。

img

1.4 发送和接收字节

发送接收字节看似是两个时序,但是在SPI中却是同一个时序,因为SPI的机制是==我们发送一个字节,并且接收一个字节==(哪怕我们并不需要接收数据)。反过来看也可以是我们接收一个字节,并且发送一个字节(哪怕这个字节是无用的数据)。

image-20250511102607470

  • 来一个时钟上升沿信号,主机和从机分别把自己高位的值左移出来(一般高位先行)
  • 来一个时钟下降沿信号,主机和从机分别读入数据,存储到移位寄存器的低位

img

交换bit

img

在SCK上升沿的时候,移出MOSI的数据,在SCK下降沿的时候读取MISO的数据。

需要在SCK上升沿之前把需要发送的数据位放置在MOSI线上

SCK下降沿的时候马上读取MISO线上的数据位

(实际上下降沿和读取应该是同时的,但是我们软件模拟没法同时,但是效果是一样的)

1.6 不同模式下的通信

image-20250305141745720

image-20250305141814533

image-20250305141718015

image-20250305141639698

image-20250305141859718

image-20250305142011451

image-20250305142031698

时钟的极性和相位

1.时钟的极性(CPOL)

什么时候读数据(数据采集)和设置的时钟和相位有关

通信的整个过程分为空闲时刻和通信时刻

模式1:SCK上升沿的时候,移出MOSI的数据,在SCK下降沿的时候读取MISO数据

  • 空闲状态SCLK是低电平,CPOL=0

image-20250511103646951

  • 空闲状态SCLK是高电平,CPOL=1

image-20250511103726353

2.时钟的相位(CPHA)

直接决定SPI总线从那个跳变沿开始采样数据

  • CPHA=0:表示从第一个跳变沿开始采样

image-20250511104059236

  • CPHA=1:表示从第二个跳变沿开始采样

image-20250511104044786

3.SPI的4种模式

时钟的两种极性和2种相位的不同组合,得到了SPI的4种工作模式

image-20250511104312629

3.1 模式0和模式2

image-20250511104947143

3.2 模式1和模式3

image-20250511104902672

三、硬件SPI

image-20250512125536962

3.1 初始化

3.1.1 SPI_HandleTypeDef

SPI_InitTypeDef

  • Mode:指定 SPI 工作模式

    • SPI_MODE_SLAVE:从模式
    • SPI_MODE_MASTER:主模式
  • Direction:指定 SPI 双向模式状态

    • SPI_DIRECTION_2LINES:同时支持数据的发送和接收
    • SPI_DIRECTION_2LINES_RXONLY:SPI只接收数据
    • SPI_DIRECTION_1LINE:SPI只使用一条数据线进行双向数据传输
  • DataSize:指定 SPI 数据大小

    • SPI_DATASIZE_8BIT:8位
    • SPI_DATASIZE_16BIT:16位
  • CLKPolarity:指定时钟极性(空闲状态时时钟的电平)

    • SPI_POLARITY_LOW:空闲时低电平
    • SPI_POLARITY_HIGH:空闲时高电平
  • CLKPhase:指定时钟相位(数据采样的边沿)

    • SPI_PHASE_1EDGE:第一个时钟边沿采样
    • SPI_PHASE_2EDGE:第二个时钟边沿采样
  • NSS:指定片选信号(NSS)的管理方式

    • SPI_NSS_SOFT:软件管理模式
    • SPI_NSS_HARD_INPUT:硬件输入模式
    • SPI_NSS_HARD_OUTPUT:硬件输出模式
  • BaudRatePrescaler:指定波特率预分频值

    • SPI_BAUDRATEPRESCALER_2
    • SPI_BAUDRATEPRESCALER_4
    • SPI_BAUDRATEPRESCALER_8
    • SPI_BAUDRATEPRESCALER_16
    • SPI_BAUDRATEPRESCALER_32
    • SPI_BAUDRATEPRESCALER_64
    • SPI_BAUDRATEPRESCALER_128
    • SPI_BAUDRATEPRESCALER_256
  • FirstBit:指定数据传输时的字节顺序

    • SPI_FIRSTBIT_MSB:最先发送高位
    • SPI_FIRSTBIT_LSB:最先发送低位
  • TIMode:用于控制SPI的三态模式(是否能进入高阻态)

    • SPI_TIMODE_DISABLE:禁用三态模式
    • SPI_TIMODE_ENABLE:启用三态模式
  • CRCCalculation:控制是否启用CRC

    • SPI_CRCCALCULATION_DISABLE:禁用CRC计算
    • SPI_CRCCALCULATION_ENABLE:启用CRC计算
  • CRCPolynomial:an odd number between Min_Data = 1 and Max_Data = 65535

问题

1. 硬件SPI的MISO引脚配置成浮空输入还是复用推挽输出?

​ 当一个GPIO端口配置为GPIO_Mode_AF_PP时,片上外设的复用功能输出信号会连接到输出控制电路,然后在端口上产生输出信号。但是在芯片内部,MISO是SPI模块的输入引脚,而不是输出引脚,也就是说“复用功能输出信号”根本不存在,所以”输出控制电路”就不能对外部产生输出信号,然而即使在复用推挽输出模式下,复用功能输入信号却与外部引脚之间相互连接,既MISO得到了外部信号的电平,实现了输入的功能。