news 2026/9/5 11:28:06

空调开发通信协议全解析:从I2C到MQTT的链路地图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
空调开发通信协议全解析:从I2C到MQTT的链路地图

空调这一类产品看起来“简单”——制冷、制热、除湿、送风,似乎逻辑并不复杂,但真正接触过项目开发后你会发现,空调是整个家电行业里通信链路最长、协议种类最杂、联调成本最高的品类之一。从内机主板上的温湿度传感器,到外机压缩机变频驱动板,再到线控器、集控系统、Wi-Fi模块直至手机 App 和云平台,一条数据要经过芯片引脚、板级总线、机组内部网络、家庭路由器、云端服务器等多个环节。每一段链路都有自己专属的通信协议,搞不清楚边界,调试时就会四处碰壁。

这篇文章想围绕“空调开发”这条主线,把板级、系统级和云端通信协议做一次系统梳理。不是单纯罗列协议名称,而是从实际开发视角出发,讲清楚每条链路上用什么协议、为什么选它、数据怎么流动、联调时经常遇到哪些坑。无论你是刚转入嵌入式通信领域的学生,还是在做空调控制器、暖通集控、智能家居接入的工程师,这篇内容都可以作为一份查阅型的通信地图来用。

1. 先把空调通信场景拆开,再看协议

1.1 一条温度数据从传感器到 App 要经过几跳

理解空调通信最好的方式,是跟着一条真实的数据流走一遍。假设用户通过手机 App 远程把空调设定温度从 26℃ 改到 22℃,这条指令看起来只是“按下按钮”,实际在设备端到底发生了什么,可以先看一个整体链路图:

手机 App ↓ ① HTTPS/MQTT 云平台(设备管理、指令下发) ↓ ② MQTT over TLS 家庭 Wi-Fi 路由器 ↓ ③ TCP/IP 空调 Wi-Fi 模块(乐鑫/Realtek/海思方案) ↓ ④ UART(通常是自定义帧协议) 空调内机主控 MCU ↓ ⑤ CAN / RS485(室内外机通信) 室外机变频驱动板 / 压缩机 ↓ ⑥ I2C/SPI(驱动板内部传感器读取) 温度传感器 / 电流采样芯片

这里每一层之间都有一套独立协议,而且协议之间经常需要相互转换。内机主控 MCU 收到 Wi-Fi 模块通过串口发来的“设定温度 22℃”帧后,要解析出指令码和参数,再把参数转换成自己的控制逻辑能识别的数据结构,随后通过 CAN 总线发给室外机,室外机变频板再从 CAN 报文里提取目标频率,结合 I2C 读取的管温、排气温度、电流值做压缩机闭环控制。

换句话说,“设 22 度”这个动作从云端到压缩机,最少要跨 4 种以上通信协议。做嵌入式软件的同学如果只盯着单片机外设驱动,往往不会意识到自己写的 I2C 读温度函数,其实只是这条长链路里最底层的一小环。

1.2 空调通信协议的层次划分

为了便于梳理,我个人习惯把空调通信分成三个层级:

  • 板级通信:指同一块 PCB 内部,或主控板与非常近的距离(几厘米到几十厘米)之间的通信。典型如 MCU 与温湿度传感器、EEROM、触摸面板、显示屏驱动之间的 I2C、SPI、UART。特点是距离短、速率要求低、实时性要求取决于传感器类型。
  • 机组级通信:指空调室内机、室外机、线控器、电表、集中控制器之间的通信。典型如 CAN 总线、RS485 总线,或者针对多联机系统的专用总线。特点是距离远(几米到上百米)、节点多、抗干扰要求高、数据实时性强。
  • 云端级通信:指设备通过 Wi-Fi、4G、NB-IoT 等联网模块接入云端平台的过程。典型链路是 Wi-Fi 模块通过 UART 与主控交互,再通过 TCP/UDP 栈发起 MQTT、HTTP、COAP 等应用层协议与云平台通信。特点是数据链路动态变化,需要处理断网重连、掉线补发、设备配网、证书校验等一系列连接管理问题。

很多刚入行的朋友容易把“CAN”和“MQTT”放在一起比较,这是没意义的——它们根本不在一个层级,一个是现场总线,一个是应用层消息协议。做空调通信架构设计时,第一件事是先把协议划分到正确的层级里,再谈选型。

2. 板级通信协议:I2C、SPI、UART 的空调场景

2.1 空调开发中的板级通信角色

空调主板上的板级通信是嵌入式开发者最先接触的部分。传感器、存储芯片、显示驱动、Wi-Fi 模块等,都要和主控 MCU 进行数据交换。常见的板级协议有 I2C、SPI、UART、GPIO 模拟时序等。它们各有优劣,选择取决于传输速率、引脚占用、从机数量、抗干扰能力等。

在空调开发中,板级通信常见场景包括:

  • 温度传感器(如室温、管温、排气温度)通过 I2C 或单总线协议读取数据。很多空调使用 NTC 热敏电阻,通过 MCU ADC 采样即可,不涉及数字通信协议。但新款变频空调逐渐使用数字温度传感器(如 I2C 接口的 SHT30),通信时序要求更严格。
  • 存储芯片(如 EEPROM、Flash)通常使用 I2C 或 SPI 接口,保存运行参数、故障记录、用户设定等。
  • 显示面板(LCD、段码屏、LED 点阵)可能通过 SPI 或 I2C 驱动,数据传输量大时用 SPI,简单显示用 I2C。
  • Wi-Fi 模块和主控 MCU 通信,绝大多数使用 UART,部分模组也支持 SPI 和 SDIO,但 UART 是最通用的方式,因为几乎所有 MCU 都有 UART 外设,而且 AT 指令交互简单。

