文章目录
概要
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 协议的核心知识,并在实际项目中灵活应用。