ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

嵌入式通信协议怎么选?从场景出发,看懂UART、I2C、SPI与CAN

嵌入式通信协议怎么选?从场景出发,看懂UART、I2C、SPI与CAN 刚学嵌入式最容易遇到的场景不是不会点灯而是灯亮了之后发现主控“读不到传感器数据”。传感器不响应、OLED 屏幕上全是花屏、WiFi 模块一上电就发烫。问题往往不是代码写错而是你选了一个不适合场景的通信方式。很多人因此陷入一个怪圈拼命背 I2C 有几根线、SPI 最高能跑多快、UART 怎么配波特率等到真正选型时仍然说不上来该用哪个协议。真正的原因是把通信协议当成“语法”来背了。这些协议其实更像是“路”有的路是 PCB 上两厘米的短走线有的是厂房里几十米的电缆有的干脆不走线走空气。一旦把协议放进“距离、线数、同步方式、双工能力、错误处理”这些坐标里就不再需要背。这篇文章就拿嵌入式开发里最常见的 12 种通信协议从“场景 特点”入手把它们逐个讲清楚。1. 只要把握这 5 个坐标协议细节就自然记住1.1 大部分协议都是“两方说话”差别只在四件事通信协议再怎么包装本质都是让两个地方互相理解对方的数据。只要落到物理世界就必须回答四个问题距离是多少需要几根线发数据时有没有一根时钟线来同步一方发送的同时另一方能不能回复这四个回答组合起来就差不多能区分出 UART、I2C、SPI、CAN 的差别。拿一个最简单的例子来说你在 PCB 板上接一个温湿度传感器板上走线不足 5 厘米环境几乎没有干扰。这时你优先考虑的不是抗干扰而是“引脚够不够、能不能多挂几个设备”。于是 I2C 会被排到很前面。但如果你要在两台设备之间传 20 米工业现场又有电机、变频器板上那套 3.3V 单端信号就不敢用了。你需要把信号变成差分传输再考虑 RS-485 或 CAN。无线也一样。BLE 和 WiFi 都工作在 2.4GHz 频段附近一个面向低功耗手机短连接一个面向数据和云平台接入场景不一样选型就不一样。这里想强调一个判断通信协议不是知识清单而是工程约束下的选择结果。1.2 用“五坐标”去看协议而不是先看概念我用得最多的分法是五个坐标距离板内、板外、跨厂房拓扑点对点、一主多从、多主多发同步异步 UART还是带 SCLK 的同步总线方向和速度是单工、半双工还是全双工速率层级是多少可靠性有没有应答、校验、重传、仲裁和错误帧拿到任何一种不熟悉的协议先不要从头去读长达几十页的规范而是先填这五个坐标。坐标填完协议的应用边界基本就清晰了。接下来正文从板级有线协议开始讲这是大多数 MCU 项目里最先遇到的。2. 板级有线UART / SPI / I2C / I2S / 单总线2.1 UART异步串口的“万能底板”波特率决定了能不能说上话UART 应该是很多人接触的第一个通信协议。MCU 把数据通过 TX 发出对方 RX 接收反过来另一根线再传回。它最典型的特征是没有时钟线。发送端按约定的波特率把每个位拆开在时间轴上逐个发送接收端也按同样的波特率去采样。两个设备之间只要波特率、数据位、停止位、校验位一致就能通信。因为简单它被用在了大量地方调试串口、蓝牙模块、GPS 模块、4G 模组、PLC 的串口通信改造甚至很多工程师把 UART 当成“万能兜底”来用。UART 容易踩坑的地方也很典型TX 和 RX 接反。两边没有共地。波特率有偏差。第二点尤其容易被忽略。两个设备之间只看 TX/RX没接 GND信号没有统一的参考电平乱码就会随机出现。很多所谓“通信不稳定”的问题到最后都会回到共地上。接线验证时可以先按最简方式做设备A TX - 设备B RX 设备A RX - 设备B TX 设备A GND - 设备B GND在开发板上UART 通常以 TTL 电平出现要接电脑或工控机时会通过 USB 转 TTL 芯片完成转换。UART 的价值不在于快而在于协议轻、实现简单、驱动生态成熟。它特别适合两个设备之间的点对点数据交换不太适合“一主多从”的总线扩展因为本身没有完整的寻址机制。2.2 I2C用两根线和地址换一条总线上挂多个设备I2C 是另一类典型。大家常把它和 UART 放在一起记但两者机制差别很大。I2C 一共两根线SDA 数据线、SCL 时钟线。时钟由主机产生所以它是同步串行总线。它允许一条 I2C 总线上挂很多从设备比如 EEPROM、温湿度传感器、OLED 屏幕、气压计等。每个设备都有一个地址主机通过地址来选择与谁通信。I2C 让我印象最深的地方在于它解决了“节省引脚”和“多设备挂载”的矛盾。很多传感器模块都可以用 I2C 接因为它只需要两根 GPIO。对于 STM32、ESP32 这类 MCU 来说如果同时要接屏幕、Flash、传感器引脚并不总是够用I2C 的复用价值就很明显。I2C 的常见坑有三个忘记接上拉电阻。I2C 是开漏输出SDA 和 SCL 必须靠上拉电阻把电平拉高。从机地址冲突。总线卡死。从设备异常拉低 SDA 不放时如果没有复位机制整个总线会一直等待。I2C 适合中等速度、短距离、多从设备的控制类场景。如果要做高速、大批量数据吞吐就不是 I2C 的强项。2.3 SPI一从一选全双工高速数据吞吐用它SPI 和 I2C 经常被放在一起对比但它们的哲学完全不一样。SPI 通常有四根线SCLK 时钟MOSI 主机发数据线MISO 从机回数据线CS 片选SPI 是全双工协议。主机在发送数据的同时也能通过 MISO 收数据。它没有复杂的地址帧选择哪个从设备靠硬件上的 CS 引脚来完成。一个从设备占一个 CS从设备越多需要的引脚也越多。因此 SPI 不会像 I2C 那样出现“总线地址冲突”但它会线多。它更常用于 LCD 屏幕、NOR Flash、SD 卡、高速 ADC、部分传感器模块。SPI 的配置项也比较容易出错。比如 CPOL 和 CPHA分别表示时钟空闲电平和采样边沿。同样的 SPI 器件如果时钟极性和相位不匹配读回来的数据经常会少一位或多一位。调试 SPI 时建议先做回环测试把 MOSI 和 MISO 短接然后发送一个已知的字节数据看能不能原样读回。这个方法可以快速避开“到底是 MCU 没有发出去还是对方没有回来”的问题。SPI 的选型结论很简单当通信量较大、对速度有要求、从设备数量不多时优先考虑 SPI。2.4 I2S 和单总线是特殊项不要和 I2C、UART 混在一起初学者经常看到 I2S 时误以为它是 I2C 的升级版。其实不是。I2S 是音频专用的串行总线名字来自 Inter-IC Sound。它专门用来传输数字音频数据比如 MCU 和音频解码芯片、DAC、数字麦克风之间的音频流。典型的 I2S 信号包括BCK 位时钟WS 声道选择/帧时钟DATA 数据线通过 WS 区分左右声道通过位时钟同步每一位非常适合连续数据流。如果用 SPI 去发音频流会发现自己还要在软件层面去维护帧和声道越来越麻烦I2S 则是把这一层直接变成硬件标准。另一个容易混淆的是“单总线”类协议也就是 1-Wire、DHT11 这类时序通信方式。这类方案通常只占用一根 GPIO数据线既要发送指令又要接收数据同时还要靠高低电平的维持时间来表示 0 或 1。DHT11 的读取时序就高度依赖代码执行时间读取期间如果被中断打断很容易超时或读错数据。我记得第一次用 DHT11 时明明代码照着例程写但经常出现“TIMEOUT”错误。后来发现是因为中断太频繁时序被撕碎了。解决办法是在读取期间关闭相关中断或者把依赖时序的代码放到临界区执行。I2S 解决的是音频帧连续传输的问题单总线解决的是“极致省引脚”的问题。它们和通用 I2C/SPI 并不在一个赛道上。3. 把信号送出电路板RS-485、CAN、LIN、Modbus、以太网3.1 RS-485 本质是“物理层”别把它当成完整协议很多人把 RS-485 和 Modbus 混在一起这是嵌入式和工业控制领域最容易出现的认知偏差。RS-485 其实是电气标准定义了如何用两根差分线把信号传得更远、更稳。它并不规定数据帧格式。也就是说你仍然可以用 UART 的时序发送字节只是底层电平从“单端 TTL”变成了“差分信号”。RS-485 能传几十米到上千米支持一主多从也支持在一条总线上挂多个节点。因为使用 A/B 两根差分线共模干扰会被抵消适合电机、变频器比较多的工业现场。但 RS-485 的半双工问题是必须面对的。典型电路里MCU 仍然使用 UART只不过外接了 MAX3485 这类收发器。方向控制引脚切换时如果 MCU 发送完数据后立刻切回接收最后一位数据很可能被截断。很多老工程师的做法是发送完成后加一个极短延时或者在 UART 的发送完成中断里再切换方向。这个细节只跑通一次通信时看不出来批量跑起来以后会反复出现。RS-485 是一个很好的“物理载体”但协议层还需要自己在上面定义帧格式。实际产品里最常叠加的是 Modbus。3.2 CAN 的可靠性来自仲裁和错误机制主机反而不重要CAN 总线在汽车电子和工业控制里太常见了。很多发动机 ECU、电池管理系统、机器人控制器之间都靠它来传递关键数据。CAN 与 UART、RS-485 最大的区别是没有固定的主机概念。每个节点都分配了不同的报文 ID。当两个节点同时发送数据时总线通过逐位仲裁决定谁先发送。优先级更高的报文不需要等待别人让出总线而是靠仲裁机制自然抢占。这在实际项目中意味着两件事系统不容易因为某个节点故障而整个瘫痪。高优先级的关键数据更容易被及时发出去。CAN 还有一个好处是错误处理能力很强。节点会检测错误、发送错误帧并维护自己的错误计数器。一个错误过多的节点甚至会自动退出总线。这种机制让 CAN 在振动、电磁干扰比较强的场景里表现稳定。使用 CAN 时最容易被忽视的是终端电阻。CAN 总线两端需要分别接入约 120Ω 的终端电阻。不是总线上所有节点都接而是物理最远的两端才需要。如果只是两个节点通信也仍然需要在两端各接电阻。电阻缺失时点对点短距离通信有时也正常一旦距离拉长或总线节点增多就会开始出现偶发通信失败。CAN 更适合“多个控制器之间共享状态、实时响应要求高、电磁干扰强”的场景。与 RS-485 相比它的硬件和协议复杂度更高但可靠性也更完整。3.3 LIN 是低成本汽车子总线不和 CAN 抢速度汽车电子中不同的设备对通信要求并不一样。动力系统要求实时性高、可靠性高可能用 CAN车窗、后视镜、雨刮这类低速车身控制如果也全部用 CAN成本并不划算。LIN 正是为这种场景出现的。它常见于汽车的车身电子子网单总线通信速度远低于 CAN结构也更简单。好处是成本和线束数量都能降下来。它不是用来传大数据流的协议。它的典型使用方式是一个主节点和几个从节点组成小区域网络负责座椅、门控、空调面板等不太紧急的控制。对嵌入式入门者来说LIN 不一定马上会用到但面试和车规项目里会经常听到。理解它的核心是知道汽车电子里同样存在“成本分层”的逻辑不是所有节点都适合接入高速总线。3.4 Modbus 是应用层协议RS-485 和以太网都能承载它Modbus 单独拿出来说是因为它不属于物理层而是建立在串口或以太网之上的应用协议。实际项目里你常看到的情况是MCU 的 UART 引脚接 RS-485 收发器然后用 Modbus RTU 报文的格式去发送数据。这样原本没有协议格式的 UART RS-485就从“能传字节”上升成了“主站可以读从站数据”的完整通信。Modbus 的核心设计非常直接一个主站按照寄存器地址去读或写从站的数据。常见的功能码包括读寄存器、写单个寄存器、写多个寄存器等。因为协议开放、格式简单大量电表、温控器、变频器、PLC 都支持 Modbus。但实际用起来有几个点要特别注意不同厂家的寄存器地址可能不一致。数据大小端顺序可能不同。浮点数存储格式可能不同。很多项目踩坑不是因为 Modbus 难而是因为厂家文档里的寄存器映射表写得不够清晰。遇到通信乱码时不要总怀疑硬件先打开厂家手册确认这件事更可能是地址、寄存器数量和字节顺序问题。Modbus TCP 也会在嵌入式网关里出现。它把 Modbus 报文封装进 TCP 包让工业设备能够接入上层管理系统。链路层从串口变成了以太网但数据模型仍然是寄存器读写。3.5 以太网进嵌入式换来的不只是速度更是软件工程量很多 MCU 型号会带以太网 MAC外部再接一个 PHY 芯片比如 LAN8720 这类方案。加上 LwIP 协议栈嵌入式设备就能具备 TCP/IP 通信能力进而接入 MQTT、HTTP、远程升级等功能。以太网的场景很明确设备需要联网、上传大量数据、与 PC 端或云平台通信。相比 WiFi有线以太网更稳定没有频段干扰也更容易做工业现场的确定性通信。但以太网并不适合所有嵌入式项目。它带来的工程复杂度比 UART、CAN 高出一个量级PCB 设计要关注差分走线和阻抗。需要处理网络协议栈。内存消耗和代码量明显增加。工程调试需要学会抓包而不是只看串口。如果你只想让 MCU 控制一个传感器用 SPI 或 I2C 就够了。一旦需要设备接入局域网甚至要远程访问以太网才值得进入选型视野。4. 无线通信WiFi 和 BLE 通常选的是“产品形态”4.1 WiFi要 IP、要云但功耗和成本也得想清楚WiFi 在嵌入式领域已经非常普及尤其是带 MCU 的 WiFi 模组出现后一颗芯片既能当主控又能联网开发门槛比过去低了不少。典型的 WiFi 产品场景是智能插座、摄像头、环境检测网关、家电联网。设备接入路由器后数据上报到 MQTT用户在手机或云端看到设备状态。WiFi 的本质优势是它具备 IP 网络能力可以直接跑 TCP/UDP、HTTP、MQTT、TLS 等协议和互联网生态对接成本低。远程升级、日志上报、语音平台接入都很顺。劣势也很明确功耗偏高不适合纽扣电池长期运行。模块射频环境复杂容易出现连接不稳定。安全配置、配网、断线重连这些都需要单独处理。我看过很多嵌入式项目把绝大多数精力放在外设驱动上却忘记了 WiFi 最需要设计的其实是“配网流程”和“断网后的状态处理”。这比单纯调通 AT 指令要重要。如果只是产品原型默认使用厂商示例代码通常够。如果是量产产品WiFi 的不稳定场景、重连策略、日志、云断开重连都要纳入
返回列表