如果从调试角度来说,I2C 最怕总线卡死,SPI 要留意极性和相位配置错误,UART 则经常出现波特率不匹配或帧格式不一致的问题。下面逐个展开。

2.2 I2C 通信协议在空调板级的使用与踩坑

I2C(Inter-Integrated Circuit)由飞利浦公司发明,是一种两线制同步串行总线,由 SCL(时钟)和 SDA(数据)两根线组成。它的应用场景是连接低速外设,属于板级通信中比较典型的协议。在空调主板上,I2C 总线常用于 EEPROM 存储芯片(如 AT24C02)、温湿度传感器、部分 IO 扩展芯片等。

I2C 的基本特征:

  • 主从架构:MCU 作为主机,各芯片分配从机地址。
  • 传输速率标准模式 100kbit/s,快速模式 400kbit/s,高速模式 3.4Mbit/s。
  • 支持多主机,不过空调场景中几乎都是单主机。
  • 两根线必须接上拉电阻(通常 4.7kΩ 或 2.2kΩ),具体阻值取决于总线电容与通信速率。

空调开发中 I2C 的坑点通常不在协议时序上,而在于总线异常处理与数据校验。例如,当外接传感器线束较长时,I2C 信号很容易因线间电容过大导致波形畸变,造成通信失败。下面给出一个模拟 I2C 读取 EEPROM 的示例片段,完整的 I2C 时序模拟可移植到不支持硬件 I2C 的 MCU 上。

#include "i2c_soft.h" #define SCL_H gpio_set_level(SCL_GPIO, 1) #define SCL_L gpio_set_level(SCL_GPIO, 0) #define SDA_H gpio_set_level(SDA_GPIO, 1) #define SDA_L gpio_set_level(SDA_GPIO, 0) #define SDA_READ gpio_get_level(SDA_GPIO) static void i2c_start(void) { SDA_H; SCL_H; delay_us(5); SDA_L; delay_us(5); SCL_L; } static void i2c_stop(void) { SDA_L; SCL_H; delay_us(5); SDA_H; delay_us(5); } static uint8_t i2c_read_byte(void) { uint8_t data = 0; for (int i = 0; i < 8; i++) { SCL_H; delay_us(2); data = (data << 1) | SDA_READ; SCL_L; delay_us(2); } return data; }

实际空调产品中,I2C 设备地址错位、总线死锁是最常见的问题。有些传感器芯片在总线繁忙时无法正确响应 ACK,如果软件没做超时处理,整个读取流程会卡死在 while 循环里。更可怕的是 I2C 总线一直为低,后续所有从机都无法通信。此时需要在初始化时检测 SDA 状态,如果发现拉低则主动产生 9 个时钟脉冲恢复总线,或者给从机单独复位。

一个很实际的经验:I2C 通信务必开启超时退出机制,而不是死等 ACK。因为这个协议本身就没有内置错误重传,一旦某个设备故障,主控必须具备“读失败就跳过本次采样,等待下一次轮询”的能力,否则一条传感器的故障就会拖垮整个控制逻辑。

2.3 SPI 通信协议在空调显示与存储中的应用

SPI(Serial Peripheral Interface)是另一种板级同步串行协议。相比于 I2C 只有两根信号线,SPI 通常使用四根线:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。每个从机需要一根独立的片选线,所以从机多时占用的 GPIO 也就多。

SPI 的特点:

  • 传输速率高,可达几十 Mbps。
  • 全双工,主机发送和接收可以同时进行。
  • 没有 ACK 应答机制,主机无法直接确认从机是否收到数据。
  • 需要片选信号来选中目标设备,同一时刻只能与一个从机通信。

空调主板上,SPI 常用于大容量 Flash 存储、LCD 显示屏驱动,以及部分高速 ADC 芯片。如果主控是 Cortex-M 系列,硬件 SPI 外设会附带 DMA 功能,可以做到大量显示数据不需要 CPU 逐字节搬运,显著降低主控负载。

一个比较典型的场景是空调线控器上的彩屏显示,屏幕刷新数据量可能达到几十 KB,如果软件模拟 SPI 的 GPIO 翻转,主频会被大量耗时操作占用,屏幕刷新不流畅。推荐的方案是开启硬件 SPI 的 DMA 发送,主控只需要把要显示的帧缓冲区地址交给 DMA 控制器,传输完成后再触发中断。参考代码:

// 伪代码:SPI DMA 发送显示缓冲区 void lcd_dma_send(uint8_t *buf, uint32_t len) { while (DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET); DMA_ClearFlag(DMA1_FLAG_TC2); SPI_DMACmd(SPI1, SPI_DMAReq_TX, ENABLE); DMA_Cmd(DMA1_Channel2, ENABLE); }

注意 SPI 有四种模式(CPOL/CPHA 组合),不同从机要求不同。很多初学者在这上面踩坑,现象是“读出来的数据全是 0xFF”或者“屏幕有噪声条纹”。排查办法是用逻辑分析仪抓 SCLK、MOSI、CS 波形,对照从机数据手册中的时序要求逐项检查。另一种容易出问题的场景是 Flash 擦写时关闭了中断导致指令超时,或者 SPI 时钟速率超过 Flash 芯片最高规格造成数据写入不稳定。在量产产品里,SPI Flash 写入异常可能导致空调故障记录无法保存,这个坑相当隐蔽。

2.4 UART(串口)是空调板级与模块通信的中枢

UART(Universal Asynchronous Receiver/Transmitter)是异步串行通信,没有时钟线,通信双方需要约定波特率、数据位、停止位、校验位。空调开发中 UART 使用频率极高,最典型的就是:

  • 主控 MCU 与 Wi-Fi 模块之间的 AT 指令通信。
  • 主控 MCU 与蓝牙模块之间的数据交互。
  • 主控 MCU 与某些传感器模块(PM2.5、CO2、甲醛传感器)之间的串口读取。
  • 调试串口打印日志。

