2、SPI协议基础:深入理解SPI总线的工作原理、四种工作模式、时序图以及优缺点

好,咱们今天来聊聊SPI。说实话,在嵌入式世界里,SPI和I2C就像一对老搭档,几乎每个工程师都绕不开。我个人习惯把SPI叫做“四线制闪电”,因为它速度快、结构简单,用起来特别爽快。但爽归爽,坑也不少。我当年刚入行时,就因为搞混了SPI的四种模式,调了整整两天才找到问题。嗯,咱们今天就把SPI彻底讲透。

2.1 SPI总线的工作原理

SPI的全称是Serial Peripheral Interface,串行外设接口。它由Motorola公司提出,后来成了事实标准。你想想看,它为什么叫“四线制”?因为核心信号线就四条:

  • SCLK(Serial Clock):时钟线,由主机产生
  • MOSI(Master Out Slave In):主机输出,从机输入
  • MISO(Master In Slave Out):主机输入,从机输出
  • CS(Chip Select):片选线,低电平有效

说白了,SPI就是一个全双工的同步通信协议。主机和从机之间,可以同时发送和接收数据。这一点比I2C强,I2C是半双工的,同一时间只能一个方向传数据。

核心要点:SPI的通信由主机控制时钟。没有时钟,就没有数据传输。主机想跟谁说话,就把谁的CS拉低,然后开始产生时钟脉冲。每次时钟跳变,双方各送出一位,同时各接收一位。

我在项目中遇到过一种情况:一个主机挂了三个SPI从机,分别是ADC、DAC和Flash。如果CS控制不好,比如释放时机不对,从机之间就会互相干扰。嗯,这里要注意:CS拉高后,必须留一点时间让从机完成内部处理,否则下次通信可能出错。

2.2 四种工作模式(CPOL和CPHA)

SPI的四种模式,其实是两个参数的组合:CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)。

  • CPOL:决定时钟空闲时的电平。CPOL=0,空闲低电平;CPOL=1,空闲高电平。
  • CPHA:决定数据在哪个时钟边沿采样。CPHA=0,第一个边沿采样;CPHA=1,第二个边沿采样。

你想想看,两个参数各有两个取值,组合起来就是四种模式。我刚开始学的时候,总觉得这玩意儿很抽象。后来我画了个时序图,一下子就明白了。

模式 CPOL CPHA 空闲时钟电平 数据采样边沿
模式0 0 0 低电平 上升沿
模式1 0 1 低电平 下降沿
模式2 1 0 高电平 下降沿
模式3 1 1 高电平 上升沿

我的小技巧:大多数SPI Flash和SD卡都工作在模式0或模式3。我个人习惯默认用模式0,因为上升沿采样、下降沿切换,逻辑上最自然。但如果从机手册明确写了模式,一定要按手册来,别自作聪明。

2.3 时序图详解

光说理论不够,咱们来看个实际的时序图。以模式0为例:

SCLK:  ▔▁▔▁▔▁▔▁▔▁▔▁▔▁▔▁
       ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑
       (采样点)
MOSI:  X──D7──D6──D5──D4──D3──D2──D1──D0──X
MISO:  X──D7──D6──D5──D4──D3──D2──D1──D0──X
CS:    ▔▁____________________________▁▔

看到了吗?在模式0下:

  • CS拉低,通信开始
  • SCLK空闲为低电平
  • 数据在SCLK的上升沿被采样
  • 数据在SCLK的下降沿被切换
  • CS拉高,通信结束

为什么会这样设计?因为上升沿采样可以保证数据在时钟跳变时已经稳定。你想想看,如果在下跳沿采样,数据可能还在变化中,容易采到毛刺。

我曾经踩过的坑:有一次调试一个温湿度传感器,怎么读都是0xFF。查了半天,发现从机要求模式3,而我配置的是模式0。CPOL和CPHA都反了,数据完全对不上。从那以后,我每次拿到新器件,第一件事就是看手册里的时序图,确认CPOL和CPHA。

2.4 SPI的优缺点

任何协议都有它的长处和短处。SPI也不例外。咱们客观地聊聊。

优点

  • 速度快:SPI没有地址字节、没有应答位,纯数据流。时钟可以跑到几十MHz甚至上百MHz。我做过一个项目,SPI时钟跑到了50MHz,传输一帧图像只需要几毫秒。
  • 全双工:同时收发,效率高。比如ADC采样和DAC输出可以同时进行。
  • 硬件简单:没有复杂的协议栈,没有仲裁机制。从机不需要地址,靠CS区分。
  • 灵活:数据位宽可以不是8位,可以是12位、16位,甚至任意长度。

缺点

  • 引脚多:每个从机需要一根独立的CS线。如果挂8个从机,就需要8+3=11根线。相比之下,I2C只需要两根线。
  • 没有流控:主机发多少,从机就得收多少。如果从机处理不过来,数据就丢了。I2C有时钟拉伸机制,可以慢下来等从机。
  • 没有应答机制:主机不知道从机是否收到了数据。如果从机没响应,主机只能靠超时来判断。
  • 距离受限:SPI不适合长距离传输。线一长,信号就容易失真。我试过用SPI传1米,结果数据全是错的。

总结一下:SPI适合片内或短距离的高速通信。如果你需要挂很多从机,或者需要长距离传输,I2C可能更合适。但如果你追求速度和全双工,SPI是不二之选。

2.5 实际开发中的注意事项

嗯,最后再分享几个实战经验:

  1. CS的释放时机:通信结束后,CS必须拉高。但拉高后,建议等至少半个时钟周期再拉低开始下一次通信。有些从机需要时间复位内部状态机。
  2. 时钟频率匹配:不是所有从机都能跑高速。我见过一个从机最高只支持1MHz,结果我配了10MHz,读出来的数据全是乱的。一定要看手册里的最大SCLK频率。
  3. 数据对齐:SPI的数据通常是MSB first(高位在前)。但有些器件是LSB first。如果搞反了,数据就颠倒了。我建议在初始化时,用0x55或0xAA做个回环测试,确认数据顺序正确。
  4. 电平匹配:如果主机是3.3V,从机是5V,需要加电平转换。直接连可能会烧坏IO口。我吃过这个亏,烧过一个ADC芯片,心疼了好几天。

我的调试习惯:先用逻辑分析仪抓波形,确认SCLK、MOSI、MISO和CS的时序对不对。如果波形对了,数据还不对,那就是配置问题。如果波形都不对,那就是硬件或驱动的问题。逻辑分析仪是SPI调试的神器,强烈推荐。

好了,SPI协议基础就讲到这里。下一章咱们会深入TC3xx的SPI模块,看看怎么配置寄存器、怎么用DMA传输。到时候我会带大家手写一个完整的SPI驱动。敬请期待!