嵌入式通信协议UART、I2C、SPI对比详解
笔记 / 嵌入式
引言
在嵌入式系统中,通信协议是各模块之间对话的语言。UART、I2C 和 SPI 是最常用的三种串行通信协议——它们各自有着鲜明的性格特点,适用的场景也截然不同。理解它们的差异,是选择正确协议的前提。
一、UART —— 异步通信的经典
基本原理
UART(Universal Asynchronous Receiver/Transmitter)是一种异步、全双工、点对点的串行通信协议。它不需要共享时钟信号,通信双方通过预先约定相同的波特率来同步。
硬件连接
- 最少 2 根线:TX(发送)、RX(接收)
- 可选硬件流控:RTS、CTS
数据帧格式
┌─────────┬──────────────────┬──────────┬──────────┐
│ 起始位 │ 数据位(5~9位) │ 校验位 │ 停止位 │
│ (1位) │ (通常8位) │ (可选) │ (1/2位) │
└─────────┴──────────────────┴──────────┴──────────┘
- 起始位:数据线从高拉低,通知接收方开始传输
- 数据位:5~9 位(通常 8 位),LSB 先发
- 奇偶校验位:可选,用于错误检测
- 停止位:将数据线拉高,持续 1 位或 2 位时间
优缺点
| 优点 | 缺点 |
|---|---|
| 仅需 2 根线,简单易用 | 仅支持点对点通信 |
| 无需时钟信号 | 数据帧最大 9 位 |
| 有奇偶校验位 | 两端波特率偏差不能超过约 10% |
| 可扩展为 RS-232/RS-485 | 速度较慢(通常 ≤ 115200 bps) |
二、I²C —— 多设备总线的优雅
基本原理
I²C(Inter-Integrated Circuit)是一种同步、半双工、多主多从的串行通信协议。它通过地址寻址方式选择通信目标设备。
硬件连接
- 仅 2 根线:SDA(数据)、SCL(时钟)
- 两条线都需要上拉电阻(通常 4.7KΩ)
- 总线为开漏输出设计,支持多设备共享
通信时序
┌──────────────────────────────────────────────────────────────┐
│ 起始条件 │ 从机地址(7/10位)+R/W位 │ ACK │ 数据帧 │ ACK │ ... │ 停止条件 │
└──────────────────────────────────────────────────────────────┘
- 起始条件:SCL 高电平时,SDA 由高→低
- 停止条件:SCL 高电平时,SDA 由低→高
- 地址帧:7 位或 10 位从机地址 + 1 位读写位
- ACK/NACK:接收方拉低 SDA 表示确认
优缺点
| 优点 | 缺点 |
|---|---|
| 仅需 2 根线 | 速度比 SPI 慢 |
| 支持多主多从架构 | 数据帧固定 8 位 |
| 内置 ACK/NACK 确认 | 协议复杂度较高 |
| 地址寻址,节省 GPIO | 通信距离短(通常板内) |
三、SPI —— 高速通信的王者
基本原理
SPI(Serial Peripheral Interface)是一种同步、全双工、主从架构的串行通信协议。它通过**片选信号(CS)**来选择通信目标。
硬件连接
- 4 根线:
- SCLK/SCK:时钟线(主机产生)
- MOSI:主机输出、从机输入
- MISO:主机输入、从机输出
- SS/CS:片选信号(每个从机一条独立线)
4 种工作模式
| 模式 | CPOL | CPHA | 说明 |
|---|---|---|---|
| 模式 0 | 0 | 0 | 空闲时钟低,第一个边沿采样(最常用) |
| 模式 1 | 0 | 1 | 空闲时钟低,第二个边沿采样 |
| 模式 2 | 1 | 0 | 空闲时钟高,第一个边沿采样 |
| 模式 3 | 1 | 1 | 空闲时钟高,第二个边沿采样 |
传输过程
- 主机输出时钟信号
- 主机拉低目标从机的 CS 引脚,激活从机
- 主机通过 MOSI 发送数据,同时从机通过 MISO 返回数据(全双工)
- 传输完成后,主机拉高 CS 释放从机
优缺点
| 优点 | 缺点 |
|---|---|
| 速度最快(10~50 MHz) | 需要 4 根线,每增加从机多一根 CS |
| 全双工,可同时收发 | 无内置错误检测和确认机制 |
| 无起始/停止位,数据可连续流 | 不支持多主机 |
| 协议简单 | 无标准协议层 |
四、三大协议全面对比
| 特性 | UART | I²C | SPI |
|---|---|---|---|
| 通信方式 | 异步 | 同步 | 同步 |
| 双工模式 | 全双工 | 半双工 | 全双工 |
| 信号线数 | 2 根 | 2 根 | 4 根 |
| 拓扑结构 | 点对点 | 多主多从 | 单主多从 |
| 设备选择 | 无(仅一对) | 地址寻址 | 片选信号 CS |
| 典型速率 | 9.6K~115.2K bps | 100K/400K/3.4M bps | 10M~50M bps |
| 数据帧大小 | 5~9 位 | 固定 8 位 | 无限制(连续传输) |
| 错误检测 | 奇偶校验位 | ACK/NACK | 无内置 |
| 通信距离 | 较长(RS-485 可达千米) | 短(板内 <1m) | 短(<0.5m) |
| 复杂度 | 中等 | 较高 | 简单 |
五、选型指南 —— 什么时候选谁?
🟢 选 UART 的场景
- 调试与日志输出:嵌入式开发中最常用的调试手段
- PC 与 MCU 通信:通过 USB 转串口连接
- GPS/GSM/蓝牙模块:点对点无线通信模块
- 工业远距离通信:配合 RS-232/RS-485 电平转换
🔵 选 I²C 的场景
- 多传感器网络:温湿度传感器(SHT30)、气压传感器(BMP280)
- EEPROM 存储:AT24Cxx 系列
- RTC 实时时钟:DS3231、PCF8563
- GPIO 扩展/ADC/DAC:需要节省引脚资源
- OLED 小屏幕:SSD1306 等
🔴 选 SPI 的场景
- 高速数据存储:NOR Flash(W25Qxx)、SD 卡
- TFT 彩屏驱动:ST7789、ILI9341
- 高速 ADC/DAC:音频采集、高速采样
- WiFi 模块:部分高速无线模块
六、总结口诀
速度排名: SPI >> I²C > UART
引脚数量: SPI(4+) > UART(2~4) > I²C(2)
设备扩展: I²C(地址寻址) > SPI(片选) > UART(仅点对点)
协议复杂度:I²C > UART > SPI
通信距离: UART(远) >> I²C(短) ≈ SPI(短)
可靠性: I²C(ACK) > UART(校验) > SPI(无内置)
没有最好的协议,只有最合适的协议。在实际项目中,三种协议往往是配合使用的——用 UART 调试通信,用 I²C 挂载传感器,用 SPI 驱动屏幕和存储。各取所长,才是正道。