框架组成

image.png

IO

  • STM32 芯片有多个 SPI 外设,它们的 SPI 通讯信号引出到不同的 GPIO 引脚上,使用时必须配置到这些指定的引脚。

    时钟控制逻辑

  • 作用:提供时钟,将F进行分频
  • SCK 线的时钟信号,由波特率发生器根据“控制寄存器 CR1”中的 BR[0:2]位控制
  • 该位是对 f时钟的分频因子,对 f的分频结果就是 SCK 引脚的输出时钟频率。

    数据控制逻辑

  • SPI 的 MOSI 及 MISO 都连接到数据移位寄存器

  • 数据移位寄存器的数据来源及目标接收、发送缓冲区以及 MISO、MOSI 线。
  • 当向外发送数据的时候
    • 数据移位寄存器以“发送缓冲区”为数据源,把数据一位一位地通过数据线发送出去;
  • 当从外部接收数据的时候,

    • 数据移位寄存器把数据线采样到的数据一位一位地存储到“接收缓冲区”中。
    • 通过写 SPI的“数据寄存器 DR”把数据填充到发送 F 缓冲区中,通讯读“数据寄存器 DR”取接收缓冲区中的内容。
    • 其中数据帧长度可以通过“控制寄存器 CR1”的“DFF 位”配置 成 8 位及 16 位模式;
    • 配置“LSBFIRST 位”可选择 MSB 先行还是 LSB 先行。

      整体控制逻辑

  • 控制参数 :SPI模式、波特率、LSB先行、主从模式、单双向模式、产生 SPI 中断信号、DMA 请求及控制

  • 读取状态:状态寄存器(SR)

通讯过程

image.png

  1. 控制 NSS 信号线,产生起始信号(图中没有画出);
  2. 把要发送的数据写入到“数据寄存器 DR”中,该数据会被存储到发送缓冲区;
  3. 通讯开始,SCK 时钟开始运行。
  4. MOSI 把发送缓冲区中的数据一位一位地传输出去;
  5. MISO 则把数据一位一位地存储进接收缓冲区中;
  6. 当发送完一帧数据的时候,“状态寄存器 SR”中的“TXE 标志位”会被置 1,表示传输完一帧,发送缓冲区已空;类似地,当接收完一帧数据的时候,“RXNE 标志位”会被置 1,表示传输完一帧,接收缓冲区非空;
  7. 等待到“TXE 标志位”为 1 时,若还要继续发送数据,则再次往“数据寄存器 DR”写入数据即可;
  8. 等待到“RXNE 标志位”为 1 时,通过读取“数据寄存器 DR”可以获取接收缓冲区中的内容

标准库结构体

  1. typedef struct
  2. {
  3. uint16_t SPI_Direction; /*设置 SPI 的单双向模式 \*/
  4. uint16_t SPI_Mode; /*设置 SPI 的主/从机端模式 \*/
  5. uint16_t SPI_DataSize; /*设置 SPI 的数据帧长度,可选 8/16 位 \*/
  6. uint16_t SPI_CPOL; /*设置时钟极性 CPOL,可选高/低电平\*/
  7. uint16_t SPI_CPHA; /*设置时钟相位,可选奇/偶数边沿采样 \*/
  8. uint16_t SPI_NSS; /*设置 NSS 引脚由 SPI 硬件控制还是软件控制\*/
  9. uint16_t SPI_BaudRatePrescaler; /\*设置时钟分频因子,fpclk/分频数=fSCK \*/
  10. uint16_t SPI_FirstBit; /\*设置 MSB/LSB 先行 \*/
  11. uint16_t SPI_CRCPolynomial; /\*设置 CRC 校验的表达式 \*/
  12. } SPI_InitTypeDef;
  • (1) SPI_Direction 本成员设置 SPI 的通讯方向
    • 双线全双工(SPI_Direction_2Lines_FullDuplex)
    • 双线只接收(SPI_Direction_2Lines_RxOnly)
    • 单线只接收(SPI_Direction_1Line_Rx)
    • 单线只发送模式(SPI_Direction_1Line_Tx)。
  • (2) SPI_Mode 设置SPI的工作模式
    • 主机模式(SPI_Mode_Master)
    • 从机模式(SPI_Mode_Slave ),
    • 这两个模式的最大区别为 SPI 的 SCK 信号线的时序,SCK 的时序是由通讯中的主机产生的
    • 若被配置为从机模式,STM32 的 SPI 外设将接受外来的 SCK 信号。
  • (3) SPI_DataSize 选择 SPI 通讯的数据帧大小
    • 8 位(SPI_DataSize_8b)
    • 16 位 (SPI_DataSize_16b)。
  • (4) SPI_CPOL 和 SPI_CPHA 配置时钟极性和时钟相位
    • 这两个成员配置 SPI 的时钟极性 CPOL 和时钟相位 CPHA,这两个配置影响到 SPI 的 通讯模式,关于 CPOL 和 CPHA 的说明参考前面“通讯模式”小节。
    • 时钟极性 CPOL 成员,
      • 高电平(SPI_CPOL_High)
      • 低电平(SPI_CPOL_Low )。
    • 时钟相位 CPHA 则可以设置为
      • SPI_CPHA_1Edge(在 SCK 的奇数边沿采集数据)
      • SPI_CPHA_2Edge (在 SCK 的偶数边沿采集数据) 。
  • (5) SPI_NSS 本成员配置 NSS 引脚的使用模式
    • 硬件模式(SPI_NSS_Hard )
      • 在硬件模式中的 SPI 片选信号由 SPI 硬件自动产生
    • 软件模式(SPI_NSS_Soft )
      • 我们亲自把相应的 GPIO 端口拉高或置低产生非片选和片选信号。
      • 实际中软件模式应用比较多。
  • (6) SPI_BaudRatePrescaler 波特率分频因子
    • 本成员设置波特率分频因子,分频后的时钟即为 SPI 的 SCK 信号线的时钟频率。
    • 这个成员参数可设置为 f的 2、4、6、8、16、32、64、128、256 分频。
  • (7) SPI_FirstBit 数据位先行选择
    • 所有串行的通讯协议都会有 MSB 先行(高位数据在前)还是 LSB 先行(低位数据在前)的问题
    • 而 STM32 的 SPI 模块可以通过这个结构体成员,对这个特性编程控制。
  • (8) SPI_CRCPolynomial SPI 的 CRC 校验中的多项式