3. SPI 硬件架构:MCU 内部 SPI 外设框图、移位寄存器、时钟分频器、FIFO 缓冲区
理解 SPI 硬件架构是驱动开发的基础。MCU 内部的 SPI 外设并非简单的引脚直连,而是由多个功能模块协同工作的复杂状态机。本节将深入剖析 SPI 外设的内部框图、核心组件(移位寄存器、时钟分频器、FIFO 缓冲区)的工作原理及其对驱动性能的影响。
3.1 SPI 外设内部框图与数据流
下图展示了一个典型的 MCU SPI 外设内部架构。数据从内核总线出发,经过 FIFO 缓冲、移位寄存器,最终通过 I/O 控制逻辑与外部引脚交互。时钟分频器则独立为整个模块提供同步时钟。
架构要点:SPI 外设内部存在两条独立的数据路径——发送路径(CPU → FIFO → 移位寄存器 → MOSI)和接收路径(MISO → 移位寄存器 → FIFO → CPU)。时钟分频器为两条路径提供同步时钟,但数据流方向相反。
3.2 移位寄存器:串并转换的核心
移位寄存器是 SPI 通信的物理执行单元。它负责将并行的数据总线数据转换为串行的位流,或将接收到的串行位流转换为并行数据供 CPU 读取。
3.2.1 工作原理
- 发送过程:CPU 将数据写入数据寄存器(DR),硬件自动将数据加载到发送移位寄存器。在每个 SCK 时钟边沿,移位寄存器将最高位(MSB)或最低位(LSB)移出到 MOSI 引脚。
- 接收过程:在每个 SCK 时钟边沿,MISO 引脚上的数据被采样并移入接收移位寄存器。当接收完一个字节/字后,数据被转移到数据寄存器或 FIFO 中。
- 全双工机制:发送和接收移位寄存器在同一个 SCK 时钟驱动下同时工作,实现全双工通信。
3.2.2 数据帧格式配置
| 配置项 | 选项 | 说明 |
|---|---|---|
| 数据帧长度 | 8 位 / 16 位 / 32 位 | 决定每次传输的数据宽度,Flash 通常使用 8 位 |
| 位序 | MSB 优先 / LSB 优先 | Flash 器件通常要求 MSB 优先 |
| 时钟极性 (CPOL) | 0 / 1 | SCK 空闲电平:0=低电平,1=高电平 |
| 时钟相位 (CPHA) | 0 / 1 | 数据采样边沿:0=第一个边沿,1=第二个边沿 |
驱动开发提示:配置移位寄存器时,必须与目标 Flash 器件的数据手册严格匹配。例如,W25Q64 系列 Flash 要求 CPOL=0、CPHA=0(模式 0),数据帧为 8 位,MSB 优先。错误的配置将导致通信完全失败。
3.3 时钟分频器:速率控制的基石
时钟分频器从 MCU 系统时钟(如 AHB/APB 时钟)分频产生 SPI 通信时钟 SCK。分频系数决定了 SPI 的通信速率,直接影响 Flash 读写性能。
3.3.1 分频原理
SPI 时钟频率计算公式:
SCK_Frequency = PCLK / (2 × (BR[2:0] + 1)) // STM32 标准 SPI
SCK_Frequency = PCLK / (2 × BR) // 某些 MCU 直接分频
其中 BR 为波特率分频寄存器值,常见分频系数如下:
| BR[2:0] 值 | 分频系数 | PCLK=72MHz 时 SCK | PCLK=100MHz 时 SCK |
|---|---|---|---|
| 000 | 2 | 36.0 MHz | 50.0 MHz |
| 001 | 4 | 18.0 MHz | 25.0 MHz |
| 010 | 8 | 9.0 MHz | 12.5 MHz |
| 011 | 16 | 4.5 MHz | 6.25 MHz |
| 100 | 32 | 2.25 MHz | 3.125 MHz |
| 101 | 64 | 1.125 MHz | 1.5625 MHz |
| 110 | 128 | 562.5 kHz | 781.25 kHz |
| 111 | 256 | 281.25 kHz | 390.625 kHz |
3.3.2 速率选择策略
- Flash 规格限制:查阅 Flash 数据手册的最大 SCK 频率(如 W25Q64 最大 104 MHz)。
- PCB 走线长度:长走线会引入信号反射,需要降低速率以保证信号完整性。
- 系统负载:高速 SPI 会占用更多 CPU 中断时间(非 DMA 模式),需平衡系统整体性能。
常见错误:初学者常将 SPI 时钟配置为 MCU 支持的最大值,而忽略 Flash 器件的速率上限。过高的 SCK 频率会导致数据采样错误,表现为读出的数据为 0xFF 或随机值。建议从较低分频(如 8 分频)开始调试,确认通信正常后再逐步提高速率。
3.4 FIFO 缓冲区:吞吐量的倍增器
FIFO(First In First Out)缓冲区是 SPI 外设中用于缓解 CPU 与 SPI 速率不匹配的关键组件。它允许 CPU 一次性写入多个数据,然后由 SPI 硬件自动逐位发送,无需 CPU 逐字节干预。
3.4.1 FIFO 深度与阈值
| MCU 系列 | FIFO 深度 | 可配置阈值 | 典型应用 |
|---|---|---|---|
| STM32F1/F4 | 无 FIFO(仅 1 级) | — | 低速率、简单控制 |
| STM32L4/G4 | 8 级 | 1/4/8 | 中等速率、DMA 配合 |
| STM32H7 | 16 级 | 1/4/8/12/16 | 高速率、大块数据传输 |
| NXP i.MX RT | 32 级 | 可编程 1~32 | 实时控制、高吞吐量 |
3.4.2 FIFO 工作模式
- 轮询模式:CPU 循环检查 TXE(发送 FIFO 空)标志,每发送一个字节等待一次。FIFO 仅作为缓冲,减少中断频率。
- 中断模式:当 FIFO 低于阈值时触发 TXE 中断,CPU 在中断服务程序中填充 FIFO。阈值设为 FIFO 深度的一半可平衡响应速度与中断次数。
- DMA 模式:DMA 控制器直接向 FIFO 写入数据,当 FIFO 满或达到阈值时,SPI 硬件自动启动发送。这是最高效的模式。
3.4.3 FIFO 配置示例(STM32 HAL)
// 配置 SPI2 使用 FIFO,阈值设为 4 级
SPI_HandleTypeDef hspi2;
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
// 启用 FIFO 并设置阈值(STM32H7 系列)
hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_04DATA;
HAL_SPI_Init(&hspi2);
性能对比:在 72MHz 系统时钟、8 分频(SCK=9MHz)条件下,读取 4KB Flash 数据:无 FIFO 轮询模式约需 4.5ms,FIFO+DMA 模式仅需 0.9ms,性能提升约 5 倍。FIFO 深度越大,DMA 传输效率越高。
3.5 硬件架构对驱动设计的影响
理解上述硬件组件后,驱动开发应遵循以下原则:
- 初始化顺序:先配置时钟分频器确定速率,再配置移位寄存器格式(帧长、位序、CPOL/CPHA),最后使能 FIFO 和 DMA。
- 中断优先级:SPI 中断优先级应高于普通任务中断,但低于系统时钟中断,避免数据溢出。
- FIFO 阈值选择:对于 DMA 传输,阈值设为 FIFO 深度的一半(如 8 级 FIFO 设阈值为 4),可保证 DMA 请求连续触发。
- 速率调试步骤:从最低分频(256 分频)开始验证通信,逐步提高分频系数,直到出现误码为止,然后回退一档作为稳定工作点。
总结:SPI 硬件架构中的移位寄存器、时钟分频器和 FIFO 缓冲区是决定通信速率和可靠性的三大核心组件。驱动开发人员必须深入理解每个组件的配置选项及其对系统性能的影响,才能编写出高效、稳定的 SPI Flash 驱动。