1. SPI通信协议概述
SPI(Serial Peripheral Interface)是一种同步串行通信协议,由摩托罗拉在1980年代提出,现已成为嵌入式系统中最常用的短距离通信标准之一。与I2C、UART等其他串行协议相比,SPI以其全双工、高速率(可达数十MHz)和简单硬件实现的特性,在存储器、传感器、显示设备等外设连接中占据重要地位。
我在实际项目中接触过各种SPI设备,从简单的EEPROM到复杂的TFT显示屏,发现虽然具体实现各有差异,但核心通信机制万变不离其宗。理解SPI协议的底层原理,能帮助开发者快速适配不同厂商的设备,甚至解决那些数据手册没有明确说明的兼容性问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. SPI硬件架构解析
2.1 四线制基础结构
标准SPI采用四线制连接:
- SCLK(Serial Clock):主设备产生的同步时钟
- MOSI(Master Out Slave In):主设备发送数据线
- MISO(Master In Slave Out):从设备返回数据线
- SS/CS(Slave Select/Chip Select):从设备使能信号
实际布线时建议SCLK走线长度不超过MOSI/MISO的20%,否则可能因时钟偏移导致采样错误。我在驱动SPI Flash时就遇到过因30cm长线导致的间歇性读写失败。
2.2 扩展信号线变体
某些特殊场景会引入额外控制线:
- HOLD:暂停传输(常见于Flash芯片)
- WP(Write Protect):写保护
- IO2/IO3:四线SPI的扩展数据线
- READY:从设备就绪信号(如六线SPI)
3. 通信时序深度剖析
3.1 四种工作模式
通过CPOL(时钟极性)和CPHA(时钟相位)组合形成四种模式:
| 模式 | CPOL | CPHA | 时钟空闲状态 | 数据采样边沿 |
|---|---|---|---|---|
| 0 | 0 | 0 | 低电平 | 上升沿 |
| 1 | 0 | 1 | 低电平 | 下降沿 |
| 2 | 1 | 0 | 高电平 | 下降沿 |
| 3 | 1 | 1 | 高电平 | 上升沿 |
大多数SPI Flash使用Mode 0或Mode 3,而ST7735S显示屏通常需要Mode 0。配置错误会导致数据错位,我曾花费两小时排查STM32驱动OLED时的花屏问题,最终发现是模式不匹配。
3.2 典型传输波形
以Mode 0为例的完整传输周期:
- 主设备拉低CS信号
- 在SCLK上升沿前至少半个周期准备好MOSI数据
- 从设备在SCLK上升沿采样MOSI
- 主设备在SCLK下降沿采样MISO
- 传输完成后拉高CS
4. 高级应用技巧
4.1 菊花链拓扑
通过级联多个从设备实现单CS控制:
c复制// 典型菊花链数据移位代码
void daisy_chain_transfer(uint8_t *data, uint8_t len) {
CS_LOW();
for(int i=len-1; i>=0; i--) {
for(int bit=7; bit>=0; bit--) {
MOSI = (data[i] >> bit) & 0x01;
SCLK_TOGGLE();
// 从设备数据会逐级传递
}
}
CS_HIGH();
}
4.2 软件片选优化
当硬件CS引脚不足时,可用GPIO模拟:
c复制void soft_cs_control(uint8_t dev_id) {
static uint8_t last_dev = 0xFF;
if(last_dev != 0xFF) {
GPIO_WritePin(CS_PORTS[last_dev], CS_PINS[last_dev], HIGH);
}
GPIO_WritePin(CS_PORTS[dev_id], CS_PINS[dev_id], LOW);
last_dev = dev_id;
}
5. 常见问题排查指南
5.1 通信失败检查清单
- 电源与接地:确保共地,电压匹配(3.3V与5V设备混接需电平转换)
- 时钟速率:初始调试建议降至100kHz以下
- 模式配置:用逻辑分析仪确认CPOL/CPHA
- CS信号:检查有效电平(有些设备要求高电平使能)
- 线序检查:MOSI-MISO交叉连接是常见错误
5.2 特殊案例处理
- WS2812误识别:部分RGB LED芯片会错误响应SPI时钟,建议在CS线加1K下拉电阻
- TF卡初始化:需先发送74个以上时钟脉冲进入SPI模式
- ST7735S屏驱动:注意DC信号与SPI的配合时序
6. 协议对比与选型建议
6.1 主流串行协议对比
| 特性 | SPI | I2C | UART |
|---|---|---|---|
| 最大速率 | 50MHz+ | 3.4MHz | 6Mbps |
| 通信方式 | 全双工 | 半双工 | 全双工 |
| 硬件复杂度 | 中等 | 简单 | 简单 |
| 寻址能力 | 无 | 7/10位 | 无 |
| 典型应用 | Flash, LCD | 传感器 | 调试接口 |
6.2 选型决策树
- 需要高速传输? → 选SPI
- 设备数量多且引脚紧张? → 选I2C
- 仅需简单调试? → 选UART
- 长距离通信? → 考虑RS485(需转换芯片)
在Zynq7000项目中,我们最终选择通过EMIO扩展SPI接口连接Flash,因为PL端的硬件SPI控制器能实现比PS端更精确的时序控制。实测在QSPI模式下写入速度可达22MB/s,比标准SPI快3倍以上。
