4、SPI协议原理与电气特性:深入SPI的4线制(SCLK、MOSI、MISO、CS)、时钟极性(CPOL)和相位(CPHA)、数据帧格式、多从机连接方式

SPI(Serial Peripheral Interface,串行外设接口)由Motorola公司于20世纪80年代提出,是一种高速、全双工、同步的串行通信总线。在嵌入式系统与DSP(数字信号处理器)开发中,SPI凭借其极低的引脚开销(通常4根线)和极高的传输速率(可达数十Mbps乃至更高),成为连接ADC/DAC、Flash存储器、传感器、LCD驱动、SD卡以及各类外设芯片的首选接口之一。与I2C的地址寻址和UART的异步帧同步不同,SPI采用主从架构,由主机(Master)产生时钟并控制片选信号,从机(Slave)被动响应。本章将深入剖析SPI的4线制信号定义、时钟极性(CPOL)与相位(CPHA)的四种工作模式、数据帧格式的灵活配置,以及多从机连接时的拓扑选择与工程权衡,帮助开发者从原理层面建立扎实的驱动开发基础。

SPI 4线制主从连接与信号流向 主机 (Master) DSP / MCU SCLK MOSI MISO CS0 从机 (Slave) 外设芯片 SCLK MOSI MISO CS SCLK (时钟,主机→从机) MOSI (主出从入,主机→从机) MISO (主入从出,从机→主机) CS (片选,低电平有效,主机→从机) 数据帧格式 (8位示例) MSB (Bit7) → Bit6 → Bit5 → Bit4 → Bit3 → Bit2 → Bit1 → LSB (Bit0) 传输方向:先发送最高有效位,每个SCLK上升沿或下降沿采样1位,8个时钟周期完成1字节。 四种工作模式 (CPOL / CPHA) 模式0 (00): CPOL=0, CPHA=0 → 空闲低电平,上升沿采样 模式1 (01): CPOL=0, CPHA=1 → 空闲低电平,下降沿采样 模式2 (10): CPOL=1, CPHA=0 → 空闲高电平,下降沿采样 模式3 (11): CPOL=1, CPHA=1 → 空闲高电平,上升沿采样

上图展示了SPI最基础的4线制主从连接拓扑。SCLK由主机统一产生,作为同步时钟驱动整个数据传输过程;MOSI(Master Output Slave Input)承载主机到从机的数据流,MISO(Master Input Slave Output)承载从机到主机的数据流,二者同时工作构成全双工通道;CS(Chip Select)通常低电平有效,主机通过拉低特定从机的CS引脚来激活通信。值得注意的是,SPI没有内置应答机制和地址帧,所有通信的发起、时序控制、数据有效性验证完全依赖主机软件协议设计,这既是SPI高效的原因,也是驱动开发中容易出错的地方。

4.1 核心原理:4线制信号定义与电气特性

SPI的4根信号线各有明确的电气角色和时序约束。SCLK作为同步时钟,其频率决定了通信速率,典型范围从几百kHz到几十MHz,具体上限取决于从机芯片的额定参数和PCB走线质量。MOSI与MISO在SCLK的驱动下逐位传输数据,数据线的建立时间(Setup Time)和保持时间(Hold Time)必须满足从机数据手册的要求,否则采样可能出错。CS信号则起到“使能”作用——只有当CS被拉低时,从机才会将MISO线置于驱动状态并响应SCLK;CS拉高后,从机释放MISO线(通常为高阻态),多个从机可以共享MISO线而不会发生总线冲突。

从电气特性角度看,SPI接口通常采用CMOS电平(3.3V或1.8V),但部分工业级芯片支持5V耐压。驱动开发者在设计电路时需注意:

  • 电平匹配:若DSP为3.3V而外设芯片为5V,需使用电平转换芯片(如TXB0108)或开漏+上拉方案。
  • 信号完整性:高速SPI(≥10MHz)时,建议串联22Ω~33Ω的源端匹配电阻,抑制振铃。
  • 上拉电阻:CS和SCLK在空闲时应有确定电平,通常通过10kΩ上拉电阻保证高电平(或下拉保证低电平,取决于CPOL配置)。
  • MISO高阻态:当多个从机共享MISO时,未选中的从机必须输出高阻态,否则会拉低总线导致通信失败。

工程经验:在DSP的SPI驱动初始化代码中,务必先配置GPIO复用功能为SPI模式,再设置时钟极性和相位,最后使能SPI控制器。顺序颠倒可能导致总线电平冲突或首个字节丢失。例如在TI C2000系列DSP中,需要先写GPCTRL寄存器选择外设功能,再配置SPICCR和SPICTL寄存器。

4.2 判断方法:CPOL与CPHA的四种模式及采样点分析

