从波形到指令:深度拆解格力空调红外协议

📅 发布时间:2026/7/8 5:35:14 👁️ 浏览次数:
从波形到指令:深度拆解格力空调红外协议
1. 从一串“嘀嘀”声开始红外协议逆向工程到底在玩什么大家好我是老张一个在智能硬件和嵌入式领域摸爬滚打了十多年的老玩家。今天我们不聊那些高大上的AI模型来点接地气的“硬核”手艺——拆解你家格力空调遥控器发出的那串红外信号。你可能觉得这玩意儿有啥好研究的按一下遥控器空调“嘀”一声就工作了。但如果你是一个物联网开发者或者是一个喜欢折腾智能家居的硬件爱好者这串看不见的红外光就是你让旧空调变“智能”的钥匙。想象一下这个场景你手头有一台逻辑分析仪或者一个简单的红外接收头加单片机你抓取到了遥控器按下“制冷25度”时发出的原始波形。屏幕上显示的是一连串高低起伏的方波就像心电图一样。你的任务就是像破译密码一样弄明白这串“嘀嘀嗒嗒”背后到底说了什么。最终目标是写出一份协议文档让一块ESP32开发板或者一个单片机也能模仿遥控器精准地控制空调。这个过程我们称之为“红外协议逆向工程”。今天我就以格力空调为例带大家走一遍从原始波形到可编程指令的完整拆解之路内容会比网上常见的解析更深入、更实操我会把踩过的坑和验证过的方法都分享出来。2. 红外通信的“摩斯电码”基础原理扫盲在动手拆解格力协议之前我们得先统一语言理解红外通信最基本的工作原理。这就像学外语先学字母一样。2.1 载波信号的“搬运工”红外通信不是直接用高低电平来表示0和1的。如果直接发射环境中的普通红外光源比如太阳、白炽灯就会产生巨大干扰。所以工程师们想了个办法调制。他们选用了一个频率固定通常是38kHz的方波作为载波。这个载波本身不携带信息它的作用就像一辆卡车。真正的数据0和1是通过控制这辆“卡车”是否发出红外光来传递的。具体来说发射管会以38kHz的频率疯狂闪烁即发出载波但我们会控制它闪烁的“时间段”。在需要发送信号的时间段内载波开启红外接收头收到这个特定频率的闪烁就会输出低电平在不需要发送信号的时间段内载波关闭接收头收不到38kHz的信号就输出高电平。所以我们最终在逻辑分析仪上看到的波形其实是接收头输出的、已经解调掉38kHz载波之后的数据电平信号。记住我们后续分析的所有高低电平时序都是指这个数据电平。2.2 编码0和1的“长相”去掉了38kHz的载波“背景音”数据本身的0和1如何区分呢这就靠脉冲宽度编码。最常见的编码方式是NEC协议用的那种但格力空调用的是一种自定义的格式。不过万变不离其宗核心思想就是用“低电平高电平”的组合来代表一个比特位而0和1的区别在于高电平部分的持续时间不同。举个例子格力空调的协议里这是我实测多款格力遥控器总结的比特‘0’可能是646微秒的低电平紧接着516微秒的高电平。比特‘1’同样是646微秒的低电平但后面跟着的是1643微秒的高电平。你看低电平时间是一样的起跑线相同但高电平“坚持”的时间长短不一这就区分了0和1。这个时间参数非常关键不同品牌、甚至同品牌不同型号都可能不同所以必须用自己的逻辑分析仪抓取确认网上查到的只能作为参考。3. 捕获与测量用逻辑分析仪看清波形真面目理论说再多不如动手抓一包数据看看。这里假设你已经有了逻辑分析仪Saleae Logic系列、DSView配廉价山寨探头都行并且接到了红外接收头的信号输出脚。3.1 连接与抓取步骤首先把红外接收头的VCC和GND接好信号线OUT接到逻辑分析仪的一个通道上。打开遥控器对准接收头按下某个键比如“开关”。在逻辑分析仪软件里设置一个合适的采样率比如1MHz就足够然后触发抓取。你会在屏幕上看到一串密集的脉冲。这里有个关键技巧一次按键发射的往往不止一帧数据。格力遥控器通常会连续发送相同的两到三帧数据以确保接收的可靠性。所以我们要在波形里找到那一段重复的、完整的信号段作为分析对象。3.2 关键时序的测量与确认抓取到稳定波形后我们需要用测量工具精确读出几个关键时间参数。这是我反复实测后为某款主流格力空调总结的典型值强烈建议你以自己的测量为准信号单元低电平时间 (us)高电平时间 (us)说明起始码90004500一帧数据的开始非常长的低电平很好识别连接码64620000分隔两段数据的桥梁高电平超长结束码646(很长)帧结束高电平持续到下次发送数据 ‘0’646516高电平较短数据 ‘1’6461643高电平较长约是‘0’的3倍怎么测量呢在软件里框选从一个下降沿开始到下一个下降沿之前的那个高电平脉冲。测量其高电平的持续时间。多测量几个‘0’和‘1’看看是否稳定。这里容易踩坑环境光干扰、接收头质量、探头接触都可能让波形边沿有点“毛刺”导致测量值有几十微秒的波动。只要波动在合理范围比如±50us内取个平均值或众数即可不必追求绝对精确。4. 拆解数据帧结构格力协议的“语法规则”现在我们知道了字母0和1怎么写接下来要看它们怎么组成单词和句子也就是帧结构。格力空调的一帧完整红外数据结构很有特点它分为两段[起始码] [第一段数据35位] [连接码] [第二段数据32位] [结束码]是的你没看错第一段是35位不是常见的8的倍数。这增加了点解析难度。整个帧看起来会很长因为起始码和连接码的时长非常夸张在波形上显得格外突出这反而成了我们定位的“路标”。4.1 起始、连接与结束帧的标点符号起始码一个长达9000us的低电平加上4500us的高电平。这个组合在数据流中独一无二是帧开始的绝对标志。在解析程序里我们首先就要在连续的电平信号中搜索这个特殊的模式来找到一帧的头部。连接码位于两段数据之间646us低电平后跟一个长达20ms的高电平。这个20ms的空白在波形上是一段漫长的“平坦”区域清晰地将前后数据分开。结束码第二段数据后的646us低电平之后高电平会一直持续。实际上在程序处理时我们更关注数据位的结束这个结束码更多是一个自然的停止。理解这些“标点”后我们就可以用程序逻辑来分割数据了找到起始码 - 读取后续的35个比特 - 跳过连接码 - 再读取32个比特 - 一帧结束。4.2 数据0与1的解析算法在代码里我们如何将连续的波形翻译成0和1的二进制串呢下面是一个简单的算法思路你可以用C、Python或Arduino IDE来实现持续监测输入引脚的电平。检测到一个下降沿从高到低时开始计时低电平持续时间。如果这个低电平时间在646us左右例如600-700us范围内则认定它是一个有效比特的开始。低电平结束后进入高电平计时高电平持续时间。根据高电平的时长判断比特值如果高电平时间在400-600us左右判定为比特‘0’。如果高电平时间在1500-1800us左右判定为比特‘1’。如果时间不符合则可能是误码或帧头/连接码需要特殊处理。将这个比特存入缓冲区继续等待下一个下降沿。注意实际编写时要考虑定时器的精度和中断处理。对于发送端逻辑相反要严格按照时序控制红外发射管输出对应的低高电平组合。5. 数据位深度解析每个比特管什么这是逆向工程最核心、也最有趣的部分——给每个比特位赋予意义。我们以“制冷25℃低风速开机”这个常用状态为例把抓取到的二进制数据摊开来对照遥控器功能一个个试。5.1 第一段数据35位功能映射经过大量测试和交叉验证我梳理出第一段数据中关键比特位的功能。请注意不同型号可能存在差异以下映射常见于许多格力型号但务必以你实测为准。Bit 3 (第4位)电源开关0 关闭空调1 打开空调这个位非常稳定是必改的位。Bit 4 Bit 5风速控制00 自动风Auto10 一级风低风01 二级风中风11 三级风高风注意这里的二进制顺序有时需要反转一下才能直观理解实际测试时发送10看看是不是低风。Bit 6扫风开关水平扫风0 扫风关闭1 扫风开启这个位需要和第二段数据的Bit 0联动两者通常保持一致。Bit 8, 9, 10, 11温度设置这4个比特以某种编码表示设定温度。常见的映射关系如下以16-28度为例0000: 16℃1000: 17℃0100: 18℃1100: 19℃0010: 20℃1010: 21℃0110: 22℃1110: 23℃0001: 24℃1001: 25℃ 我们的例子0101: 26℃1101: 27℃0011: 28℃看起来有点乱但其实有一定规律可以理解为“温度值-16”的某种二进制变形。直接查表是最稳妥的。Bit 15定时开关0 定时功能关闭1 定时功能开启这个位开启后后面的定时时间位才有效。Bit 16-19定时小时数当定时开启时这几位表示定时的小时部分。例如1000可能代表1小时0100代表2小时等等。需要结合定时分钟数一起解析。5.2 第二段数据32位与校验码第二段数据的前面部分可能包含模式制冷、制热、除湿等等信息但不同型号差异极大。有一个位是相对统一的Bit 0扫风开关再次出现通常与第一段的Bit 6值相同。修改扫风状态时需要同时改变这两个位。最最重要的是第二段数据的最后4位Bit 28-31这是校验码。校验码是协议为了防止传输错误或验证数据合法性而设置的。网上流传很多格力校验码公式比如“和校验”或“取反”但我实测发现并不通用。我通过大量数据反推找到一个在我测试的几款格力空调上有效的经验公式校验码 (设定温度 - 18) 定时小时数 (开关状态 × 8)其中开关状态开机为1关机为0。以“开机、25℃、不定时”为例校验码 (25-18) 0 (1*8) 7 8 15。15的十六进制是0xF二进制是1111。你去看抓到的数据帧最后4位很可能就是1111。重要提醒这个公式是我自己试出来的可能不适用于所有格力机型。最可靠的方法是你固定其他所有参数只改变温度观察校验码的变化规律自己归纳出公式。校验码是协议逆向的最后一道关卡必须攻克。6. 从协议到代码构建你的红外指令库当我们完整掌握了波形时序、帧结构和数据位映射后就可以动手创建一份可编程的协议字典了。这份字典本质上就是一个函数输入是“开关、温度、风速”等参数输出是一个符合格力红外协议的、代表高低电平时序的数组。6.1 构建数据帧函数以Arduino平台为例我们可以这样设计一个发送函数// 定义时序常量单位微秒 #define START_LOW 9000 #define START_HIGH 4500 #define CONNECT_LOW 646 #define CONNECT_HIGH 20000 #define BIT_ZERO_LOW 646 #define BIT_ZERO_HIGH 516 #define BIT_ONE_LOW 646 #define BIT_ONE_HIGH 1643 void sendGreeIR(bool power, int temp, int fanSpeed, bool swing) { // 1. 创建缓冲区存放最终的脉冲时序低、高、低、高... unsigned int rawData[67 * 2]; // 估算大小实际需计算 int index 0; // 2. 添加起始码 rawData[index] START_LOW; rawData[index] START_HIGH; // 3. 根据参数计算第一段35位数据 unsigned long segment1 0; // 设置Bit3: 电源 if(power) segment1 | (1UL 3); // 设置Bit4-5: 风速假设fanSpeed: 0Auto,1Low,2Mid,3High segment1 | ((fanSpeed 0x03) 4); // 设置Bit6: 扫风 if(swing) segment1 | (1UL 6); // 设置Bit8-11: 温度 (需要查表或计算) unsigned char tempCode getTempCode(temp); // 自定义函数根据温度返回4位编码 segment1 | ((tempCode 0x0F) 8); // ... 设置其他位模式、定时等假设为默认值 // 4. 将segment1的35位按位转换为时序填入rawData for(int i34; i0; i--) { // 从高位开始发送 rawData[index] BIT_ZERO_LOW; // 低电平时间固定 if((segment1 i) 0x01) { rawData[index] BIT_ONE_HIGH; } else { rawData[index] BIT_ZERO_HIGH; } } // 5. 添加连接码 rawData[index] CONNECT_LOW; rawData[index] CONNECT_HIGH; // 6. 计算第二段32位数据包含校验码 unsigned long segment2 0; // 设置Bit0: 扫风与第一段一致 if(swing) segment2 | (1UL 0); // ... 设置其他位 // 计算校验码 unsigned char checksum (temp - 18) 0 (power ? 8 : 0); // 简化公式 segment2 | ((checksum 0x0F) 28); // 7. 将segment2的32位按位转换为时序填入rawData for(int i31; i0; i--) { rawData[index] BIT_ZERO_LOW; if((segment2 i) 0x01) { rawData[index] BIT_ONE_HIGH; } else { rawData[index] BIT_ZERO_HIGH; } } // 8. 添加结束码低电平部分 rawData[index] BIT_ZERO_LOW; // 结束码低电平 // 高电平部分在发送函数中处理为一段延时 // 9. 调用底层红外发射函数发送rawData数组 irSender.sendRaw(rawData, index, 38); // 38代表38kHz载波频率 }6.2 调试与验证让空调听你的话代码写好了怎么验证最好的方法就是搭建一个简单的发射电路。用一个NPN三极管如8050驱动一个红外发射二极管单片机引脚通过一个100欧姆左右的电阻连接到三极管基极发射管串联一个限流电阻比如100欧姆接在VCC和集电极之间。上传代码后用手机摄像头大部分手机摄像头能看到红外光对着发射管按下测试按钮。你应该能看到发射管发出微弱的紫光这是红外光被摄像头转换后看到的。然后拿着这个自制发射器对准空调尝试发送开机、调温指令。调试过程中常见的坑空调没反应首先检查硬件连接和电源。然后用逻辑分析仪抓一下你发射的波形和原装遥控器的波形对比看时序对不对。最常见的问题是时序单位弄错微秒当成毫秒或者载波频率不对。空调反应错乱比如开机变成关机。这大概率是数据位映射错了。回去仔细核对是哪个功能位出了问题可以尝试只修改一个位比如只改温度发送后观察空调反应进行“二分法”排查。校验码错误空调可能完全不理睬或者执行一次后不再响应。这说明你的校验码计算错误。老老实实多抓几组不同状态下的原装信号用排除法推导校验算法。这个过程需要耐心但当你亲手让ESP32成功控制空调的那一刻成就感是非常足的。这份你自己逆向出来的协议文档和代码就是最宝贵的资产。以后无论遇到什么型号的格力空调你都有了快速上手分析的能力。红外协议逆向就像一门手艺掌握基本方法后剩下的就是经验和细心。希望这篇超详细的拆解能帮你打开这扇门。