1. 四大通信协议核心对比图
先来看这张对比表格,5秒钟就能抓住关键差异:
| 协议 | 硬件接线 | 通信方式 | 典型速度 | 最大设备数 | 典型应用场景 |
|---|---|---|---|---|---|
| UART | TX/RX/GND | 异步全双工 | 115.2kbps | 1对1 | 调试终端、GPS模块 |
| I2C | SCL/SDA | 同步半双工 | 100kbps-3.4Mbps | 理论128个 | 温湿度传感器 |
| SPI | MOSI/MISO/SCLK/CS | 同步全双工 | 50Mbps+ | 无理论限制 | OLED屏幕、Flash存储 |
| CAN | CAN_H/CAN_L | 异步半双工 | 1Mbps | 理论110个 | 汽车ECU、工业控制 |
我第一次接触这些协议时,最头疼的就是记不清它们的硬件连接方式。后来发现用生活场景类比特别管用:
- UART就像两个人打电话,必须一对一连接
- I2C像微信群聊,一个群主(@主设备)可以@多个成员
- SPI像快递柜,每个柜子(从设备)有独立取件码(CS片选)
- CAN则像紧急广播,重要通知(高优先级报文)可以打断普通通话
2. UART:最古老的串口协议
2.1 硬件连接与工作原理
UART的硬件接线简单到令人发指——只需要交叉连接TX和RX,再加根地线。我在调试树莓派时,经常用USB转TTL模块这样连接:
# 查看Linux系统串口设备 ls /dev/ttyUSB* # 用minicom调试 minicom -D /dev/ttyUSB0 -b 115200但要注意电平标准:
- TTL电平:3.3V/5V(单片机常用)
- RS232:±15V(老式电脑串口)
- RS485:差分信号(工业现场)
2.2 帧格式与波特率
一个标准的UART数据帧包含:
- 起始位(总是低电平)
- 5-8位数据(LSB先发)
- 可选的奇偶校验位
- 1-2位停止位(高电平)
常见波特率有4800、9600、115200等。这里有个坑:我曾经因为设备双方波特率设置不一致,收到一堆乱码。建议用示波器测量实际波形确认:
理想波形:_-----___--_ (起始位+01000001+停止位) 异常波形:_---_-_---_ (波特率不匹配时)3. I2C:优雅的总线协议
3.1 多设备连接方案
I2C总线的精髓在于7位设备地址。比如MPU6050陀螺仪的地址是0x68,AT24C02 EEPROM是0x50。接线时所有设备的SCL和SDA分别并联,就像这样:
Master | |-- SCL -- Sensor1 (0x68) | |-- Sensor2 (0x50) | |-- SDA -- Sensor1 |-- Sensor2实际项目中遇到过地址冲突的问题——两个相同型号的传感器默认地址相同。解决方法要么改硬件地址引脚,要么用I2C多路复用器(如TCA9548A)。
3.2 通信时序解析
用逻辑分析仪抓取的典型I2C波形:
START -- 地址+W -- ACK -- 数据 -- ACK -- STOP \________ 单次传输 ________/特殊机制:
- 时钟拉伸:从设备可以拉低SCL来请求等待
- 重复起始位:在不释放总线的情况下开始新传输
- 10位地址:扩展地址空间(较少使用)
4. SPI:速度之王
4.1 四种工作模式
SPI的模式由CPOL和CPHA决定:
| 模式 | CPOL | CPHA | 采样时刻 |
|---|---|---|---|
| 0 | 0 | 0 | 上升沿 |
| 1 | 0 | 1 | 下降沿 |
| 2 | 1 | 0 | 下降沿 |
| 3 | 1 | 1 | 上升沿 |
比如W25Q128 Flash芯片用的是Mode 3。配置错误会导致数据错位,我有次把Mode 0设成Mode 3,读出的ID全是0xFF。
4.2 实战技巧
- 片选管理:Linux下用gpiod控制CS引脚更可靠
// 手动控制CS示例 struct gpiod_chip *chip = gpiod_chip_open("/dev/gpiochip0"); struct gpiod_line *cs = gpiod_chip_get_line(chip, 17); gpiod_line_request_output(cs, "SPI_CS", 1);- 速度优化:DMA传输能突破CPU瓶颈
- 信号完整:超过10MHz时要考虑阻抗匹配
5. CAN:工业级可靠性
5.1 差分信号优势
CAN总线用CAN_H和CAN_L的电压差表示数据:
- 显性电平(逻辑0):CAN_H - CAN_L > 1.5V
- 隐性电平(逻辑1):电压差≈0V
这种设计让CAN在工厂环境中抗干扰能力极强。实测发现,即使其中一根线断路,网络仍能工作(速率下降)。
5.2 报文优先级机制
CAN的仲裁域包含11位标识符(标准帧),数值越小优先级越高。这就像急诊科分诊——心跳骤停(高优先级报文)可以插队处理。
过滤设置示例(SocketCAN):
# 只接收ID为0x123的报文 candump can0,123:7FF6. 协议选型指南
6.1 成本敏感型场景
- 最低成本方案:UART(2根线)
- 中等成本:I2C(需上拉电阻)
- 不考虑成本:SPI+硬件CS控制
6.2 速率需求对照
| 需求 | 推荐协议 |
|---|---|
| <100kbps | I2C/UART |
| 100k-1Mbps | SPI |
| >1Mbps | SPI+ DMA |
| 长距离可靠传输 | CAN |
6.3 开发难度评估
从调试便利性看:
- UART最友好(printf调试)
- SPI时序简单
- I2C需注意地址冲突
- CAN需要专用分析仪
最近给客户做电机控制器,最终选择CAN+SPI组合:CAN负责机间通信,SPI连接高速ADC。调试时先用CANalyzer抓包,再用Saleae逻辑分析仪看SPI时序,效率提升明显。