CPOL(Clock Polarity,时钟极性)决定SCLK在空闲状态(无数据传输时)的电平:CPOL=0表示空闲低电平,CPOL=1表示空闲高电平。CPHA(Clock Phase,时钟相位)决定数据采样发生在SCLK的哪个边沿:CPHA=0表示在第一个边沿(即从空闲状态跳变的边沿)采样,CPHA=1表示在第二个边沿采样。组合起来形成四种模式,如下表所示:

模式 CPOL CPHA 空闲电平 采样边沿 数据变化边沿 典型应用
模式0 0 0 低 上升沿 下降沿 多数Flash、SD卡
模式1 0 1 低 下降沿 上升沿 部分传感器
模式2 1 0 高 下降沿 上升沿 某些音频编解码器
模式3 1 1 高 上升沿 下降沿 多数EEPROM、ADC

判断从机所需模式的实用方法:查阅芯片数据手册中的时序图(Timing Diagram),找到SCLK波形和数据线的采样指示。通常手册会标注“Data Setup Time”和“Data Hold Time”相对于哪个边沿。若手册标注“Data is latched on the rising edge of SCLK”且空闲电平为低,则对应模式0;若标注“Data is latched on the falling edge”且空闲为高,则对应模式2。另一种快速判断法:观察数据手册中MOSI波形在SCLK哪个边沿之后变化,若在上升沿之后变化、下降沿采样,则为模式0。

风险提示:配置错误的CPOL/CPHA不会导致硬件损坏,但会造成数据全部为0xFF或0x00,且难以排查。调试时建议先用逻辑分析仪抓取SCLK和MOSI波形,确认空闲电平和采样边沿是否与从机手册一致。切勿仅凭“感觉”猜测模式,务必以数据手册时序图为准。

4.3 数据帧格式:位宽、字节序与传输流程

SPI的数据帧格式灵活多样,最常见的为8位帧,但许多DSP的SPI控制器支持4~16位可编程帧长度。帧格式的关键参数包括:

  • 帧长度(Frame Length):一次CS有效期间传输的位数,常见8位、12位(ADC)、16位(DAC)。
  • 位序(Bit Order):MSB First(高位先发)或LSB First(低位先发)。绝大多数SPI外设默认MSB First,但部分芯片(如某些LCD控制器)要求LSB First。
  • 连续传输模式:当需要传输多字节时,主机可以保持CS为低,连续发送多个帧;或每帧之间拉高CS再拉低(非连续模式)。某些从机(如Flash)要求CS在整个命令+地址+数据序列期间保持低电平。

一个典型的8位SPI传输流程如下:

  1. 主机将CS拉低,从机被激活。
  2. 主机在SCLK的第一个有效边沿之前,将MOSI置为第1位数据(MSB)。
  3. 每个SCLK周期,主机在数据变化边沿更新MOSI,从机在采样边沿锁存;同时从机在MISO上输出数据,主机在采样边沿读取。
  4. 8个SCLK周期后,1字节传输完成。主机拉高CS,结束本次通信。
// 伪代码示例:DSP SPI发送1字节并接收1字节(模式0,8位帧)
uint8_t spi_transfer_byte(uint8_t tx_data) {
    SPI_DRV_DataReg = tx_data;  // 写入发送寄存器
    while (!(SPI_DRV_StatusReg & SPI_TX_EMPTY)); // 等待发送完成
    while (!(SPI_DRV_StatusReg & SPI_RX_FULL));  // 等待接收数据
    return SPI_DRV_DataReg;     // 读取接收寄存器
}

上述代码展示了最基本的轮询方式。实际驱动开发中,为提高效率,常使用DMA(直接内存访问)配合中断进行批量传输,此时需注意帧长度与DMA数据宽度的匹配(如16位帧对应DMA半字传输)。

4.4 多从机连接方式:独立片选与菊花链拓扑

当系统中存在多个SPI从机时,有两种主流连接方案:独立片选(Parallel CS)和菊花链(Daisy Chain)。

独立片选方式是最常见的拓扑。每个从机占用主机的一个GPIO作为CS引脚,所有从机共享SCLK、MOSI、MISO三根总线。主机通过拉低目标从机的CS来选中它,未选中的从机MISO输出高阻态。这种方式优点是:各从机完全独立,通信互不干扰,时序简单;缺点是:占用主机GPIO资源多(每增加一个从机需多一个CS引脚),且MISO总线的电容负载随从机数量增加而增大,高速通信时信号质量可能下降。

菊花链方式则将所有从机的MISO和MOSI串联起来,形成一个移位寄存器链。主机只需一个CS引脚控制所有从机,数据从第一个从机的MOSI输入,经过内部移位后从MISO输出到下一个从机的MOSI,依此类推。菊花链的优点是节省GPIO,适合从机数量多且对实时性要求不高的场景(如LED驱动、多通道DAC);缺点是:所有从机必须支持菊花链功能(通常数据手册会标注),且每次通信需要传输N×帧长度(N为从机数量)的数据,延迟增加,且任一从机故障会导致整条链路失效。

