STM32 SPI通信协议

1. SPI协议概述

1.1 什么是SPI?

SPI(Serial Peripheral Interface)是由摩托罗拉公司于1980年代提出的同步串行通信协议,主要用于短距离高速芯片间通信。作为四线制全双工通信协议,它以简单的硬件实现和高效的传输速率著称,广泛应用于存储器、传感器、显示模块等嵌入式设备中。

典型应用场景

  • 微控制器与Flash存储器通信(如W25Q128)
  • 触摸屏控制器数据传输
  • 数字信号处理器与ADC/DAC模块连接
  • TFT液晶屏驱动控制

1.2 核心特性对比

特性SPII2CUART
通信方式全双工半双工全双工
拓扑结构点对点/主从多主多从点对点
最大速率100Mbps+3.4Mbps115200bps
信号线数量422
寻址方式硬件片选软件地址无地址

https://img-blog.csdnimg.cn/20210720172318888.png


2. SPI物理层详解

2.1 四线制信号定义

  1. MOSI (Master Output Slave Input)
    • 主设备数据输出线
    • 传输方向固定:主→从
    • 典型应用:发送控制指令或写入数据
  2. MISO (Master Input Slave Output)
    • 从设备数据输出线
    • 传输方向固定:从→主
    • 注意:同一时刻只能有一个从设备驱动该线路
  3. SCLK (Serial Clock)
    • 主设备产生的同步时钟
    • 频率范围:通常1MHz-50MHz(具体取决于器件)
    • 时钟相位和极性可配置(详见第4章)
  4. SS/CS (Slave Select)
    • 低电平有效的片选信号
    • 每个从设备独立拥有CS线
    • 多从机系统需要多个GPIO控制

2.2 硬件连接注意事项

  • 总线长度限制:一般不超过30cm
  • 上拉电阻:根据器件需求添加(通常4.7kΩ-10kΩ)
  • 信号完整性:高速传输时需考虑阻抗匹配
  • 多从机连接方式:
    • 独立片选(推荐):每个从机单独CS线
    • 菊花链:数据级联传输(需器件支持)

3. SPI协议层深度解析

3.1 通信时序模型

c

Copy

// 典型SPI数据传输伪代码
void SPI_Transfer(uint8_t *txData, uint8_t *rxData, int length)
{
    CS_LOW(); // 起始信号
    
    for(int i=0; i<length; i++){
        // 时钟边沿触发数据交换
        for(int bit=7; bit>=0; bit--){
            MOSI = (txData[i] >> bit) & 0x01;
            SCLK_TOGGLE();
            rxData[i] |= (MISO << bit);
            SCLK_TOGGLE();
        }
    }
    
    CS_HIGH(); // 停止信号
}

3.2 关键时序参数

参数描述典型值
t_SCLK时钟周期20ns@50MHz
t_SU数据建立时间5ns
t_HOLD数据保持时间3ns
t_CS2CLKCS有效到第一个时钟边沿的延迟10ns

https://img-blog.csdnimg.cn/20210720172536907.png


4. SPI工作模式详解

4.1 CPOL与CPHA组合模式

c

Copy

typedef enum {
    SPI_MODE0 = 0,  // CPOL=0, CPHA=0
    SPI_MODE1,      // CPOL=0, CPHA=1
    SPI_MODE2,      // CPOL=1, CPHA=0
    SPI_MODE3       // CPOL=1, CPHA=1
} SPI_Mode;
4.1.1 模式0(最常用)
  • 时钟空闲状态:低电平
  • 数据采样时刻:上升沿
  • 应用案例:大多数SPI Flash存储器
4.1.2 模式3
  • 时钟空闲状态:高电平
  • 数据采样时刻:下降沿
  • 应用案例:某些型号的SD卡

4.2 模式选择实践建议

  1. 严格参照器件手册确定工作模式
  2. 使用逻辑分析仪验证实际波形
  3. 当通信异常时首先检查模式设置
  4. 注意不同厂家对模式的命名差异

5. STM32的SPI外设配置

5.1 初始化代码示例

c

Copy

void SPI1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    SPI_HandleTypeDef hspi1 = {0};

    // 时钟使能
    __HAL_RCC_SPI1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();

    // MOSI(PA7), MISO(PA6), SCLK(PA5)
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // SPI参数配置
    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_4;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    HAL_SPI_Init(&hspi1);
}