UART 在空调板级通信中的核心作用,可以理解为“主板和外部智能模块之间的翻译官”。尤其 Wi-Fi 模块,无论是 ESP8266、ESP32 还是其他国产 Wi-Fi 模组,初期方案几乎都支持 UART AT 指令方式接入。主控不需要理解 TCP/IP、TLS、JSON 这些复杂概念,只需把 AT 指令按照约定格式通过串口发出,模块就会把数据包转发到云端。

下面是一段常用的连接 Wi-Fi 并建立 MQTT 的 AT 指令示例(以乐鑫 ESP 系列为例,指令细节因固件版本而异):

AT+CWMODE=1 AT+CWJAP="my_wifi_ssid","my_wifi_password" AT+MQTTUSERCFG=0,1,"client_id","username","password",0,0,"" AT+MQTTCONN=0,"mqtt.cloud.example.com",8883,1 AT+MQTTSUB=0,"device/001/publish",0 AT+MQTTPUB=0,"device/001/subscribe","{\"cmd\":\"set_temp\",\"value\":22}",0,0

简单解释一下这段指令:第一条设置 Wi-Fi 模块为 Station 模式;第二条让模块连接家庭路由器;第三条配置 MQTT 用户属性,包括客户端 ID、用户名、密码以及 TLS 服务端证书校验开关;第四条连接 MQTT Broker;第五、六条分别是订阅和发布主题。这种模式下主控 MCU 只需要在串口中断里做字符串解析即可,压力非常小。

UART 调试中最容易忽略的问题是硬件流控和电平匹配。MCU 的 UART 通常是 3.3V TTL 电平,Wi-Fi 模块是 3.3V,但有些 4G 模块需要 1.8V 电平,接反了轻则无响应,重则烧毁模块 GPIO。另外串口的地线必须共地,否则通信会出现随机乱码。量产测试环节还容易出现波特率误差累积问题,建议波特率不要选太高的非标值,9600 和 115200 是行业最稳妥的选择。

3. 机组级通信:CAN 与 RS485/Modbus 造就空调系统的神经网

3.1 为什么空调内部机组通信不用 I2C 或 UART?

空调室内机和室外机之间、多台室内机与室外机之间,不能直接用 I2C 或 SPI 来通信。原因有三:

  • 距离太长。I2C 设计初衷是板级通信,超过 1 米后信号完整性问题会很突出。
  • 干扰太大。空调压缩机启动、风机调速、继电器吸合都会产生强烈电磁干扰。普通 UART 单端信号在这种环境里误码率很高。
  • 节点多,实时性要求高。一拖多多联机系统中,一台室外机可能需要同时和十几台室内机通信,每个室内机都有不同的运行状态和控制指令,必须使用多主或主从轮询效率够高、误码率低的总线方案。

因此空调行业常用的机组级通信协议集中在 CAN 和 RS485 上。

3.2 CAN 总线协议在空调多联机中的应用

CAN(Controller Area Network)总线最初是博世公司为汽车电子设计的,后来大量应用于工业控制和楼宇暖通。CAN 是差分信号传输,使用 CAN_H 和 CAN_L 两根线,抗干扰能力很强。它支持多主通信,任何一个节点都可以主动往总线上发数据,不需要主机轮询,因此响应速度快,非常适合压缩机、电子膨胀阀等需要实时控制的场景。

空调多联机系统中,CAN 通信的主要特点:

  • 波特率通常配置为 5kbps 到 500kbps。空调系统常用 50kbps、125kbps 或者 250kbps,需要根据总线上节点数量和距离来定。
  • 报文采用 ID 优先级仲裁,ID 越小优先级越高。一般把压缩机的控制指令设为高优先级,温度采集等状态上报设为低优先级。
  • 支持错误检测和错误恢复机制,瞬时干扰导致的错误帧可以自动重发。
  • 硬件成本不高,很多 MCU 内置 CAN 控制器,只需要外接一个 CAN 收发器(如 TJA1050、SN65HVD230)。

下面是一个标准 CAN 数据帧的位段结构:

位段功能
SOF帧起始,表示一帧报文开始
仲裁段包含报文 ID 和 RTR 位,决定优先级
控制段包含 IDE、DLC,声明数据长度
数据段要发送的实际数据,最多 8 字节
CRC 段校验数据,检测传输错误
ACK 段接收节点应答,确认已收到报文
EOF帧结束

实际空调开发中,CAN 协议的上层往往还会自定义“应用层协议”。比如规定 0x01 代表室内机运行状态上报,0x02 代表室外机控制指令。报文里第 1 个字节放目标地址,第 2 个字节放源地址,第 3 个字节放指令码,后面字节放参数。不同的空调厂家协议格式差异很大,但核心设计原则都是:ID 尽量体现报文优先级,数据段尽量紧凑且重要信息前置。

CAN 开发调试一个很常见的现象:用 USB-CAN 分析仪连到总线上,发现不停地收到错误帧,或者某个节点总是离线。这通常不是 MCU 代码问题,而是波特率不匹配或终端电阻缺失。CAN 总线两端必须接 120Ω 终端电阻,否则信号在末端反射,波形边沿会产生台阶,误码率飙升。空调内机和外机距离远,如果每个 PCB 都默认不焊终端电阻,联调时就要在总线物理两端额外并联 120Ω 电阻。

3.3 RS485 与 Modbus 协议在空调集控中的兼容性

RS485 也是一种差分总线协议,和 CAN 类似使用双绞线传输,抗干扰能力强,最远通信距离可达 1200 米,支持最多 32 个节点(部分驱动芯片可扩展更多)。但与 CAN 不同,RS485 是半双工、主从模式,总线上的通信完全由主机(集中控制器)发起,从机不能主动上报数据。

