
很多嵌入式初学者了解通信协议的方式是先把 UART、SPI、I2C、CAN 这些名字背熟再记一遍“同步还是异步、全双工还是半双工”。结果一旦到了真实项目里I2C 传感器读不到数据、SPI Flash 偶尔丢字节、RS-485 拉到 200 米之后随机乱码立刻卡住。这些问题的根源不在于你背得不够多而在于你只记住了协议的“名字”没有理解协议的“场景”和“取舍”。判断嵌入式工程师通信协议功底的标准其实就三个问题这个协议解决什么问题它用什么代价换来了这个能力你的项目到底该选哪一种本文按“场景 特点 坑位”的方式把 12 种最常见嵌入式通信协议一次性讲清楚。读完你至少能回答为什么板内常用 I2C/SPI、板间常用 RS-485/CAN、物联网终端常用 BLE/WiFi/LoRa以及面试官追问“为什么选它不选另一个”时你该怎么把逻辑讲完整。1. 别再死记通信协议了嵌入式开发真正要理解的是什么先说一个很多工程师踩过的坑。有朋友接手一个项目MCU 需要采集 8 路温湿度传感器。他第一个想到的就是 I2C因为 I2C 能挂多个设备一根 SDA 一根 SCL接线少代码例程也多。结果做出来之后发现一个问题传感器模块的 I2C 地址全都一样8 个设备挂在同一根总线上主机根本无法区分哪个是哪个。这时候有人建议换 SPI每个设备一根片选线8 个设备就需要 8 个 CSGPIO 又不够用。最后只能换成带地址拨码的 RS-485 传感器或者给每个 I2C 传感器做独立地址扩展。看完这个例子你会发现通信协议从来不是“哪个好”的问题而是“当前项目在物理层、拓扑、数据量、功耗、成本这几个维度下哪种协议最合适”的问题。所以正确学习通信协议的方法不是背定义而是建立一张“选型地图”。你要知道每种协议适合什么场景、物理上长什么样、如何传输、典型速率是多少、最常见的坑在哪里。这样面试时你能讲清楚选择依据做项目时你能提前避开“看起来能用、量产就翻车”的坑。这篇文章就是围绕这张地图展开的。2. 先建立框架三个维度看懂所有通信协议理解任何通信协议都可以从三个维度入手。2.1 物理层信号到底通过什么传物理层决定了速率上限、传输距离和接线方式。比如 SPI 是主机通过时钟线主动产生时钟所以可以跑得很快UART 是双方约定波特率异步收发没有时钟线所以对时钟精度更敏感RS-485 用差分信号传输所以能传上千米WiFi/BLE 用无线电波传输所以不需要物理线缆但会引入天线、频段、干扰和功耗问题。2.2 拓扑与角色谁跟谁说话、能不能同时说点对点例如 UART 的两台设备直接对接。一主多从例如 SPI 靠片选线选中不同从设备I2C 靠地址寻址。多主总线例如 CAN 总线上多个节点都能主动发报文靠仲裁机制解决冲突。星型/网状例如 WiFi 设备接入 APBLE Mesh/ZigBee 可以实现多跳组网。这个维度决定了项目的扩展方式和通信可靠性。2.3 协议层级物理、数据链路、应用层要分开看很多人把 Modbus 和 RS-485 混为一谈这就是典型的分层不清。Modbus 是应用层协议它规定了报文格式、功能码、寄存器寻址而 RS-485 是物理层标准只规定了电气特性。实际项目里Modbus RTU 可以跑在 RS-485 上也可以跑在串口上Modbus TCP 则跑在以太网上。把层级分开你后续看协议栈、调试通信问题会清晰很多。2.4 12 种协议总览表下面这张总览表是整篇文章的地图。后面每一节都会围绕其中一条展开。序号协议分类典型场景一句话特点1UART/USART板级有线调试串口、低速传感器、模块通信异步串行实现简单双方需约定波特率2SPI板级有线Flash、屏幕、SD 卡、ADC 等高速外设同步全双工速率高靠片选区分设备3I2C板级有线传感器、EEPROM、电源管理芯片两根线多设备靠地址寻址适合低速多从机4RS-485现场总线工业控制、楼宇自控、远距离多点通信差分信号抗干扰强半双工总线5CAN现场总线汽车电子、工业控制、机器人多主总线带错误处理和仲裁机制6Modbus RTU应用层协议PLC、传感器、电表、工业网关主从问答式报文结构简单兼容性极好7WiFi无线局域网摄像头、网关、需接入互联网的设备带宽高、生态成熟但功耗高、连接逻辑重8BLE短距无线手环、传感器、手机交互设备低功耗蓝牙连接快GATT 服务模型9ZigBee低速无线 Mesh智能家居、工业无线传感网络自组网、多跳适合大量低速率节点10LoRa远距离低功耗广域网抄表、农业监测、园区传感器灵敏度高、距离远但速率很低11NFC近场通信碰一碰配网、支付、标签识别通信距离只有几厘米安全性天然加分12Ethernet/工业以太网有线网络网关、视觉系统、运动控制带宽高可跑 TCP/IP工业场景需考虑实时性3. 板级有线通信协议UART、SPI、I2C先看同一块 PCB 上MCU 与传感器、存储芯片、屏幕之间的通信。这类通信距离很短通常只有几厘米到几十厘米重点是速率、接线数量和寻址方式。3.1 UART/USART最朴实也最常用的串口UART 的全称是 Universal Asynchronous Receiver/Transmitter通用异步收发器。它没有时钟线收发双方靠预先约定好的波特率比如 9600、115200来采样。在 MCU 内部USART 通常是在 UART 基础上增加同步模式、硬件流控等能力但绝大多数场景我们还是把它当作异步串口用。场景判断调试日志输出几乎每个嵌入式项目的 console 口。GPS 模块、蓝牙模块、4G 模块、部分传感器大量模组默认就是串口通信。两个 MCU 之间简单点对点通信。为什么它是入门首选第一接线只有 TX、RX、GND逻辑简单。第二几乎任何 MCU 都有串口外设任何 IDE 都有串口调试助手。第三查问题最方便逻辑分析仪加上串口助手就能看到数据。代码示例以 STM32 HAL 库为例// 文件路径uart_demo.c #include main.h UART_HandleTypeDef huart2; void MX_USART2_UART_Init(void) { huart2.Instance USART2; huart2.Init.BaudRate 115200; huart2.Init.WordLength UART_WORDLENGTH_8B; huart2.Init.StopBits UART_STOPBITS_1; huart2.Init.Parity UART_PARITY_NONE; huart2.Init.Mode UART_MODE_TX_RX; huart2.Init.HwFlowCtl UART_HWCONTROL_NONE; huart2.Init.OverSampling UART_OVERSAMPLING_16; if (HAL_UART_Init(huart2) ! HAL_OK) { Error_Handler(); } } void UART_SendTest(void) { uint8_t msg[] Hello CSDN\r\n; HAL_UART_Transmit(huart2, msg, sizeof(msg) - 1, 100); }这里要提醒一下HAL_UART_Transmit的最后一个参数是超时时间单位毫秒。实际项目中如果数据量大建议改用中断或 DMA 方式否则会阻塞在主流程里。常见坑TX 接 RX、RX 接 TX交叉连接不是同名直接相连。GND 必须共地否则通信会随机出错。波特率误差不能太大双方不一致会出现乱码。MCU 的 TTL 电平不能直接接 RS-232 的 DB9 口需要电平转换芯片。3.2 SPI高速全双工的“片选”方案SPI 是同步串行外设接口通常有 4 根线SCLK时钟线由主机产生。MOSI主机输出、从机输入。MISO主机输入、从机输出。CS/SS片选线低电平有效。SPI 的核心理念是“谁拉低片选主机就和谁通信”。所以一台主机可以挂多个从设备每个从设备独占一根 CS。场景判断NOR Flash / SD 卡高速读写存储。TFT 屏幕像素数据吞吐量大。高速 ADC/DAC、传感器需要较高采样率。需要全双工持续交换数据的场景。为什么 SPI 适合这些场景SPI 是同步通信时钟由主机主动产生不需要双方精确匹配时钟所以速率可以做到很高。很多 MCU 的 SPI 外设可以跑到几十 Mbps远高于 UART 和 I2C 的常见速率。代码示例读取 SPI Flash 的 JEDEC ID// 文件路径spi_flash_demo.c #include main.h extern SPI_HandleTypeDef hspi1; #define FLASH_CS_LOW() HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_RESET) #define FLASH_CS_HIGH() HAL_GPIO_WritePin(FLASH_CS_GPIO_Port, FLASH_CS_Pin, GPIO_PIN_SET) uint8_t SPI_ReadFlashID(void) { uint8_t tx[4] {0x9F, 0x00, 0x00, 0x00}; uint8_t rx[4] {0}; FLASH_CS_LOW(); HAL_SPI_TransmitReceive(hspi1, tx, rx, 4, HAL_MAX_DELAY); FLASH_CS_HIGH(); return rx[1]; // 不同 Flash 返回的字节含义以具体手册为准 }这里 0x9F 是“读 JEDEC ID”指令常见 SPI Flash 都支持但具体返回内容要看芯片手册。示例的目的是演示 CS 拉低、发送命令、读取数据、CS 拉高这一完整过程。常见坑CPOL/CPHA 配置不一致主机和从机对不上时序数据可能全是 0xFF。时钟频率太高在杜邦线下信号质量变差。CS 拉低和拉高的时机不对可能多读或少读一个字节。多个从设备共用 MOSI/MISO/SCLK 时从机的 MISO 必须支持三态输出否则会互相打架。3.3 I2C两根线串联一堆设备I2C 是 Philips 公司最早提出的两线式串行总线只有 SCL时钟线和 SDA数据线两根线所有设备并联在这两根线上。每个从设备有一个地址主机通过地址选择要通信的对象。场景判断温湿度传感器、气压计、加速度计等小封装传感器。EEPROM、RTC、电源管理芯片。同一块板子上挂多个低速率外设且 GPIO 资源紧张。I2C 真正的优势是节省引脚。两个 GPIO 就能挂几十个设备代价是速率比 SPI 低、协议比 UART 复杂而且每根线上都要接上拉电阻。代码示例通过 I2C 读取传感器寄存器// 文件路径i2c_sensor_demo.c #include main.h extern I2C_HandleTypeDef hi2c1; #define SENSOR_I2C_ADDR 0x76 // 部分模块为 0x77取决于地址引脚 #define SENSOR_REG_TEMP_MSB 0xFA uint8_t I2C_ReadTempMSB(void) { uint8_t reg SENSOR_REG_TEMP_MSB; uint8_t data 0; HAL_I2C_Mem_Read(hi2c1, SENSOR_I2C_ADDR 1, reg, I2C_MEMADD_SIZE_8BIT, data, 1, 100); return data; }注意不同 STM32 HAL 版本、不同 MCU 厂商的 I2C 驱动对“从机地址是否需要左移一位”的定义可能不一样。实际调试时如果发送地址后一直收不到 ACK先查这个问题。常见坑SDA/SCL 忘记接上拉电阻通信直接失败。从机地址 7 位和 8 位混淆代码里左移一位出错。两个从机地址冲突需要改地址或加 I2C 开关。I2C 总线被设备拉死SCL 或 SDA 一直为低需要排查哪个从机异常。三个板级协议的小结论追求高速、需要全双工、从设备不多优先考虑 SPI传感器多、引脚紧张、速率要求不高优先考虑 I2C只要点对点通信、调试方便优先考虑 UART。4. 现场总线通信协议RS-485、CAN、Modbus到了板间通信设备之间相距几米到几百米甚至处在电机、变频器等强干扰环境中。这时候再拿普通 TTL 串口拉线问题就会很多共地困难、干扰大、距离不够。4.1 RS-485工业现场的距离之王RS-485 本质上是串口通信的物理层升级版。它把 TTL 单端信号转换成 A/B 两根线之间的差分信号因此抗共模干扰能力更强传输距离更远还支持一条总线上挂多个节点。场景判断工业设备之间长距离通信比如 PLC、变频器、仪表。楼宇自控、停车场道闸、环境监测。多点采集系统比如多个传感器节点挂在同一根总线上。为什么是差分信号就能远单端信号是“对地电压”表示 0 和 1当地电位有差异时信号就容易被淹没。差分信号则是比较 A、B 两线之间的电压差外部共模干扰同时作用在两根线上差值基本不受影响。这就是 RS-485 在工业现场更有优势的原因。常见坑A、B 线接反通信直接不通。总线两端没加终端电阻长距离时信号反射严重。半双工模式下发送和接收切换时机不对会吃掉第一个字节或最后一个字节。多个节点距离很远时地电位差异可能损坏收发器需要隔离或共地处理。4.2 CAN汽车和工控里的可靠总线CAN 是控制器局域网络最早由 Bosch 为汽车电子设计。它和 RS-485 类似也是一条差分总线但 CAN 的可靠性设计要更完整。CAN 和 RS-485 的最大区别维度RS-485CAN通信模型通常主从半双工多主任意节点可主动发冲突处理靠主站调度避免冲突靠报文 ID 仲裁非破坏性错误处理主要由应用层处理协议内建错误检测、错误帧、重发机制报文寻址通常按设备地址按报文 ID可配置过滤器典型速率距离越远速率越低常见 125kbps~1Mbps场景判断汽车车身网络车窗、车灯、电池管理、OBD。工业控制伺服驱动器、传感器、PLC。机器人关节之间、AGV 内部通信。CAN 报文看起来是什么样一个标准数据帧的核心字段包括仲裁场11 位 ID、控制场DLC、数据场最多 8 字节。例如 ID 为 0x123数据为 01 02 03 04 05 06 07 08在 CAN 分析仪里大概长这样ID: 0x123 DLC: 8 Data: 01 02 03 04 05 06 07 08不同 CAN 控制器对过滤寄存器、屏蔽寄存器的实现不同但“按 ID 过滤”这一思想是一致的。常见坑CAN_H 和 CAN_L 接反节点无法通信。总线两端需要 120Ω 终端电阻缺失时通信不稳定。波特率不一致总线会一直报错。报文 ID 设计不合理过滤器和屏蔽器配起来很痛苦。4.3 Modbus工业设备通用的应用层语言Modbus 不是物理层协议它通常跑在串口或以太网上。最常见的形态是 Modbus RTU over RS-485因为 RS-485 解决了物理传输问题Modbus 解决了“主站怎么问、从站怎么答”的格式问题。Modbus RTU 主从问答模型主机发送一帧请求从机收到后返回一帧响应。典型报文结构是地址码(1字节) 功能码(1字节) 数据 CRC16(2字节)例如主机读取从机地址 0x01 的保持寄存器从地址 0x0000 开始读 2 个寄存器完整的请求帧可能是01 03 00 00 00 02 C4 0B其中01从机地址03读保持寄存器功能码00 00寄存器起始地址00 02寄存器数量C4 0BCRC16 校验低字节在前为什么嵌入式设备几乎都要支持 Modbus原因很简单PLC、触摸屏、组态软件、网关几乎全都认 Modbus。你的设备只要把 Modbus 从站协议做好就能非常快地接入工业系统不用为每家的私有协议单独适配。常见坑协议地址和真实寄存器地址常常有“偏 1”关系实现时容易搞混。CRC 计算错误从站直接丢弃报文。RS-485 方向切换和 Modbus 帧间隔没处理好主站会认为超时。5. 无线通信协议WiFi、BLE、ZigBee、LoRa无线协议在嵌入式中的选择本质是一场“功耗、速率、距离、成本、生态”的五方博弈。5.1 WiFi高带宽、易联网但功耗不低WiFi 设备在嵌入式中的角色通常是“需要接入互联网的网关”摄像头、智能音箱、家电、工业网关。WiFi 的优势是带宽高、生态成熟、手机和路由器都能直接连劣势是协议栈重、连接时间长、功耗高。为什么不能把所有传感器都改成 WiFi如果一个纽扣电池供电的温湿度计每隔 5 分钟上报一次数据WiFi 模块光是保持连接、每次重新关联 AP 的功耗就非常可观。而且一个 AP 能稳定承载的设备数量有限大规模部署会被迫做网关架构。嵌入式 WiFi 常见开发方式串口 WiFi 模块 AT 指令MCU 不跑 TCP/IP 协议栈。运行 RTOS lwIP直接在 MCU 里处理 TCP/IP。Linux 平台直接用 socket开发效率最高。AT 指令接入 AP 的典型流程如下ATCWMODE3 // 设置为 Station SoftAP 模式 ATCWJAPSSID,PWD // 连接路由器 ATCIFSR // 查看获取到的 IP ATCIPSTARTTCP,192.168.1.100,8080 // 建立 TCP 连接 ATCIPSEND10 // 准备发送 10 字节数据实际模块之间的指令细节会有差异但流程基本一致。常见坑路由器 SSID 或密码错误模块反复重连。信号弱时 TCP 连接不稳定应用层没有断线重连机制。电源供电不足WiFi 发射瞬间电流大导致模块重启。5.2 BLE物联网小设备的低功耗主力BLE 是低功耗蓝牙和经典蓝牙 BR/EDR 不一样。BLE 不是为了传音频和大文件而是为了“小数据、低功耗、频繁连接”的物联网场景。场景判断手环、体脂秤、血压计等健康设备。手机 App 与设备配对的智能硬件。信标 Beacon、室内定位、设备配网。BLE 的通信模型以 GATT 为核心外设提供 ServiceService 下面有 Characteristic手机或主机通过读写 Characteristic 来交互。开发者需要先设计好服务 UUID、特征值、读写权限、通知方式再去写业务逻辑。为什么 BLE 功耗能这么低BLE 不是持续传输而是靠“广播、连接事件、睡眠”来工作。平时设备深度睡眠只在连接事件到达时短暂唤醒。实际功耗取决于广播间隔、连接间隔、是否开启通知而不是只看芯片标称电流。常见坑把经典蓝牙的 SPP 思路套到 BLE 上协议模型对不上。广播包设计得太大导致扫描成功率下降。没有处理断连重连和绑定关系用户换手机后设备不认。私有协议裸奔在 BLE 上没有做认证和签名容易被伪造指令控制。5.3 ZigBee低速多跳自组网ZigBee 基于 IEEE 802.15.4速率只有 250kbps 左右但它的特点是支持大规模节点自组网、多跳路由适合智能家居和工业无线传感器网络。场景判断智能家居里的灯光、窗帘、门锁系统。几十甚至上百个节点的工业无线采集网络。需要节点之间自动路由、绕过故障点的场景。ZigBee 的陷阱在于“标准化程度没那么理想”。ZigBee 协议栈很复杂从物理层到应用层每一层都有不少可配置项。产品化过程中很多厂商做的是“基于 802.15.4 的私有协议”并不是标准 ZigBee。如果你只是买了一个“ZigBee 模块”最终能不能和其他品牌的网关互通取决于协议栈是否一致。从学习性价比来看如果只是做低功耗局域物联网先学 BLE如果追求多跳 Mesh、大规模传感器网络再去深入 ZigBee 或 Thread。5.4 LoRa远距离低功耗广域网LoRa 是 Semtech 公司推动的扩频通信技术核心卖点是“低速率下的超远距离”。典型应用是智能抄表、农业灌溉监测、园区路灯、河道水位监测。一个 LoRa 节点可以通过网关把几公里外的数据传回服务器。LoRa 的性能受参数影响很大扩频因子 SF、带宽 BW、编码率 CR 共同决定了速率和灵敏度。SF 越大灵敏度越高但空中传输时间越长速率越低。所以不能直接说“LoRa 能传 5 公里”因为这是“特定速率、特定环境、特定天线高度”下的结果。应用 LoRa 时要注意LoRa 解决的是“物理层远距离传输”不等于 LoRaWAN。LoRaWAN 包含网络服务器、设备入网、加密、数据上行下行等完整机制。不同地区对使用频段和发射功率有规定产品化前必须先确认目标市场要求。节点数量大时需要考虑信道冲突、上行时间、网关容量不能把 LoRa 当成无限容量的 4G 替代品。6. 近场与网络通信协议NFC、以太网/工业以太网最后两类协议很容易被忽略但在产品选型中经常是加分项。6.1 NFC几厘米内的安全交互NFC 是近场通信工作在 13.56MHz通信距离通常只有几厘米。它的优点恰恰来自这个短距离靠近才能通信天然减少了很多恶意攻击场景。典型嵌入式场景手机“碰一碰”配网。设备身份识别、防伪验证。电子价签、门禁卡、校园卡读取。在 MCU 项目里NFC 通常以 NFC 读卡器芯片或模组形式出现MCU 通过 I2C/SPI/UART 与 NFC 控制器通信再