SPI 协议深度解析:从原理到实战(附源码)

概要

SPI(Serial Peripheral Interface)是一种高速、全双工、同步通信协议,广泛应用于嵌入式系统中。以下从底层原理到实际应用进行全方位解析,帮助你深入理解并熟练运用这一协议。

一、SPI 协议基础架构

1. 物理层设计

四线制通信:
SCLK(Serial Clock):时钟信号线,由主设备控制
MOSI(Master Out Slave In):主设备发送,从设备接收
MISO(Master In Slave Out):从设备发送,主设备接收
SS/CS(Slave Select/Chip Select):片选信号线,低电平有效
电气特性:
支持单主多从架构,每个从设备需要独立的 SS 线
高速传输能力(可达数十 Mbps),适合短距离通信

2. 通信拓扑结构

在这里插入图片描述

二、SPI 通信原理

1. 主从架构

主设备(Master):
控制时钟信号(SCLK)和片选信号(SS),发起通信
从设备(Slave):
响应主设备的片选信号,根据 SCLK 同步数据传输

2. 数据传输机制

同步传输:
数据传输由 SCLK 信号同步,主从设备在时钟边沿采样数据
全双工通信:
MOSI 和 MISO 线独立工作,可同时发送和接收数据
移位寄存器:
主从设备各有一个移位寄存器,数据在时钟驱动下逐位移动

3. 片选信号(SS/CS)

低电平有效:
主设备通过拉低特定从设备的 SS 线来选择通信对象
多从机实现:
每个从设备需要独立的 SS 线,主设备通过控制不同的 SS 线选择目标从机

三、SPI 模式与时序

1. 时钟极性(CPOL)与相位(CPHA)

CPOL(Clock Polarity):
定义时钟空闲状态电平
CPOL=0:时钟空闲时为低电平
CPOL=1:时钟空闲时为高电平
CPHA(Clock Phase):
定义数据采样时机
CPHA=0:数据在第一个时钟边沿采样
CPHA=1:数据在第二个时钟边沿采样

2. 四种 SPI 模式组合

在这里插入图片描述

3. 时序示例(模式 0)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、SPI 数据帧格式

1. 单字节传输流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 多字节传输

连续传输:
在第一个字节传输完成后,继续提供时钟信号,即可传输更多字节
MSB/LSB 优先:
数据传输顺序可配置为高位优先(MSB)或低位优先(LSB)

五、SPI 协议优缺点

1. 优点

高速传输:支持数十 Mbps 的传输速率
全双工通信:可同时发送和接收数据
简单协议:无需复杂的握手和应答机制
灵活性高:可自定义数据帧格式和传输长度

2. 缺点

硬件成本高:每个从设备需要独立的 SS 线
缺乏流控制:没有应答机制,需上层协议保证可靠性
扩展性有限:从设备数量受限于主设备的 GPIO 数量
无寻址机制:需通过物理连线区分从设备

六、SPI 与其他协议对比

在这里插入图片描述

七、SPI 应用场景

1. 常见外设接口

传感器:加速度计、陀螺仪、温度传感器等
存储设备:SPI Flash、EEPROM 等
显示设备:OLED/LCD 显示屏控制器
通信模块:WiFi 模块、蓝牙模块等

2. 典型应用案例

数据采集系统:主控制器通过 SPI 读取多个传感器数据
显示驱动:向 OLED 屏幕发送图像数据
存储扩展:使用 SPI Flash 存储大量数据

八、SPI 实战技巧

1. 软件模拟 SPI

// 软件模拟SPI(模式0)发送单字节
void spi_send_byte(uint8_t data) {
    uint8_t i;
    for (i = 0; i < 8; i++) {
        // 发送数据(MSB优先)
        if (data & 0x80) {
            MOSI_HIGH();
        } else {
            MOSI_LOW();
        }
        data <<= 1;
        
        // 生成时钟上升沿(采样数据)
        SCLK_LOW();
        delay_us(1);  // 延时确保信号稳定
        SCLK_HIGH();
        delay_us(1);
    }
}

// 软件模拟SPI接收单字节
uint8_t spi_receive_byte(void) {
    uint8_t i, data = 0;
    for (i = 0; i < 8; i++) {
        // 生成时钟下降沿(发送数据)
        SCLK_HIGH();
        delay_us(1);
        
        // 采样数据
        data <<= 1;
        if (MISO_READ()) {
            data |= 0x01;
        }
        
        SCLK_LOW();
        delay_us(1);
    }
    return data;
}

2. 硬件 SPI 配置(STM32 为例)

// 初始化SPI1为主设备(模式0)
void SPI1_Init(void) {
    // 使能SPI1和GPIO时钟
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    
    // 配置GPIO引脚(PA5:SCLK, PA6:MISO, PA7:MOSI)
    GPIOA->MODER |= GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1;
    GPIOA->AFR[0] |= (5 << 20) | (5 << 24) | (5 << 28);  // AF5 for SPI1
    
    // 配置SPI1
    SPI1->CR1 |= SPI_CR1_BR_1 | SPI_CR1_BR_0;  // 波特率 = fPCLK/32
    SPI1->CR1 &= ~SPI_CR1_CPOL;  // CPOL=0
    SPI1->CR1 &= ~SPI_CR1_CPHA;  // CPHA=0
    SPI1->CR1 |= SPI_CR1_MSTR;   // 主模式
    SPI1->CR1 |= SPI_CR1_SSI;    // 内部从设备选择
    SPI1->CR1 |= SPI_CR1_SPE;    // 使能SPI
}

// SPI发送并接收数据
uint8_t SPI1_TransferByte(uint8_t data) {
    // 等待发送缓冲区为空
    while (!(SPI1->SR & SPI_SR_TXE));
    
    // 发送数据
    SPI1->DR = data;
    
    // 等待接收缓冲区非空
    while (!(SPI1->SR & SPI_SR_RXNE));
    
    // 返回接收的数据
    return SPI1->DR;
}

3. 常见问题排查

在这里插入图片描述

九、SPI 扩展与变种

1. QSPI(Quad SPI)

  • 特性:使用 4 条数据线同时传输数据,带宽提升 4 倍
  • 应用:高速 Flash 存储器访问,图形数据传输

2. DSPI(Dual SPI)

  • 特性:使用 2 条数据线同时传输数据,带宽提升 2 倍

3. 三线 SPI

  • 特性:共享 MOSI 和 MISO 线,减少引脚使用
  • 缺点:半双工通信,需软件控制数据线方向

十、总结

SPI 协议凭借其高速、全双工的特性,成为嵌入式系统中数据传输的重要选择。理解其工作原理、掌握数据帧格式和时序模式是应用的基础,而处理实际问题和性能优化则需要结合硬件设计和软件编程技巧。通过本文的解析,你可以系统性掌握 SPI 协议的核心知识,并在实际项目中灵活应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逻辑森林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值