空调集控系统中,RS485 最常见的上层协议是 Modbus RTU。Modbus 协议里,每个设备分配一个从站地址(1-247),主机通过“功能码”告诉从机要做什么操作:读保持寄存器、写单个寄存器、写多个寄存器等。空调的开关机、模式设定、设定温度、风扇转速、故障状态都可以映射为不同寄存器地址。

下面是一个 Modbus RTU 读取室内机运行状态的标准帧示例:

请求帧(主机 -> 从机): 地址 功能码 起始寄存器高 起始寄存器低 寄存器数高 寄存器数低 CRC低 CRC高 0x01 0x03 0x00 0x01 0x00 0x06 0x95 0xCB 响应帧(从机 -> 主机): 地址 功能码 字节数 数据区... CRC低 CRC高 0x01 0x03 0x0C 寄存器数据... ...

用一句话拆解请求帧:读取地址为 0x01 的从机,起始寄存器为 0x0001,连续读 6 个寄存器。寄存器地址 0x0001 如果定义为当前运行模式,0x0002 定义为设定温度,0x0003 定义为室内环境温度,那么主机拿到 12 个字节的寄存器值后,就可以解析出这台空调的完整运行状态。

RS485 在空调开发中的坑,主要来自收发切换方向控制和时间间隙控制。RS485 是半双工通信,发送数据前要把 DE/RE 引脚置为发送状态,发完后必须马上切回接收状态,否则会漏掉从机的应答。问题在于 MCU 串口发送寄存器清空和引脚电平翻转之间存在时序空隙,如果代码处理不严谨,最后一个字节容易发送不完全。另一个问题是帧间隔,Modbus RTU 规定两帧之间需要至少 3.5 个字符时间的静默间隔,部分协议栈把这部分实现简化,导致连续快速轮询时从机无法正确切帧。

对于空调外机变频驱动板来说,RS485 的低成本优势依然明显,很多中小功率的单元机仍然选择 RS485 做内外机通信,而不是成本略高的 CAN。如果你在空调企业面试时被问到“为什么有些空调外机用 CAN,有些用 RS485”,可以考虑从成本、实时性、节点数、协议复杂度几个维度回答:多联机对实时性和多主通信要求高,用 CAN;普通单元机成本压力大,控制逻辑简单,用 RS485 足够了。

3.4 总线选择对比:CAN 还是 RS485

把 CAN 与 RS485 放在表格里比较会更直观:

对比项CANRS485
物理层差分两线,CAN_H/CAN_L差分两线,A/B
通信模式多主,任意节点可主动发送半双工,主从模式
最高速率1Mbps(短距离)10Mbps(极短距离)
典型速率125kbps、250kbps9600bps、115200bps
错误处理有硬件错误检测与重发无硬件级错误重发,依赖上层协议
终端电阻两端各 120Ω两端各 120Ω
成本稍高,需要 CAN 收发器较低,硬件简单
应用场景多联机、变频驱动、汽车集控系统、电表、楼宇自控

选择时还要考虑你 MCU 内部是否集成了 CAN 控制器。比如 STM32F103 就带基本扩展 CAN(bxCAN),但很多低成本 MCU 没有 CAN 外设,此时要软件模拟 CAN 或直接选 RS485。部分厂家的方案是 MCU 内部用 SPI 接口外接一个独立的 CAN 控制器(如 MCP2515),再搭配 CAN 收发器,硬件设计就复杂一些了。

4. 从板级走向云端:Wi-Fi 模块与主控 MCU 之间的通信协作

4.1 为什么 AI 空调联网部分依然保留 MCU 架构

市面上很多空调的“智能”体现在 App 远程控制、语音控制、能耗统计、故障主动上报。但即使云平台功能再丰富,空调本体的控制逻辑仍然运行在可靠的 MCU 上。Wi-Fi 模块如果直接接到压缩机控制电路里,一旦模块死机、固件升级失败或者被网络攻击,后果可能非常严重。因此几乎主流空调方案都会采用“MCU + 通信模块”分离的设计:

  • MCU 负责空调核心控制逻辑,包括温度采集、压缩机启停、风机调速、电子膨胀阀控制、故障保护。
  • Wi-Fi 模块负责网络接入、TCP/TLS 连接、MQTT 协议解析、OTA 固件下载。
  • MCU 与 Wi-Fi 模块之间通过 UART 连接,使用私有串口协议或 AT 指令交互。

这种架构的好处是逻辑隔离、职责单一、便于过认证(无线相关的认证主要针对模块),也方便支撑未来的协议升级。MCU 程序可以长时间不做大改,只升级 Wi-Fi 模块固件来适配新的云平台或新的加密方式。

4.2 MCU 与 Wi-Fi 模块的 UART 通信设计

设计 MCU 与 Wi-Fi 模块之间的串口通信,要解决几个关键问题:帧格式、数据校验、分包粘包、应答超时、异常恢复。

一个常见的设计方案如下:

帧头 : 0xAA 0x55 帧长 : 1 字节,表示后续内容长度 命令码 : 1 字节,如 0x01 查询状态,0x02 下发控制 设备地址 : 1 字节 数据区 : N 字节 校验和 : 1 字节(数据累加和或 CRC8) 帧尾 : 0x0D 0x0A

主控 MCU 向 Wi-Fi 模块下发“上报当前温度”命令时,帧内容可能是这样:

AA 55 03 01 01 64 69 0D 0A

拆开解读:

  • AA 55:帧头,表示一帧的开始,防止粘包时字节错位。
  • 03:数据区长度,即后面01 01 64三个字节。
  • 01:命令码,0x01 代表查询当前状态。
  • 01:设备地址,表示内机 1 号机。
  • 64:参数,这里可以是附加参数。
  • 69:前面数据段的校验和。
  • 0D 0A:帧尾。

