3. SPI硬件架构:主从设备结构、移位寄存器原理、数据收发机制、片选信号的作用与多从机连接方式
SPI(Serial Peripheral Interface,串行外设接口)由Motorola公司于20世纪80年代提出,是一种高速、全双工、同步的串行通信总线。与I2C和UART相比,SPI以极简的硬件逻辑和极高的传输速率在嵌入式系统中占据不可替代的地位。理解SPI的硬件架构,是掌握其通信协议、时序设计以及驱动开发的基础。本章将从物理连接结构出发,深入剖析主从设备之间的数据通路、移位寄存器的工作机制、数据收发流程,以及片选信号在多从机系统中的关键作用。
上图展示了SPI总线最基本的物理连接架构。主设备(Master)与从设备(Slave)之间通过四条信号线相连:SCLK(串行时钟)、MOSI(主出从入)、MISO(主入从出)和SS(片选)。这四条线构成了SPI通信的物理基础,理解它们各自的作用以及相互之间的时序关系,是进行SPI驱动开发和硬件调试的前提。
3.1 主从设备结构与信号线定义
核心原理:SPI总线采用主从(Master-Slave)架构,通信始终由主设备发起。主设备通常是MCU、SoC或FPGA,负责产生时钟信号并控制通信节奏;从设备是外设芯片,如Flash存储器、ADC、DAC、传感器等,被动响应主设备的操作。这种架构决定了SPI通信的时序完全由主设备掌控,从设备无法主动发起数据传输。
四条信号线的具体功能如下:
- SCLK(Serial Clock):由主设备产生,为通信提供同步时钟。SCLK的频率决定了数据传输速率,常见的SPI时钟频率从几百kHz到几十MHz不等。SCLK的极性和相位可以通过CPOL(Clock Polarity)和CPHA(Clock Phase)配置,以适应不同从设备的时序要求。
- MOSI(Master Out Slave In):主设备输出、从设备输入的数据线。主设备通过MOSI线向从设备发送命令、地址或数据。
- MISO(Master In Slave Out):从设备输出、主设备输入的数据线。从设备通过MISO线向主设备返回状态或数据。
- SS(Slave Select):片选信号,低电平有效。主设备通过拉低某个从设备的SS引脚来选中该从设备,使其参与通信;未被选中的从设备则释放MISO线,保持高阻态,避免总线冲突。
3.2 移位寄存器原理与数据收发机制
核心原理:SPI的数据收发依赖于主从设备内部各有一个移位寄存器(Shift Register)。移位寄存器是一种能够在时钟脉冲作用下,将数据逐位向左或向右移动的存储结构。SPI通信的本质,就是主从设备的移位寄存器通过MOSI和MISO线首尾相连,构成一个环形移位回路。
以8位数据为例,一次完整的数据传输过程如下:
- 主设备将待发送的8位数据装入其移位寄存器,从设备也将自己的8位数据装入其移位寄存器。
- 主设备拉低SS,选中从设备,并开始产生SCLK时钟脉冲。
- 在每个SCLK时钟沿(上升沿或下降沿,取决于CPOL/CPHA配置),主设备和从设备同时从移位寄存器中移出最高位(MSB)到MOSI/MISO线上,同时从线上采样移入一位数据到移位寄存器的最低端。
- 经过8个时钟周期后,主设备的移位寄存器中存放的是从设备发来的8位数据,从设备的移位寄存器中存放的是主设备发来的8位数据。此时一次传输完成。
这种机制实现了全双工通信:主设备发送数据的同时,也在接收从设备的数据。因此,SPI的每一次传输,都同时完成了一次“写”和一次“读”操作。
| 时钟周期 | 主设备移位寄存器内容 | 从设备移位寄存器内容 | MOSI线上数据 | MISO线上数据 |
|---|---|---|---|---|
| 初始 | 1 0 1 0 0 1 1 0 | 0 1 1 0 1 0 0 1 | - | - |
| 第1个时钟 | 0 1 0 0 1 1 0 0 | 1 1 0 1 0 0 1 1 | 1 (主→从) | 0 (从→主) |
| 第2个时钟 | 1 0 0 1 1 0 0 1 | 1 0 1 0 0 1 1 0 | 0 | 1 |
| 第3个时钟 | 0 0 1 1 0 0 1 0 | 0 1 0 0 1 1 0 1 | 1 | 1 |
| ... | ... | ... | ... | ... |
| 第8个时钟 | 0 1 1 0 1 0 0 1 | 1 0 1 0 0 1 1 0 | 0 | 1 |
上表清晰地展示了移位寄存器在8个时钟周期内的数据交换过程。可以看到,主设备发送的数据(10100110)完整地移入了从设备的移位寄存器,而从设备发送的数据(01101001)也完整地移入了主设备的移位寄存器。这就是SPI全双工通信的底层实现。
3.3 片选信号的作用与多从机连接方式
核心原理:片选信号SS是SPI总线中唯一由主设备控制、用于选择从设备的信号。当SS为高电平时,从设备与总线隔离,其MISO引脚处于高阻态,不参与通信;当SS被拉低时,从设备被激活,开始响应SCLK时钟并参与数据交换。SS信号的低电平有效特性,使得多个从设备可以共享SCLK、MOSI和MISO三条总线,而不会发生数据冲突。
多从机连接方式主要有两种:独立片选方式和菊花链方式。
独立片选方式(Parallel SS):每个从设备都有一根独立的SS线连接到主设备的GPIO引脚。主设备通过控制不同的GPIO引脚电平来选择对应的从设备。这种方式连接简单,访问速度快,但会占用主设备较多的GPIO资源。例如,主设备连接4个从设备,就需要4个GPIO引脚作为片选。
菊花链方式(Daisy Chain):所有从设备共享一根SS线,但数据线采用级联方式连接:主设备的MOSI连接到第一个从设备的MOSI,第一个从设备的MISO连接到第二个从设备的MOSI,以此类推,最后一个从设备的MISO连接到主设备的MISO。这种方式只需要一个GPIO引脚作为片选,但数据传输延迟较大,且从设备必须支持菊花链功能。菊花链常用于多个相同类型的设备级联,如多片移位寄存器或LED驱动芯片。
| 对比维度 | 独立片选方式 | 菊花链方式 |
|---|---|---|
| SS线数量 | 每个从机一根,占用GPIO多 | 所有从机共享一根,节省GPIO |
| 数据传输速度 | 快,直接访问目标从机 | 慢,数据需逐级传递 |
| 硬件复杂度 | 简单,布线直观 | 较复杂,需考虑级联时序 |
| 适用场景 | 从机数量少(2-4个),对速度敏感 | 从机数量多,且支持菊花链功能 |
3.4 案例拆解:基于STM32的多从机SPI采集系统
案例背景:某工业数据采集项目需要同时读取3个SPI接口的温度传感器(MAX31855)和1个SPI接口的Flash存储芯片(W25Q64)。主控采用STM32F407,SPI1外设作为Master,工作频率设为2MHz。系统要求每100ms完成一次所有传感器的温度读取,并将数据写入Flash。
硬件连接方案:
- SCLK、MOSI、MISO三根线并联连接到所有4个从设备。
- 3个MAX31855分别使用PA4、PA5、PA6作为独立SS引脚。
- W25Q64使用PA7作为SS引脚。
- 所有从设备的电源均采用3.3V供电,并在电源引脚附近放置100nF去耦电容。
软件实现要点:
// 伪代码示例:读取3个温度传感器并写入Flash
void Read_All_Temp_And_Store(void) {
uint8_t temp_data[3][4]; // 每个MAX31855返回4字节数据
uint8_t flash_buffer[12];
// 读取第1个温度传感器
SS1_LOW(); // 拉低PA4,选中MAX31855_1
SPI_ReceiveData(temp_data[0], 4); // 接收4字节
SS1_HIGH(); // 拉高PA4,释放从机
// 读取第2个温度传感器
SS2_LOW(); // 拉低PA5
SPI_ReceiveData(temp_data[1], 4);
SS2_HIGH();
// 读取第3个温度传感器
SS3_LOW(); // 拉低PA6
SPI_ReceiveData(temp_data[2], 4);
SS3_HIGH();
// 将温度数据打包
memcpy(flash_buffer, temp_data[0], 4);
memcpy(flash_buffer + 4, temp_data[1], 4);
memcpy(flash_buffer + 8, temp_data[2], 4);
// 写入Flash(先发送写使能命令,再写数据)
SS4_LOW(); // 拉低PA7,选中W25Q64
SPI_SendCommand(0x06); // 写使能
SS4_HIGH();
SS4_LOW();
SPI_SendCommand(0x02); // 页编程命令
SPI_SendAddress(0x000000); // 目标地址
SPI_SendData(flash_buffer, 12); // 发送12字节数据
SS4_HIGH();
}
调试过程与问题分析:在首次调试时,发现第2个温度传感器的数据始终为0xFFFFFFFF(MAX31855的故障标志)。使用逻辑分析仪抓取波形后发现,SS2拉低后,MISO线上没有数据返回。进一步检查硬件,发现PA5引脚虚焊,导致SS2信号未真正到达传感器。重新焊接后,通信恢复正常。
复盘经验:
- 多从机系统调试时,建议先用逻辑分析仪确认每个SS引脚的时序是否正确,再检查数据线。
- SPI通信的故障排查顺序应为:供电 → 片选 → 时钟 → 数据线 → 软件配置。
- 在硬件设计时,每个从设备的SS引脚建议串联一个10kΩ上拉电阻,防止上电瞬间SS电平不确定导致误触发。