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线制主从连接拓扑。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传输流程如下:
- 主机将CS拉低,从机被激活。
- 主机在SCLK的第一个有效边沿之前,将MOSI置为第1位数据(MSB)。
- 每个SCLK周期,主机在数据变化边沿更新MOSI,从机在采样边沿锁存;同时从机在MISO上输出数据,主机在采样边沿读取。
- 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,但高速下时序裕量不足)。
实际操作步骤:
- 修正SPI时钟分频系数,将SCLK降至20MHz。
- 检查CS信号时序:W25Q64要求CS拉低后至少等待tCSSU(CS setup time,通常100ns)才能发送第一个时钟,DSP的SPI控制器默认满足,但若使用GPIO模拟CS,需在代码中插入延时。
- 验证DMA配置:DMA源地址指向SPI接收寄存器,目的地址为内存缓冲区,传输长度设为3字节(JEDEC ID为3字节)。发现DMA触发条件配置错误,改为“接收FIFO非空”触发。
- 重新测试,读取到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),将不同外设的差异通过配置结构体隔离,可大幅提高代码复用性和可维护性。