MCU 的串口接收建议使用环形缓冲区 + 状态机解析的方式。串口中断只负责把字节放入缓冲区,主循环或专用解析任务负责从缓冲区里寻找帧头、提取长度、组装完整帧、校验、分发。不要在串口中断里做耗时的 JSON 解析或字符串格式化,这会导致中断响应超时,丢失后续字节。

4.3 配网方式演变与开发注意点

空调 Wi-Fi 模块要上云,必须先让模块知道家庭 Wi-Fi 的 SSID 和密码。早期空调配网主要在 App 里输入 Wi-Fi 密码,由 App 通过 AirKiss、SmartConfig 等方式把 Wi-Fi 配置信息以广播包形式发给模块。这种方式配网成功率不稳定。

后来逐步演进为热点配网(SoftAP)方式:模块切换到 AP 模式,手机连接模块发出来的热点,然后通过 HTTP 页面或 UDP 协议把 Wi-Fi 信息传给模块,模块再切换回 STA 模式连接路由器。这种方式更稳定,但用户操作步骤多。

再到现在很多智能家居品牌采用“近距离蓝牙配网”方式:模块上集成蓝牙,手机 App 通过蓝牙把 Wi-Fi 信息传给模块,然后用 Wi-Fi 连接,配网成功率大幅提升。空调品类因为设备功率大、安装位置固定,开始大量采用“Wi-Fi + 蓝牙”双模方案。

从开发者角度看,配网相关的关键代码主要在模块侧或 App 侧,MCU 需要关心的核心点是:收到模块“配网完成并成功连接路由器”的事件后,要立即上报设备上线状态给云平台,同时更新本地状态指示,例如让空调面板上的 Wi-Fi 指示灯从快闪变为常亮。

5. 从设备到云端的通信协议:MQTT 与 HTTP/COAP

5.1 MQTT 协议为什么是智能家电上云的主流

设备联网后,主控数据和云平台之间的通信协议非常关键。目前空调行业使用占比最高的应用层协议是 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)。它基于发布/订阅模型,特别适合网络不稳定、设备数量庞大、带宽有限的物联网场景。

MQTT 的核心概念包括 Broker(消息代理服务器)、Topic(主题)、Client 端(发布者和订阅者)、QoS(服务质量)。空调设备和云平台之间的常见 Topic 设计可能是:

空调设备发布上行状态: /product/{productKey}/{deviceName}/thing/event/property/post 云平台下发控制指令: /product/{productKey}/{deviceName}/thing/service/property/set 设备上报事件: /product/{productKey}/{deviceName}/thing/event/{eventId}/post

设备端订阅“属性设置”主题后,平台一旦下发设置目标温度指令,设备端收到 JSON 消息并解析后,把控制参数转成 MCU 协议帧再通过 UART 发送给空调主控。

在嵌入式资源受限环境下,MQTT 客户端库选择也很重要。若使用 ESP32,官方有 esp-mqtt 组件,内部基于 TCP/TLS,支持订阅、发布、遗嘱消息、Keep Alive。下面是一个基于 ESP-IDF 的 MQTT 连接配置参考:

#include "mqtt_client.h" esp_mqtt_client_config_t mqtt_cfg = { .broker.address.uri = "mqtts://mqtt.cloud.example.com:8883", .broker.verification.certificate = server_cert_pem_start, .credentials.username = "thermostat_device_001", .credentials.authentication.password = "device_secret_123", .session.keepalive = 60, }; esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); esp_mqtt_client_register_event(client, ESP_MQTT_EVENT_ANY_EVENT, mqtt_event_handler, NULL); esp_mqtt_client_start(client);

这里特别要提醒安全边界:设备上云必须启用 TLS 加密,并且要校验服务器证书。不要把设备密钥硬编码在客户端代码里,建议在产线上为每台设备烧录唯一的设备证书/密钥,云端再结合设备证书做双向认证。空调被非法控制除了造成财产损失,还可能导致制热环境下超温运行引发安全隐患,所以“设备身份认证”不是可有可无的事,而是底线要求。

5.2 HTTP 与 COAP 协议在空调云通信中的定位

HTTP 协议也常用于设备与云端通信,但它本质是客户端主动请求服务器模式,设备需要不断轮询或依靠长连接,大量不必要的数据交互会导致流量浪费。HTTP 适合设备升级包下载、设备首次激活获取 Token 这类低频、大数据量的场景。

COAP(Constrained Application Protocol)则专为资源受限设备设计,基于 UDP,报文采用二进制格式,比 HTTP 更轻量。不过 COAP 在空调设备中应用并不像 MQTT 那样普遍,因为空调不像传感器节点一样严重受限于电力或带宽,Wi-Fi 模组性能足够跑 MQTT over TLS。COAP 更常见于 NB-IoT、LoRa 等低功耗广域网场景的智能表计和水浸传感器等。

做空调云平台接入时,我的建议是:设备状态上行和控制下行主链路优先考虑 MQTT;OTA 固件升级和日志文件上传用 HTTPS;设备首次配网获取 Token 或证书申请用 HTTPS;不要用 HTTP 明文传输任何控制指令。

5.3 设备端数据格式:JSON 在 MCU 侧的处理策略

云平台和设备之间传输的控制指令,通常使用 JSON 格式,因为便于平台端解析和业务逻辑扩展。但空调整机的主控 MCU 资源往往很紧张,处理 JSON 可能让 ROM 和 RAM 都压力山大。这种矛盾的解决方案是:

  • Wi-Fi 模块负责 JSON 的编码与解析:模块收到云平台下发的 JSON 消息后,先解析提取字段,再打包成紧凑的二进制帧发给 MCU。
  • MCU 只管私有二进制协议:MCU 不解析 JSON,只需按帧格式收发数据。比如收到“设定温度 22℃”的二进制帧,提取温度字段即可执行后续逻辑。

