1. SPI通信基础概念解析
SPI(Serial Peripheral Interface)作为一种同步串行通信协议,在嵌入式系统和硬件开发中占据着核心地位。我第一次接触SPI是在调试一个传感器模块时,当时被它简洁的四线制设计和高速传输特性所吸引。与I2C相比,SPI最大的特点是采用主从架构和全双工通信,这使得它在需要高速数据交换的场景中表现尤为出色。
SPI总线由四根基本信号线组成:
- SCLK(Serial Clock):时钟信号线,由主设备产生
- MOSI(Master Out Slave In):主设备输出,从设备输入
- MISO(Master In Slave Out):主设备输入,从设备输出
- SS/CS(Slave Select/Chip Select):片选信号线(低电平有效)
实际应用中常见一个误区:认为SPI必须同时使用MISO和MOSI。其实在单向传输场景下,可以只使用其中一条数据线,这在驱动某些特定外设(如DAC芯片)时能节省IO资源。
SPI的工作机制本质上是通过时钟边沿同步数据。主设备控制时钟信号,在SCLK的每个周期内,主从设备同时交换一位数据。这种同步特性使得SPI可以达到很高的传输速率(通常可达几十MHz),远高于异步串口通信。
2. SPI四种工作模式深度剖析
SPI的工作模式由CPOL(Clock Polarity)和CPHA(Clock Phase)两个参数决定,组合出四种不同的时序模式。我在调试不同厂家的设备时,经常遇到因模式设置不当导致的通信失败问题,这也是新手最容易踩的坑。
2.1 模式0与模式3对比
模式0(CPOL=0,CPHA=0)是最常用的配置:
- 时钟空闲时为低电平
- 数据在时钟的第一个边沿(上升沿)采样
- 适用于大多数SPI从设备(如Flash存储器)
模式3(CPOL=1,CPHA=1)在特定传感器中常见:
- 时钟空闲时为高电平
- 数据在时钟的第二个边沿(下降沿)采样
- 某些温度传感器(如MAX31855)就采用此模式
重要经验:设备手册中如果标注"SPI mode 1"这样的描述,通常指的就是模式0-3的编号。我曾因混淆编号和参数导致整批传感器数据异常,建议在代码中明确注释CPOL和CPHA值。
2.2 模式1和模式2的特殊应用
模式1(CPOL=0,CPHA=1):
- 数据在时钟下降沿捕获
- 某些ADC芯片(如ADS1256)采用此模式
模式2(CPOL=1,CPHA=0):
- 数据在时钟上升沿捕获
- 在电机驱动芯片(如DRV8711)中可能遇到
实测中发现一个规律:存储类器件多用模式0/3,而模拟量采集器件倾向模式1/2。这可能与信号稳定性的需求有关。
3. SPI硬件接口实现细节
3.1 标准SPI与模拟SPI实现
硬件SPI(如STM32的SPI外设):
- 由专用硬件实现,CPU开销低
- 支持DMA传输,适合大数据量场景
- 但管脚固定,布线受限
模拟SPI(GPIO模拟):
- 任意IO口均可实现
- 时序完全可控,便于调试
- 但占用CPU资源,速率受限
在最近一个项目中,我同时使用了硬件SPI和模拟SPI:
- 硬件SPI连接TFT屏幕(ILI9341)
- 模拟SPI连接多个低速传感器 这种混合方案既保证了显示流畅度,又实现了管脚资源的灵活分配。
3.2 片选信号的处理技巧
硬件片选:
- 使用专用SS引脚
- 硬件自动控制,效率高
- 但引脚数量受限
软件片选:
- 任意GPIO控制
- 可配合SPI复用器扩展多设备
- 需要手动管理时序
一个实用技巧:对于高速设备(如W25Q64 Flash),建议在传输完成后延迟1-2个时钟周期再释放CS,避免最后一位数据丢失。这个细节在多数手册中不会明确说明,是我通过示波器实测发现的。
4. SPI高级应用与性能优化
4.1 DMA在SPI中的应用
以STM32H750驱动SPI LCD为例:
- 配置SPI为16位宽模式(RGB565格式)
- 设置DMA为内存到外设模式
- 启用DMA双缓冲机制
- 配置DMA传输完成中断
关键点:DMA缓冲区的地址必须对齐到4字节边界,否则会导致性能下降。这个问题在H750上尤为明显,我通过__attribute__((aligned(4)))强制对齐解决了帧率不稳定的问题。
4.2 SPI菊花链拓扑
适用于多个相同器件级联:
- 所有器件的SCLK、MOSI、MISO并联
- 仅第一个器件的CS连接主控
- 数据依次通过各器件传递
典型应用场景:
- 多个数字电位器级联
- LED驱动芯片(如WS2812的SPI驱动方案)
- 多通道ADC采集系统
注意:菊花链中每个器件都会引入一个时钟周期的延迟,计算总传输长度时需要乘以器件数量。
5. 常见问题排查指南
5.1 无数据返回问题排查(以DRV8711为例)
- 确认模式设置正确(通常模式1)
- 检查CS信号是否有效(有些芯片要求CS在两次传输间保持高电平)
- 验证时钟极性是否匹配(用示波器观察SCLK和MOSI相位)
- 检查MISO引脚上拉电阻(部分开漏输出需要上拉)
5.2 SPI与I2C/UART的选型参考
| 特性 | SPI | I2C | UART |
|---|---|---|---|
| 速度 | 高(50MHz+) | 中(400kHz) | 低(115200bps) |
| 引脚数 | 4线+CS | 2线 | 2线 |
| 拓扑 | 点对点/菊花链 | 多主多从 | 点对点 |
| 复杂度 | 中等 | 高 | 低 |
选择建议:
- 高速、短距离:优先SPI
- 多设备、中速:考虑I2C
- 远距离、简单设备:UART更合适
6. SPI在实际项目中的应用实例
6.1 STM32驱动SPI Flash(W25Q64)
关键配置参数:
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_2; // 系统时钟二分频 hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;读写操作注意事项:
- 写操作前必须发送WREN指令
- 页编程地址自动回卷(256字节边界)
- 读取状态寄存器判断操作完成
6.2 绝对式编码器(MT6701)SPI接口实现
特殊处理点:
- 需要14位数据读取(非标准8/16位)
- 采用模式1(CPOL=0,CPHA=1)
- CRC校验需软件实现
数据帧结构:
[13:0] - 角度值(0-16383) [15:14] - CRC校验位实测发现:在电机干扰环境下,建议降低SPI时钟频率(<1MHz)并增加CS信号滤波电容(100pF),可显著提高读数稳定性。
7. SPI信号完整性与PCB设计要点
7.1 走线规范
- 等长处理:SCLK与数据线长度差控制在±5mm内
- 阻抗匹配:串联33Ω电阻减少反射
- 避免交叉:MOSI/MISO尽量不平行长距离走线
7.2 接地策略
- 使用完整地平面
- 敏感器件(如ADC)采用星型接地
- SPI信号线下方保持连续地参考面
在最近一个高速SPI项目(20MHz)中,通过将线宽控制在6mil、线间距3倍线宽,使信号质量明显改善,眼图测试结果提升40%。
8. 特殊SPI变种与应用
8.1 单线双向SPI
某些ADC芯片(如ADS1256)支持:
- 共用SDIO线实现半双工通信
- 通过方向控制位切换收发
- 节省IO资源但速率减半
实现要点:
- 配置SPI为单线模式
- 在传输间隙切换方向
- 增加适当延时保证方向稳定
8.2 QSPI接口
四线SPI(Quad SPI)特性:
- 数据线扩展到4条(IO0-IO3)
- 指令阶段仍使用标准SPI
- 数据阶段可并行传输
在W25Q256FV Flash上的性能对比:
| 模式 | 读取速度 |
|---|---|
| 标准SPI | 50MHz |
| Dual SPI | 2倍速 |
| Quad SPI | 4倍速 |
使用QSPI时需要注意:多数芯片需要先发送特定指令(如0xEB)进入四线模式,且IO口需要配置为推挽输出模式。