对比维度 独立片选 菊花链
GPIO占用 每从机1个CS 仅1个CS
通信延迟 低(直接寻址) 高(需传输N倍数据)
从机要求 无特殊要求 必须支持菊花链
故障隔离 好(单点故障不影响其他) 差(链路中断全盘失效)
典型应用 Flash、ADC、传感器混合系统 LED驱动、多通道DAC

4.5 案例拆解:基于DSP的SPI Flash驱动初始化与排障

以某工业控制板卡为例,DSP(TMS320F28379D)需要外接一颗SPI NOR Flash(型号W25Q64,支持模式0和模式3)。系统要求SPI时钟频率为20MHz,使用DMA方式读取Flash数据。开发过程中遇到以下问题:

初始现象:读取Flash的JEDEC ID(命令0x9F)时,返回数据为0xFFFFFF,明显异常。

分析过程:首先使用逻辑分析仪抓取SCLK、MOSI、MISO、CS波形,发现SCLK空闲电平为低,且数据在上升沿采样——这对应模式0。但W25Q64数据手册明确推荐模式0或模式3均可,问题不在此。进一步检查发现,DSP的SPI模块初始化时,GPIO复用配置正确,但SPI时钟分频系数设置错误:DSP主频200MHz,期望20MHz,分频系数应设为10,但代码中误写为5,导致实际SCLK为40MHz,超出Flash最高支持频率(通常为33MHz或50MHz,但高速下时序裕量不足)。

实际操作步骤:

  1. 修正SPI时钟分频系数,将SCLK降至20MHz。
  2. 检查CS信号时序:W25Q64要求CS拉低后至少等待tCSSU(CS setup time,通常100ns)才能发送第一个时钟,DSP的SPI控制器默认满足,但若使用GPIO模拟CS,需在代码中插入延时。
  3. 验证DMA配置:DMA源地址指向SPI接收寄存器,目的地址为内存缓冲区,传输长度设为3字节(JEDEC ID为3字节)。发现DMA触发条件配置错误,改为“接收FIFO非空”触发。
  4. 重新测试,读取到JEDEC ID为0xEF4017,与W25Q64手册一致。

结果对比:修复前读取数据全为0xFF,修复后正确读取ID。进一步测试Flash擦除、写入、读取回环,均正常。

复盘经验:SPI驱动开发中,时钟频率、CPOL/CPHA、CS时序、DMA触发条件是四大关键点。建议在驱动初始化后,先执行“读ID”自检命令,确认通信链路正常后再进行复杂操作。此外,逻辑分析仪是SPI调试的必备工具,能直观显示时序关系。

经验提醒:当SPI通信异常时,按以下顺序排查:① 用万用表确认SCLK、MOSI、MISO、CS电平是否正常(有无短路、断路);② 用逻辑分析仪抓取波形,确认CPOL/CPHA是否匹配;③ 检查时钟频率是否在从机允许范围内;④ 检查CS时序是否满足从机要求;⑤ 检查数据帧格式(位宽、位序)是否一致。

4.6 常见误区与总结复盘

在SPI驱动开发中,以下误区值得特别注意:

  • 误区一:所有SPI从机都支持模式0。实际上,部分传感器(如某些温湿度传感器)仅支持模式3,配置错误会导致通信失败。
  • 误区二:CS拉低后立即发送数据。许多从机要求CS拉低后等待一定时间(tCSSU)才能开始时钟,否则首个字节可能丢失。
  • 误区三:忽略MISO高阻态。当多个从机共享MISO时,未选中的从机必须输出高阻态,否则会拉低总线。某些从机芯片的MISO引脚在CS为高时自动高阻,但有些需要外部上拉电阻配合。
  • 误区四:帧长度不匹配。DSP的SPI控制器可能默认8位帧,但外设要求16位帧(如某些DAC),导致数据错位。
  • 误区五:忽略字节序。部分外设要求LSB First,若DSP配置为MSB First,则所有数据位序颠倒。

总结而言,SPI协议的精髓在于“主控一切”:时钟由主机产生,通信由主机发起,时序由主机保证。驱动开发者的核心任务就是精确匹配从机的时序要求。建议在项目初期建立一张“SPI外设参数表”,记录每个从机的CPOL/CPHA、最大时钟频率、帧长度、位序、CS时序要求等关键参数,作为驱动开发的对照清单。同时,编写通用的SPI底层驱动接口(如spi_init、spi_transfer、spi_transfer_dma),将不同外设的差异通过配置结构体隔离,可大幅提高代码复用性和可维护性。