反过来,MCU 上报状态时,也是先发给模块一个紧凑的二进制状态帧,模块负责包装成 JSON 并通过 MQTT 发布。这个架构的关键是 MCU 和模块之间需要定义一套足够清晰、可扩展的串口映射表:

0x10 查询设备基本信息 0x11 上报设备运行状态(温度、模式、风速) 0x12 设置运行模式(制冷/制热/除湿/送风) 0x13 设置目标温度 0x14 设置风速 0x15 查询故障状态

如果 MCU 资源实在紧张到无法处理复杂状态机,也可以考虑在 MCU 上使用轻量 JSON 库(如 cJSON),但只建议用于调试阶段,不建议在生产固件里大量解析 JSON。因为 JSON 解析天然存在内存碎片、深层嵌套解析不完备等问题,会让系统稳定性打折扣。

6. 空调通信联调实战:一条“设 22 度”指令的完整链路

6.1 设备端软件模块划分

前面聊了这么多协议,下面用一个具体场景把整个联调过程串起来。假设我们要实现:“用户从手机 App 把空调设定温度从 26℃ 改为 22℃。” 涉及的模块包括:

  • 手机 App
  • 云平台 MQTT Broker
  • 家庭 Wi-Fi 路由器
  • 空调 Wi-Fi 模块
  • 空调内机主控 MCU
  • 室内外机通信总线(假设是 CAN bus)
  • 室外机变频驱动板

6.2 云平台下发的报文格式示例

手机 App 点击“22℃”按钮后,云平台将控制指令包装成一条 MQTT 消息。Topic 是设备订阅的属性设置主题,Payload 如下:

{ "method": "thing.service.property.set", "id": "123456", "params": { "target_temp": 22, "unit": "celsius" }, "version": "1.0" }

Wi-Fi 模块收到后,先解析 JSON,提取params.target_temp = 22,再根据模块协议映射表,把它转成一条发给内机主控 MCU 的串口二进制帧:

AA 55 05 22 01 02 00 16 40 0D 0A

字段拆解:

  • AA 55:帧头。
  • 05:数据区长度(后面 5 个字节)。
  • 22:设备地址,表示内机 1 号。
  • 01:命令码,0x01 表示控制命令。
  • 02:控制类型,0x02 表示设置目标温度。
  • 00 16:大端表示目标温度 0x0016,即十进制 22。
  • 40:前面数据的校验和(这里按累加和计算)。
  • 0D 0A:帧尾。

6.3 MCU 收到指令后的处理流程

内机主控 MCU 的 UART 接收状态机解析到一帧完整数据后,先从校验和确认数据没有被破坏,再根据命令码分发到温度控制模块。这个判断过程可以用一个简化函数表示:

