1. 串行通信协议的三国演义从业十年我调试过的通信接口能绕实验室三圈。每当新人问我SPI、UART、I2C到底怎么选我都会先带他们看这张对比表特性UARTI2CSPI信号线数量2线(TX/RX)2线(SCL/SDA)4线(SCLK/MOSI/MISO/SS)通信方式异步同步同步拓扑结构点对点多主多从一主多从最大速率12Mbps(USB转串口)5MHz(高速模式)50MHz硬件复杂度最低中等最高这张表背后藏着三个关键认知速率不是唯一指标SPI虽然快但占用引脚多I2C引脚少但需要上拉电阻同步/异步决定时钟策略UART需要双方约定波特率SPI/I2C由主机控制时钟拓扑结构影响系统设计I2C适合传感器网络SPI适合高速外设UART专注设备间对话2. UART简单可靠的异步通信老兵2.1 帧结构解析最近调试STM32与ESP8266的WiFi模块时示波器捕获到的典型UART帧如下[起始位0][数据位01000001][校验位1][停止位1]对应ASCII字符A的传输过程。关键细节起始位从高到低的跳变唤醒接收端数据位通常8位(LSB先发)也可配置5-9位校验位奇偶校验检测单比特错误停止位1-2个高电平作为帧间隔实测坑点当波特率误差超过3%时连续传输会出现错位。曾用11.0592MHz晶振给9600bps通信比12MHz晶振稳定10倍。2.2 流控实战去年做工业控制器项目时CPU通过UART向打印机发送数据出现过缓冲区溢出的惨案。后来用RTS/CTS硬件流控解决了问题接收方准备好时拉低RTS(Request To Send)发送方检测到CTS(Clear To Send)有效才发送数据通过MAX3485芯片实现3.3V与RS-485电平转换3. I2C优雅的双线制总线3.1 协议栈拆解用逻辑分析仪抓取AT24C02 EEPROM的读写时序时可见典型I2C事务包含START条件SCL高电平时SDA下降沿设备地址7位地址1位读写方向(0写/1读)应答位每字节后接收方拉低SDA数据帧SCL上升沿采样数据STOP条件SCL高电平时SDA上升沿3.2 多主竞争处理在智能家居项目中STM32与树莓派共享I2C总线时我们实现了冲突检测机制// 检测总线忙状态 HAL_I2C_IsDeviceReady(hi2c1, DEV_ADDR, 3, 100); // 仲裁失败处理 if (HAL_I2C_GetError(hi2c1) HAL_I2C_ERROR_AF) { // 释放总线并重试 __HAL_I2C_GENERATE_NACK(hi2c1); }4. SPI速度之王的代价4.1 四种模式详解为GD32F303驱动OLED屏时需要严格匹配SPI模式CPOL时钟极性(0空闲低电平1空闲高电平)CPHA时钟相位(0第一个边沿采样1第二个边沿采样)模式CPOLCPHA适用场景000多数传感器101SD卡初始化210某些RF模块311高速FLASH芯片4.2 DMA优化技巧使用STM32H743的SPI3接口以50MHz传输图像数据时传统轮询方式CPU占用率达70%。通过DMA优化后骤降至5%// 配置DMA流 hdma_tx.Instance DMA1_Stream5; hdma_tx.Init.Request DMA_REQUEST_SPI3_TX; HAL_DMA_Init(hdma_tx); // 启动传输 HAL_SPI_Transmit_DMA(hspi3, pData, Size);5. 选型决策树根据多年项目经验我总结出通信协议选择的五个维度速率需求低速配置(≤100kbps)I2C/UART中速传输(1-10Mbps)SPI高速数据(≥10Mbps)并行总线或SerDes设备数量单设备点对点UART多设备共享I2C(≤10个)/SPI(片选扩展)布线限制空间受限I2C(2线)引脚充足SPI(全双工优势)实时性要求严格时序SPI(主控时钟)宽松时序UART(异步)开发资源新手友好UART(调试简单)老手追求性能SPIDMA最近为医疗设备选择通信方案时就因EMC要求放弃了I2C——它的开漏输出在强干扰环境下不如SPI的推挽输出稳定。这个案例再次证明没有最好的协议只有最合适的场景。
SPI、UART、I2C串行通信协议对比与选型指南
1. 串行通信协议的三国演义从业十年我调试过的通信接口能绕实验室三圈。每当新人问我SPI、UART、I2C到底怎么选我都会先带他们看这张对比表特性UARTI2CSPI信号线数量2线(TX/RX)2线(SCL/SDA)4线(SCLK/MOSI/MISO/SS)通信方式异步同步同步拓扑结构点对点多主多从一主多从最大速率12Mbps(USB转串口)5MHz(高速模式)50MHz硬件复杂度最低中等最高这张表背后藏着三个关键认知速率不是唯一指标SPI虽然快但占用引脚多I2C引脚少但需要上拉电阻同步/异步决定时钟策略UART需要双方约定波特率SPI/I2C由主机控制时钟拓扑结构影响系统设计I2C适合传感器网络SPI适合高速外设UART专注设备间对话2. UART简单可靠的异步通信老兵2.1 帧结构解析最近调试STM32与ESP8266的WiFi模块时示波器捕获到的典型UART帧如下[起始位0][数据位01000001][校验位1][停止位1]对应ASCII字符A的传输过程。关键细节起始位从高到低的跳变唤醒接收端数据位通常8位(LSB先发)也可配置5-9位校验位奇偶校验检测单比特错误停止位1-2个高电平作为帧间隔实测坑点当波特率误差超过3%时连续传输会出现错位。曾用11.0592MHz晶振给9600bps通信比12MHz晶振稳定10倍。2.2 流控实战去年做工业控制器项目时CPU通过UART向打印机发送数据出现过缓冲区溢出的惨案。后来用RTS/CTS硬件流控解决了问题接收方准备好时拉低RTS(Request To Send)发送方检测到CTS(Clear To Send)有效才发送数据通过MAX3485芯片实现3.3V与RS-485电平转换3. I2C优雅的双线制总线3.1 协议栈拆解用逻辑分析仪抓取AT24C02 EEPROM的读写时序时可见典型I2C事务包含START条件SCL高电平时SDA下降沿设备地址7位地址1位读写方向(0写/1读)应答位每字节后接收方拉低SDA数据帧SCL上升沿采样数据STOP条件SCL高电平时SDA上升沿3.2 多主竞争处理在智能家居项目中STM32与树莓派共享I2C总线时我们实现了冲突检测机制// 检测总线忙状态 HAL_I2C_IsDeviceReady(hi2c1, DEV_ADDR, 3, 100); // 仲裁失败处理 if (HAL_I2C_GetError(hi2c1) HAL_I2C_ERROR_AF) { // 释放总线并重试 __HAL_I2C_GENERATE_NACK(hi2c1); }4. SPI速度之王的代价4.1 四种模式详解为GD32F303驱动OLED屏时需要严格匹配SPI模式CPOL时钟极性(0空闲低电平1空闲高电平)CPHA时钟相位(0第一个边沿采样1第二个边沿采样)模式CPOLCPHA适用场景000多数传感器101SD卡初始化210某些RF模块311高速FLASH芯片4.2 DMA优化技巧使用STM32H743的SPI3接口以50MHz传输图像数据时传统轮询方式CPU占用率达70%。通过DMA优化后骤降至5%// 配置DMA流 hdma_tx.Instance DMA1_Stream5; hdma_tx.Init.Request DMA_REQUEST_SPI3_TX; HAL_DMA_Init(hdma_tx); // 启动传输 HAL_SPI_Transmit_DMA(hspi3, pData, Size);5. 选型决策树根据多年项目经验我总结出通信协议选择的五个维度速率需求低速配置(≤100kbps)I2C/UART中速传输(1-10Mbps)SPI高速数据(≥10Mbps)并行总线或SerDes设备数量单设备点对点UART多设备共享I2C(≤10个)/SPI(片选扩展)布线限制空间受限I2C(2线)引脚充足SPI(全双工优势)实时性要求严格时序SPI(主控时钟)宽松时序UART(异步)开发资源新手友好UART(调试简单)老手追求性能SPIDMA最近为医疗设备选择通信方案时就因EMC要求放弃了I2C——它的开漏输出在强干扰环境下不如SPI的推挽输出稳定。这个案例再次证明没有最好的协议只有最合适的场景。