5.2 关键配置参数解析

  1. BaudRatePrescaler
    • 计算公式:SCLK = APB Clock / (2 * prescaler)
    • 常用值:2分频(高速模式)、8分频(常规模式)
  2. DataSize
    • 支持8/16位数据帧
    • 注意对齐16位访问(使用__packed关键字)
  3. NSS管理
    • 硬件模式:自动片选(需配置NSS引脚)
    • 软件模式:手动控制GPIO(推荐)

6. SPI与I2C的对比选择

6.1 协议特性对比

对比维度SPII2C
传输速率高速(50MHz+)中速(400kHz-1MHz)
引脚资源4线+N*CS2线
寻址方式硬件片选7/10位地址
拓扑复杂度多CS线导致布线复杂总线式易于扩展
功耗较高(持续时钟)较低(时钟拉伸)

6.2 选型建议

选择SPI当

  • 需要高速数据传输
  • 系统对实时性要求高
  • 通信距离短(<30cm)
  • 主设备引脚资源充足

选择I2C当

  • 设备数量多且布线空间有限
  • 通信速率要求不高
  • 需要热插拔支持
  • 低功耗设计场景

7. SPI实战应用案例

7.1 OLED显示屏驱动

c

Copy

// SSD1306写命令函数
void OLED_WriteCmd(uint8_t cmd)
{
    OLED_CS_LOW();
    OLED_DC_CMD();  // 命令模式
    HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
    OLED_CS_HIGH();
}

// 初始化序列示例
const uint8_t init_seq[] = {
    0xAE, // 关闭显示
    0xD5, 0x80, // 设置时钟分频
    0xA8, 0x3F, // 设置多路复用率
    // ...其他初始化命令
};

void OLED_Init(void)
{
    for(int i=0; i<sizeof(init_seq); i++){
        OLED_WriteCmd(init_seq[i]);
    }
}

7.2 FLASH存储器读写

c

Copy

#define W25Q_CMD_READ  0x03
#define W25Q_CMD_WRITE 0x02

void W25Q_ReadData(uint32_t addr, uint8_t *buffer, uint16_t len)
{
    uint8_t cmd[4] = {
        W25Q_CMD_READ,
        (addr >> 16) & 0xFF,
        (addr >> 8) & 0xFF,
        addr & 0xFF
    };
    
    W25Q_CS_LOW();
    HAL_SPI_Transmit(&hspi1, cmd, 4, 100);
    HAL_SPI_Receive(&hspi1, buffer, len, 1000);
    W25Q_CS_HIGH();
}

8. 常见问题排查指南

8.1 通信失败常见原因

  1. 模式配置错误(占故障的60%以上)
    • 检查CPOL/CPHA设置
    • 使用逻辑分析仪捕获实际波形
  2. 时序问题
    • 确保CS信号有效时间足够
    • 调整时钟分频系数
  3. 硬件连接故障
    • 检查线路短路/断路
    • 确认电压电平匹配

8.2 调试技巧

  1. 使用示波器测量关键信号:
    • SCLK频率是否符合预期
    • MOSI/MISO数据是否对齐时钟边沿
    • CS信号的有效时间
  2. 分步验证:
    • 先测试单字节传输
    • 验证主从设备各自独立工作
    • 添加软件延时辅助调试

9. 未来发展趋势

  1. 增强型SPI协议
    • QSPI(四线制,带宽翻倍)
    • OSPI(Octal SPI,八线制)
    • HyperBus(混合协议)
  2. 自动化配置技术
    • 基于AI的自动模式识别
    • 动态时钟调整技术
  3. 安全增强
    • 硬件加密引擎集成
    • 时序随机化防窃听

10. 总结与建议

通过本文的系统讲解,我们深入剖析了SPI协议的各个技术细节。在实际项目开发中,建议:

  1. 建立标准化的SPI驱动框架
  2. 编写完善的错误检测和恢复机制
  3. 使用版本控制管理设备配置参数
  4. 定期进行总线信号完整性测试

随着物联网设备的爆发式增长,SPI作为经典的高速通信协议,仍将在嵌入式领域发挥重要作用。掌握其核心原理并积累实战经验,是嵌入式工程师的必备技能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值