int temp_control_handle_frame(const uint8_t *frame, uint16_t len) { if (!check_frame_crc(frame, len)) { return -1; } uint8_t dev_addr = frame[2]; uint8_t cmd = frame[3]; uint8_t ctrl_type = frame[4]; if (cmd != 0x01) { return -2; } if (ctrl_type == 0x02) { // 设置目标温度 int16_t target_temp = ((int16_t)frame[5] << 8) | frame[6]; target_temp = (target_temp > 3000) ? 3000 : (target_temp < 1600) ? 1600 : target_temp; system_set_target_temp(target_temp / 100.0f); return 0; } return -3; }

注意这里我使用了target_temp / 100.0f的换算逻辑,因为部分帧协议为了避免小数会把温度乘以 100 再传输,比如 22.00℃ 就是 2200。实际工程中这个精度可以根据需求调整,用 10 倍还是 100 倍,需要和云端定好数据定义,避免出现“设置 22℃,空调却跑到了 2200℃”的笑话。

内机 MCU 更新目标温度后,需要通过 CAN 总线把新的目标温度同步给室外机。假设 CAN 报文的 ID 为 0x0A(高优先级控制帧),数据格式如下:

CAN ID : 0x0A DLC : 0x08 数据字节0 : 源地址 0x01(室内机) 数据字节1 : 目标地址 0x10(室外机) 数据字节2 : 控制码 0x03(温度设定) 数据字节3 : 温度整数部分 22 数据字节4 : 温度小数部分 0 数据字节5 : 备用 0x00 数据字节6 : 备用 0x00 数据字节7 : 校验和或计数器

发送代码参考:

void can_send_target_temp(uint8_t src, uint8_t dst, float temp) { CAN_TxHeaderTypeDef tx_header; uint8_t tx_data[8]; tx_header.StdId = 0x0A; tx_header.IDE = CAN_ID_STD; tx_header.RTR = CAN_RTR_DATA; tx_header.DLC = 8; tx_data[0] = src; tx_data[1] = dst; tx_data[2] = 0x03; tx_data[3] = (uint8_t)((int)temp); tx_data[4] = (uint8_t)((temp - (int)temp) * 10); tx_data[5] = 0x00; tx_data[6] = 0x00; tx_data[7] = 0x00; if (HAL_CAN_AddTxMessage(&hcan1, &tx_header, tx_data, &tx_mailbox) != HAL_OK) { // 错误处理,例如总线繁忙时重试 } }

室外机收到 CAN 报文后,解析出目标温度,再结合室内环境温度、蒸发器管温、室外环境温度等参数进行压缩机目标频率计算。这部分涉及变频空调的核心控制逻辑“PID + 模糊算法”,虽然不属于通信协议范围,但通信的实时性和可靠性直接决定了控制算法能不能拿到准确输入。如果 CAN 报文延迟 100ms,也许还能容忍;如果报文丢失导致室外机频繁启停,那通信问题就被转化成了整机性能投诉。

6.4 室外的数据上行:状态上报链路

空调执行温度设定后,需要把最新状态上报到云端,让 App 界面更新。完整的反馈路径为:

外机控制结果 -> (CAN)-> 内机 MCU -> (UART)-> Wi-Fi 模块 -> (MQTT over TLS)-> 云平台 -> App

内机 MCU 把最新的运行状态打包成二进制帧给 Wi-Fi 模块,模块负责 JSON 编码和 MQTT 发布:

{ "method": "thing.event.property.post", "id": "654321", "params": { "target_temp": 22, "current_temp": 26.5, "mode": "cool", "fan_speed": "auto", "power": "on" }, "version": "1.0" }

云平台解析这条状态后,会比对设备影子(Device Shadow)中保存的期望值与设备实际报告值是否一致。如果设备已成功执行 22℃,那么影子状态被更新,App 收到推送后展示最新温度。这里有一个常见的开发陷阱:设备端上报要在控制指令执行完成之后触发,不要一收到指令就盲目上报“已执行”,一定要等到传感器或控制步进真正完成后再上报,否则 App 上看到的设置值和实际运行状态不一致,用户就会反复提交指令,造成云端和设备的“指令风暴”。

7. 空调通信协议的调试与测试工具箱

7.1 串口级调试:逻辑分析仪与串口助手

MCU 与 Wi-Fi 模块的 UART 报文调试,建议使用逻辑分析仪抓取真实波形,不要只依赖串口助手打印。逻辑分析仪能直观看到帧头、数据帧间隔、字节之间是否有异常延迟。采样率建议设置为波特率的 8 倍以上,例如波特率 115200 时用 1MHz 采样率,可以清晰看到每个 bit 的电平变化。如果用串口助手透传调试,请关闭“发送新行”里的自动加\r\n选项,否则会莫名多出两个字节,导致对端解析错位。

7.2 CAN 总线调试:CAN 分析仪抓包法

CAN 总线最有效的调试手段是使用 USB-CAN 分析仪,把 PC 接到 CAN 总线中,像抓网络包一样抓取所有 CAN 报文。调试要点:

  • 配置与设备一致的波特率,把比特率误差控制在 0.5% 以内。
  • 在总线空闲状态下观察是否有错误帧或 Bus Off。
  • 如果收不到报文,先用示波器查看 CAN_H 与 CAN_L 之间的差分波形,正常显性电平差约 2V。
  • 使用分析仪的“自发自收”功能验证收发器芯片和 MCU CAN 控制器是否正常。

7.3 MQTT 云端调试:本地 Broker 与抓包

云端联调难度大,容易受到公网波动、证书过期、DNS 解析等因素干扰。推荐的调试方法是先在本地搭建一个 MQTT Broker(如 EMQX、Mosquitto),让设备和本地 Broker 通信,验证设备端协议逻辑。本地调通后再切换到云端环境,逐步排查网络链路。

本地调试时可以在 PC 上开启 Wireshark 抓包,过滤端口 8883 或 1883 查看 MQTT 报文,但需要注意 TLS 加密后内容不可直接读取。如果只是验证连接是否建立,看 TCP 握手与 TLS 握手包就够了。若需要进一步观察业务报文,可以在设备端暂用 1883 明文端口做本地测试,测试完成后必须切回加密端口,避免把安全隐患带入生产环境。

7.4 常见问题排查清单

把空调通信开发中的高频问题整理成一张排查表:

问题现象常见原因解决思路
MCU 读不到 I2C 温湿度数据总线死锁、地址错误、上拉电阻缺失用万用表测量 SDA/SCL 电平,检查从机地址和上拉电阻
SPI Flash 读写数据不稳定CPOL/CPHA 配置错误、时钟过快对照数据手册时序图,降低 SPI 时钟测试
UART 收到数据乱码波特率偏差、地线不共地、干扰使用逻辑分析仪解码,检查共地,降低波特率
Wi-Fi 模块搜索不到家庭网络路由器 5G 频段不兼容、配网流程出错优先用 2.4G Wi-Fi 测试,确认模块进入配网模式
MQTT 连接频繁掉线Keep Alive 过短、网络不稳定根据实际网络环境调整 Keep Alive 为 30-120 秒
CAN 总线错误帧较多波特率不匹配、缺少终端电阻用 CAN 分析仪查错,确认总线两端 120Ω 电阻
设备已执行但 App 状态不更新状态上行上报时机不对确保控制执行完成后再上报状态
设备证书校验失败设备时间错误、根证书过期检查设备 RTC,更新根证书,关闭失效证书缓存

8. 工程最佳实践:把通信可靠性做在产品代码里

空调产品属于“长期在线、低容错”的智能设备,通信链路中的任何一个环节出了故障,轻则控制失灵,重则造成设备损坏。因此从第一天写代码时就要把通信可靠性设计进去。

8.1 帧协议设计:留好版本号与扩展位

无论是板级 UART 私有协议还是 CAN 应用层协议,都应该在协议开头预留一个版本号字段。空调产品生命周期长达 5-10 年,后期增加新风控制、净化模块、语音交互时,如果一开始没有预留协议扩展空间,升级过程就会非常痛苦。我见过一些项目在协议帧里用掉了所有字节,后期为加一个字段不得不整帧重定义,导致老设备固件全部不兼容,只能通过云端 OTA 强刷,升级战线拉得非常长。

8.2 通信超时与重连机制

所有通信链路都要有超时概念。MCU 与 Wi-Fi 模块之间如果超过 5 秒没有收到心跳应答,就应该主动重启模块或做一次 UART 复位。模块与云端断线后,需要按指数退避策略重连(1 秒、2 秒、4 秒……最大 5 分钟),避免在路由器或云端故障恢复时,大量设备同时请求导致服务端压力过大。

设备本地还需要维护一个“平台连接状态标志”。当断网时间过长时,空调应该自动进入“本地控制模式”,用户按面板或遥控器仍然可以正常控制空调,只是无法远程操作。等网络恢复后,设备要把离线期间的状态变化补报给云端,并拉取云端下发的影子消息,确保远端状态与本地真实状态一致。

8.3 数据安全与合法授权

这是空调云通信必须划清楚的红线部分。设备接入云端时,需要保证整个链路使用 TLS 加密,服务端证书校验和客户端证书双向认证不能省。设备身份信息要在产线烧录时写入安全区,一机一密,防止同一套密钥在所有设备间复用被攻破后出现“批量仿冒”。开发者不能为了方便调试而把生产环境密钥、测试账号提交到 Git 仓库。使用云平台时必须遵守服务商的使用协议和当地法律,只接入合法运营的云平台。整机产品若涉及远程控制空调,OTA 升级指令也要在云端做操作者和设备自身的双重校验,防止越权指令下发。

8.4 日志和可观测性

空调设备本身资源有限,无法像服务器一样记录庞大数据日志。但我们需要在关键节点留下轻量痕迹:Wi-Fi 模块启动记录、路由器连接成功点、MQTT 连接成功点、首次上报状态时间点、每次收到控制指令的时间。这些事件用环形日志存储在 Flash 中,用户在售后反馈“空调有时无法远程控制”时,工程师远程拉取设备日志就能快速判断问题是出在 Wi-Fi 模块、路由器连接、MQTT 连接还是 MCU 交互层。

日志设计要遵循“正常不刷屏、异常打关键”原则。例如每 5 分钟定时上报状态是正常行为,不需要每次打印完整 JSON;但连接失败、重连退避、CRC 校验错误、连续控制失败等异常路径必须记录。

8.5 开发阶段建议预留的测试接口

硬件设计阶段建议预留以下调试接口:

  • 主控 MCU 引出独立的 UART 调试串口,不要和 Wi-Fi 模块串口共用。
  • 通信模块底板预留 CAN 收发器接口和终端电阻可选位。
  • 电源设计上,Wi-Fi 模块在发射瞬间会有较大电流波动,要给模块独立 LDO 或 DC-DC,并做好地与主控地之间的单点连接。
  • 预留状态指示灯,至少能区分“模块上电”“Wi-Fi 已连接”“云端已连接”三个阶段。

量产阶段,产线测试要覆盖:Wi-Fi 模块 SSID 扫描、路由器连接、MQTT 连云、设备信息上报、远程控制响应时间。如果这些测试出现在用户家里才第一次跑通,售后成本会成倍上升。

9. 总结与下一步学习路线

空调嵌入式通信开发是一个典型的“层层协议 + 软硬结合”的领域。从本文的梳理可以看出,真正的难点不在于单个协议有多复杂——I2C、UART、CAN、MQTT 每一种单独拿出来都是成熟技术。难点在于把这些协议放到一条完整的数据链路上,让它们在不同层级之间无缝转换,并且在整个生命周期内保持稳定。开发中要形成分层意识:板级解决芯片间的数据搬运,机组级解决强电磁干扰环境下的可靠通信,云端解决设备远程管理与状态同步。

对于刚接触这个方向的同学,建议按这样的顺序逐步深入:

  • 首先用开发板跑通基础总线协议,I2C 读温湿度传感器、SPI 驱动 LCD、UART 与 PC 通信。
  • 然后学习在 MCU 上写一个带状态机的串口帧接收解析器,通过模拟 Wi-Fi 模块下发指令来测试自己的解析逻辑。
  • 再进一步接触 CAN 总线,配合 USB-CAN 分析仪实现两组 MCU 的 CAN 收发通信。
  • 最后把 ESP32 或 Wi-Fi 模块接到云端,跑通 MQTT 发布订阅流程,把传感器数据或控制状态移植到自己的设备协议里。

如果本文对你有帮助,可以收藏备用,后续开发需要时翻到对应章节排查。如果你已经做过空调或其他家电的通信开发,欢迎在评论区分享你遇到过的奇葩通信坑,比如某个“神秘”的校验算法、某种只能在特定批次硬件上复现的总线超时,互相借鉴经验会让后面的开发顺利不少。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 11:27:48

从零开始画卡通小马:结构简化与数字绘画实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 11:26:46

CSS 3D变换与状态管理:从零实现可开合笔记本交互组件

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 11:26:40

Vue3+SpringBoot3小众城市旅游系统实战解析

简介&#xff1a;这是一套面向Web全栈开发者与毕业设计学习者的前后端分离旅游系统源码&#xff0c;聚焦小众城市文旅场景&#xff0c;解决个性化旅游信息获取、在线预订与智能推荐等实际需求。资源采用Vue 3构建响应式前端界面&#xff0c;Spring Boot 3搭建高可用后端服务&am…

作者头像 李华
网站建设 2026/9/5 11:24:59

不会编程也能做AI Agent:无代码搭建与提示词调试实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 11:22:17

AI Agent项目实战推荐:从框架、工具到多Agent协作与编码实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 11:21:38

STM32F103驱动DHT11的时序精度实战指南

简介&#xff1a;本资源是一套基于STM32F103微控制器的DHT11温湿度传感器实战实验工程&#xff0c;面向嵌入式初学者与课程实践者&#xff0c;解决单总线传感器驱动开发、时序精准控制及数据解析等核心难点。压缩包含80个文件&#xff08;294KB&#xff09;&#xff0c;以33个.…

作者头像 李华