先看一个反差。
I2C有标准协议文档。Philips(飞利浦半导体,现NXP)在1982年发布了第一版I2C规范,定义了从机地址分配、速率等级、应答机制、时钟拉伸、多主机仲裁等一整套规则。你想实现一个符合标准的I2C外设,必须遵循这份几百页的文档。每一代升级——从标准模式到快速模式到高速模式——都有明确的电气参数和时序要求。
UART也有标准。虽然它的协议层极其简单(起始位、数据位、停止位),但电气层有EIA制定的RS-232、RS-422、RS-485标准。这些标准规定了电压范围、驱动能力、共模抑制、端接阻抗等物理参数。你不一定需要看这些标准来写代码,但硬件工程师在设计收发器时必须遵循它们。
SPI呢?SPI没有标准协议文档。
Motorola在1980年代推出SPI接口时,没有发布过一份类似"I2C Bus Specification"的权威规范。你找不到一份由某个标准化组织或创始公司维护的、定义了SPI所有行为边界和技术参数的官方文档。SPI不是一个"标准",它是Motorola在其微控制器上实现的一种接口,然后被整个工业界模仿、扩展、变形,最终形成了一个"约定俗成"的事实标准。
这篇文章不讲SPI怎么用,只讲一个更有趣的问题:一个没有标准文档的接口,凭什么活成了事实标准?
一、SPI的"定义"到底有多简陋?
SPI的核心定义可以用四句话说完:
• 主机产生时钟信号(SCK),从机接收时钟信号。 • 主机通过MOSI线发送数据,从机通过MISO线发送数据。 • 主机通过拉低SS线选择目标从机。 • 数据在时钟边沿上被采样和更新。
这就是SPI的全部协议层定义。它没有定义:
• 数据帧格式:一帧是多少位?8位?16位?32位?随意。SPI不规定数据字长,外设自己决定。有些SPI Flash用8位命令加24位地址,总共32位一帧。有些ADC用16位一帧。有些DAC用12位。主机和外设之间的约定是点对点的,不需要标准来统一。 • 命令结构:SPI没有定义"命令"和"数据"的区分。不像I2C有明确的"写地址+寄存器+数据"结构,SPI只是把数据从主机搬到从机。数据的第一字节是命令还是地址还是纯数据,完全由从机决定。 • 速率范围:SPI没有定义标准速率等级。I2C有标准模式(100kHz)、快速模式(400kHz)、高速模式(3.4MHz)。SPI没有。从机数据手册说它能跑到多少就是多少,主机把SCK频率调到那个值以下就行。 • 电气特性:SPI没有定义电压范围、驱动强度、输入阈值。这些参数跟随芯片的通用IO电气特性。3.3V的MCU和5V的传感器连SPI,需要自己确认电平兼容性。 • 应答机制:SPI没有ACK。主机发出一串时钟,从机是否收到了数据、数据是否正确,SPI协议层完全不管。如果需要确认,只能在应用层用特定字节或CRC来做。 • 错误检测:SPI没有帧错误、没有校验位、没有超时机制。通信失败时,主机和从机都不会在协议层收到任何错误通知。
这不是一个"标准"。这是一个最小化的、没有冗余的物理层管道。
二、为什么"简陋"反而成了优势?
换个角度看问题。如果你设计一个协议,要求它被尽可能多的外设采用,你会怎么做?
一种做法是把所有可能的需求都纳入标准,让协议足够全面,能覆盖所有场景。I2C就是这条路——它定义了速率等级、地址分配、仲裁机制、时钟拉伸,试图用一套规则解决板内中低速总线的所有问题。
另一种做法是什么都不定义,把决策权交给外设设计者。SPI就是这条路。
"简陋"带来的不是功能的缺失,而是灵活性。
当一个芯片设计团队决定给他们的传感器加一个串行接口时,他们有两种选择。
选择I2C:需要申请从机地址,实现完整的I2C状态机(起始条件检测、地址匹配、ACK生成、时钟拉伸逻辑、停止条件检测),遵守速率等级的时序约束,通过I2C合规性测试。如果他们的传感器有一些非标准需求——比如需要连续读取100字节而不希望每字节都发ACK——I2C协议不允许这么干。
选择SPI:只需要一个移位寄存器、一个时钟输入、一个SS输入。数据字长自己定,命令格式自己定,速率自己定。不需要申请任何地址,不需要兼容任何标准。唯一的要求是:主机的SPI外设配置成和从机一致的模式和速率。
对于外设设计者来说,SPI意味着零合规成本。你不需要阅读几百页的协议文档,不需要参加兼容性测试,不需要向任何标准化组织交钱申请地址。你只需要在你的数据手册里写清楚:这个芯片用SPI模式0,最高时钟20MHz,命令格式如下。
这就是SPI成为事实标准的核心原因:它不是被一个委员会设计出来的,而是被一群芯片设计师"用脚投票"选出来的。 每一个选择加SPI接口的芯片,都在为SPI的生态添砖加瓦。而它们选择SPI的原因,不是因为SPI更好,而是因为SPI更简单——对自己简单,对用户也简单。
三、SPI缺失的每一项功能,都有一个"不是bug"的解释
现在我们逐个分析SPI缺失的每一项功能,看看没有它们,SPI是怎么工作的。
没有地址。 I2C需要7位或10位从机地址来区分总线上的不同设备。SPI用SS线做物理寻址——一根线连一个从机。没有地址冲突,不需要地址分配,不需要担心两个从机地址相同。代价是主机要为每个从机多出一根SS线。但在板内通信场景下,GPIO引脚是充裕的——一个MCU有几十个GPIO,拿出五个做片选完全不是问题。SPI用引脚数量换了地址管理的复杂度,在板上场景下是合算的。
没有ACK。 I2C的ACK机制让发送方知道接收方确实收到了数据。SPI没有ACK,主机发出一串时钟,从机是否在正确的位置收到了正确的值,主机完全不知道。这听起来像是严重的设计缺陷。但在实际使用中,SPI的数据完整性由更高的层级保证——比如在命令帧后面附加CRC,或者在传输结束后回读状态寄存器确认。为什么不在协议层直接做ACK?因为ACK意味着每一帧都要等一个确认周期,这降低了吞吐量。SPI的设计哲学是:用最快的速度把数据搬完,正确性校验让上层决定。很多SPI传感器在连续读取模式下,ACK反而会成为瓶颈——主机不想在每字节后等待确认,它想连续读出100字节然后统一校验。
没有标准速率。 I2C的速率等级(100kHz、400kHz、3.4MHz)让主机知道"我应该用多快"。SPI没有。主机需要查从机数据手册,找到"最大SCK频率"这个参数,然后配一个低于它的值。这比I2C多了一步查手册的动作,但换来了更大的灵活性——从机可以跑在任意频率上,从几百kHz到几十MHz,没有一个"标准等级"的限制。你的从机能跑33MHz?配33MHz就好,不需要等SPI 2.0标准定义"超高速模式"。
没有电气标准。 I2C规定了开漏输出、上拉电阻、输入阈值和输出驱动能力。SPI没有这些规定。SPI的电气特性通常跟随芯片的CMOS IO标准——推挽输出,轨到轨摆幅。这意味着两个3.3V芯片之间的SPI连接,电气层是天然兼容的。不需要上拉电阻,不需要电平转换电路(除非电压域不同)。这个"没有标准"的特性,恰好让SPI在同一电压域的板内通信中极其简单。
四、SPI的"标准化"发生在数据手册里,而不是协议文档里
没有标准协议文档,并不意味着SPI是混乱的。
SPI的事实标准化,发生在每一个芯片的数据手册里。当一个传感器厂商写下"支持SPI模式0,CPOL=0,CPHA=0,最大SCK频率20MHz"时,他们就在定义这个设备在SPI生态中的行为规范。
这种"去中心化"的标准化方式有一个巨大的优势:规则的制定者是最了解这个设备的人——芯片设计者自己。
I2C的标准化是"自上而下"的。NXP定义规则,所有I2C设备必须遵守。当新的需求出现时(比如更快的速率、更低的功耗),必须先修改标准文档,然后所有设备再跟着升级。这个过程缓慢且充满妥协——标准委员会里的每个成员都有自己的利益诉求。
SPI的标准化是"自下而上"的。每个芯片定义自己的SPI行为。如果一个传感器厂商决定使用48位命令帧、双边沿采样(DDR模式)、50MHz时钟,它不需要说服任何标准委员会。它只需要在自己的数据手册里写清楚,然后确保主机的SPI外设能配置成相应的模式。如果主机的SPI外设不支持双边沿采样,那是主机的问题——用户会选择更灵活的MCU,或者用GPIO模拟SPI时序。
这种灵活性的代价是:用户在使用一个新SPI外设时,必须仔细阅读数据手册。 你不能像I2C那样"挂上去就能通信",你需要确认模式、速率、字长、命令格式。但在嵌入式开发中,阅读数据手册本来就是工程师的日常工作。这个代价是分散的、可管理的。
五、为什么I2C没有因为SPI的存在而消亡?
SPI这么好,为什么还需要I2C?
因为SPI的"简陋"在另一种场景下是劣势。
当你的PCB上有十个外设——六个传感器、两个EEPROM、一个RTC、一个温度计——都要挂到同一个MCU上时。如果用标准SPI共享总线的方式,所有从机共用SCK、MOSI、MISO三根线,但每个从机独占一根SS片选线。十个从机就需要 10根SS + 3根总线 = 共13根线。MCU需要拿出10个GPIO做片选,PCB需要走13根信号线。
如果速率极高、共享总线出现信号完整性问题(比如SCK的扇出过大导致边沿退化,或者多个从机的MISO并联导致容性负载过大、信号边沿退化),可能需要分成多组SPI总线,引脚数还会进一步增加。虽然通常不会夸张到给每个从机都配独立时钟和数据线,但相比I2C的两根线就能挂所有设备,引脚开销仍然明显更大。
这时候I2C的优势就凸显了:两根线,挂所有设备。不需要额外的SS线,不需要为每个从机分配GPIO。用地址区分设备,用ACK确保可靠传输,用时钟拉伸处理慢速设备。
SPI适合"少设备、高速率"的场景。I2C适合"多设备、中低速率"的场景。它们不是竞争对手,而是在同一个系统中共存、各司其职。
六、事实标准的本质
SPI的故事告诉我们一件事:一个技术是否成为标准,和它是否有标准文档无关。
标准文档能保证一致性。但没有标准文档,不代表没有标准。SPI的标准在哪里?在每一个SPI外设的数据手册里,在每一个MCU的SPI外设寄存器的定义里,在几十年来无数工程师的设计习惯里。
这些"约定俗成"构成了一个比任何书面标准都更强大的事实标准。它不是被设计出来的,而是被使用出来的。每一个选择SPI的芯片设计者,每一个配置SPI的嵌入式工程师,都在用自己的选择投票。
SPI没有标准协议文档,但它也不需要。它足够简单——简单到任何工程师用四根线就能实现,简单到任何芯片设计者用一个移位寄存器就能支持,简单到不需要一个权威组织来告诉你"这样用是对的"。
在工程世界里,最持久的往往不是设计最精巧的那个,而是简单到让所有人觉得"我也可以"的那个。SPI就是这样活成了事实标准。
夜雨聆风