嵌入式笔记:常用接口之详解SPI通信协议

 一、SPI协议概述

SPI由Motorola于1980年代推出,采用全双工同步通信模式,具有以下核心特征:
- 高速传输:可达100MHz时钟频率
- 主从架构:支持一主多从拓扑
- 硬件连接:4线制基础配置(SCK/MOSI/MISO/SS)

关于具体的SPI,I2C,UART的特点与比较在之前的博客中都有介绍,这里不再过多阐述。

二、工作原理

2.1 物理层接口

信号线全称方向作用描述  
SCKSerial Clock主→从同步时钟信号
MOSIMaster Out Slave In主→从主机数据输出
MISOMaster In Slave Out从→主  从机数据输出
SS/CSSlave Select主→从从机片选信号(低电平有效)

根据英文很容易记住每个信号线的作用

典型连接拓扑:

主机           从机1          从机2
SCK  --------- SCK --------- SCK
MOSI --------- SDI --------- SDI
MISO --------- SDO --------- SDO
SS1 ---------- CS             |
SS2 ------------------------ CS

2.2 数据传输机制

1. 时钟同步:主机生成SCK信号,每个时钟周期传输1bit数据
2. 双工传输:MOSI与MISO同时工作,实现双向通信
3. 数据移位:采用移位寄存器实现串并转换
   - 主机寄存器:8位数据通过MOSI移出
   - 从机寄存器:同时通过MISO移入数据

2.3 时钟模式配置

SPI通信通过CPOL(时钟极性)与CPHA(时钟相位)组合形成四种工作模式,它们共同决定了 SPI 通信的时序,确保主设备和从设备能够正确地同步和交换数据。

首先了解时钟极性和时钟相位两个概念:

时钟极性 (CPOL - Clock Polarity)

定义: CPOL 决定了 SPI 时钟线 (SCK) 在空闲状态时的电平。 换句话说,当没有数据传输时,SCK 应该保持什么电平。

CPOL = 0: SCK 在空闲时保持低电平。

CPOL = 1: SCK 在空闲时保持高电平。

时钟相位 (CPHA - Clock Phase)

定义: CPHA 决定了在 SPI 时钟周期的哪个边沿 (上升沿或下降沿) 采样 (读取) 数据,以及在哪个边沿改变 (输出) 数据。

CPHA = 0:

  • 在 SCK 的第一个边沿 (取决于 CPOL,如果是上升沿或下降沿) 采样 MISO (主设备输入,从设备输出) 和 MOSI (主设备输出,从设备输入) 上的数据。
  • 在 SCK 的第二个边沿 改变 MOSI 和 MISO 上的数据。 这意味着数据在时钟边沿发生变化,并在下一个时钟边沿被采样。

CPHA = 1:

  • 在 SCK 的第二个边沿 采样 MISO 和 MOSI 上的数据。
  • 在 SCK 的第一个边沿 改变 MOSI 和 MISO 上的数据。 这意味着数据在时钟边沿发生变化,并在同一个时钟边沿被采样。

由此我们可以做出这样的总结:

  • CPOL 决定空闲状态: SCK 空闲时是高电平还是低电平。
  • CPHA 决定采样和改变的时机: 决定在哪个时钟边沿采样数据,在哪个时钟边沿改变数据。

CPOL(时钟极性)与CPHA(时钟相位)组合形成的四种工作模式

三、协议进阶特性

1. 独立片选法:

每个从机独占SS线类似并联结构(硬件资源消耗大)


2. 菊花链拓扑:

多个从机串联,数据级联传输

3. 性能优化策略

- 时钟分频:根据设备特性调整SCK频率
- DMA传输:减少CPU占用率
- 双缓冲机制:提升吞吐量

四、SPI协议优缺点分析

优势:
- 传输速率显著高于I2C(可达100Mbps)
- 时钟配置更灵活
- 全双工通信效率高

局限:
- 短距离通信
- 多从机需要较多IO资源(至少四根)
- 没有设备地址,多设备时需要额外的片选线

五、应用场景与开发

1. 存储器访问:NOR Flash、SD卡(SPI模式)
2. 显示驱动:OLED、TFT屏幕
3. 传感器读取:IMU(MPU6050)、环境传感器
4. 无线模块:nRF24L01+、ESP8266

以下是STM32cubeMX的部分代码,仅供参考

static void MX_SPI1_Init(void)
{
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;				//主机模式
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;	//全双工
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;		//数据位为8位
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;		//CPOL=0
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;			//CPHA为数据线的第一个变化沿
    hspi1.Init.NSS = SPI_NSS_SOFT;					//软件控制NSS
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;//2分频,32M/2=16MHz
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;			//最高位先发送
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;			//TIMODE模式关闭
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;//CRC关闭
    hspi1.Init.CRCPolynomial = 10;					//默认值,无效
    if (HAL_SPI_Init(&hspi1) != HAL_OK)				//初始化
    {
        _Error_Handler(__FILE__, __LINE__);
    }
}
    
//发送数据
HAL_StatusTypeDef  
HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, 
                 uint8_t *pData, 
                 uint16_t Size, 
                 uint32_t Timeout);
//接收数据
HAL_StatusTypeDef  
HAL_SPI_Receive(SPI_HandleTypeDef *hspi, 
                uint8_t *pData, 
                uint16_t Size, 
                uint32_t Timeout);

六、SPI的常见问题

时钟模式不匹配: 主从设备的CPOL和CPHA设置不一致会导致通信失败。

片选错误: 没有正确选择从设备会导致数据传输错误。

传输速率过高: 传输速率超过从设备的最大支持速率会导致数据丢失。

引脚连接错误: MOSI和MISO引脚连接错误会导致数据传输方向错误。

B站有众多课程涉及到SPI通信讲解,大家可以自行学习,本文仅作为学习总结,欢迎大家交流学习,共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值