STM32F103 格力空调红外协议解析:从示波器波形到C结构体的3步解码法

发布时间:2026/7/9 19:05:13
STM32F103 格力空调红外协议解析:从示波器波形到C结构体的3步解码法 STM32F103格力空调红外协议逆向实战从波形捕获到状态机解码全解析1. 红外协议逆向工程核心方法论当我们面对未知的红外协议时逆向工程的核心在于建立波形特征-数据结构-功能映射的三层解析体系。以格力空调YAPOF3型号为例其协议结构呈现出典型的长帧特征[起始码] [35位数据段] [连接码] [32位数据段] [结束码]通过逻辑分析仪捕获的典型波形特征如下表所示信号类型低电平持续时间高电平持续时间识别要点起始码9000±100μs4500±100μs持续时间显著长于数据位连接码560±50μs20000±500μs高电平持续时间超长数据0560±50μs560±50μs高低电平对称数据1560±50μs1680±50μs高电平持续时间是3倍实战技巧使用STM32的输入捕获功能时建议配置定时器时钟为1MHz1μs分辨率预分频值设为7172MHz/(711)。这样既能保证时间测量精度又不会因计数器溢出丢失长间隔信号。2. 硬件捕获系统搭建2.1 高精度信号捕获方案推荐电路设计采用三级信号调理前端限幅并联5.1V稳压管保护GPIO中间放大LM358搭建100倍增益放大器后级整形施密特触发器(如74HC14)消除抖动// 定时器4输入捕获配置示例 void TIM4_IRQ_Config(void) { TIM_ICInitTypeDef TIM_ICInitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); TIM_ICInitStructure.TIM_Channel TIM_Channel_3; TIM_ICInitStructure.TIM_ICPolarity TIM_ICPolarity_BothEdge; TIM_ICInitStructure.TIM_ICSelection TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter 0x04; TIM_ICInit(TIM4, TIM_ICInitStructure); NVIC_InitStructure.NVIC_IRQChannel TIM4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority 1; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); TIM_Cmd(TIM4, ENABLE); TIM_ITConfig(TIM4, TIM_IT_CC3, ENABLE); }2.2 抗干扰设计要点在红外接收头OUT引脚与地之间并联100nF陶瓷电容使用屏蔽线连接逻辑分析仪在STM32的VDDA引脚增加10μF钽电容滤波软件上采用中值滤波算法处理捕获时间值3. 协议状态机实现3.1 解码状态机设计格力协议解码适合采用五状态有限状态机模型stateDiagram-v2 [*] -- IDLE IDLE -- SYNC: 检测到起始码 SYNC -- DATA_35BIT: 起始码验证通过 DATA_35BIT -- CONNECT: 接收完35位 CONNECT -- DATA_32BIT: 连接码验证通过 DATA_32BIT -- COMPLETE: 接收完32位 COMPLETE -- IDLE: 数据存储完成对应C语言实现typedef enum { STATE_IDLE, STATE_SYNC, STATE_DATA_35BIT, STATE_CONNECT, STATE_DATA_32BIT, STATE_COMPLETE } DecodeState; typedef struct { uint8_t rawData[9]; // 353267bit → 9字节存储 DecodeState state; uint8_t bitCounter; uint32_t lastEdgeTime; } ProtocolDecoder; void ProcessEdge(ProtocolDecoder* decoder, uint32_t currentTime) { uint32_t duration currentTime - decoder-lastEdgeTime; switch(decoder-state) { case STATE_IDLE: if(IsStartCode(duration)) { decoder-state STATE_SYNC; memset(decoder-rawData, 0, sizeof(decoder-rawData)); } break; case STATE_SYNC: if(IsStartCodeEnd(duration)) { decoder-state STATE_DATA_35BIT; decoder-bitCounter 0; } break; case STATE_DATA_35BIT: if(decoder-bitCounter 35) { uint8_t bitValue DecodeBit(duration); uint8_t bytePos decoder-bitCounter / 8; uint8_t bitPos decoder-bitCounter % 8; decoder-rawData[bytePos] | (bitValue bitPos); decoder-bitCounter; } else { decoder-state STATE_CONNECT; } break; // 其他状态处理... } decoder-lastEdgeTime currentTime; }3.2 校验算法逆向格力空调协议的校验算法具有型号差异性通过实测多款遥控器发现常见校验模式简单求和校验对前6字节数据求和取低4位异或校验特定字节进行异或运算模式相关校验与工作模式、温度参数关联典型校验函数实现uint8_t CalculateChecksum(const uint8_t* data) { // 实测某型号校验算法 uint8_t sum (data[0] 0x0F) (data[1] 4); sum (data[2] 0x03) (data[3] 5); return (sum 0x0F) ^ 0x05; // 异或固定值 }4. 数据帧结构解析4.1 功能位域映射通过解析数百组实测数据得出格力空调典型控制帧结构typedef struct __attribute__((packed)) { // 字节0 uint8_t mode : 3; // 000-自动 001-制冷 010-除湿 011-送风 100-制热 uint8_t power : 1; // 0-关机 1-开机 uint8_t fanSpeed : 2; // 00-自动 01-低速 10-中速 11-高速 uint8_t swingV : 1; // 垂直扫风 uint8_t sleep : 1; // 睡眠模式 // 字节1 uint8_t temp : 4; // 16-30℃ (实际值16value) uint8_t turbo : 1; // 强力模式 uint8_t light : 1; // 显示屏开关 uint8_t eco : 1; // 节能模式 uint8_t swingH : 1; // 水平扫风 // 字节2-3为定时设置 // 字节4-5为扩展功能 // 字节6-7为校验和及保留位 } GreeControlFrame;4.2 实测数据对照表功能数据位范围十六进制值实际效果制冷26℃字节1[3:0]0x0A261610高速风字节0[5:4]0x03二进制11对应高速开启垂直扫风字节0[6]0x40位6置1ECO模式字节1[6]0x40单独设置该位无效注部分功能需要组合设置如ECO模式需同时设置温度在26℃以上5. 工程实践中的陷阱规避5.1 典型问题解决方案信号抖动问题硬件在接收头输出端增加RC滤波1kΩ100nF软件连续3次采样一致才确认边沿长帧丢失问题// 在定时器溢出中断中处理 void TIM4_IRQHandler(void) { if(TIM_GetITStatus(TIM4, TIM_IT_Update)) { if(decoder.state ! STATE_IDLE) { decoder.state STATE_IDLE; // 超时重置 } TIM_ClearITPendingBit(TIM4, TIM_IT_Update); } }校验失败问题建立校验规则库尝试多种已知算法对固定型号记录校验位位置5.2 性能优化技巧时间临界代码优化; 边沿处理关键段用汇编优化 ProcessEdge PROC LDR R1, [R0, #lastEdgeTime] SUB R2, R3, R1 ; 计算时间差 STR R3, [R0, #lastEdgeTime] ; 状态判断逻辑... BX LR ENDP内存优化使用位域结构体节省存储空间双缓冲机制一组解析时另一组可处理功耗控制void EnterLowPowerMode(void) { GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin IR_RX_PIN; GPIO_InitStruct.GPIO_Mode GPIO_Mode_IPU; // 上拉输入 GPIO_Init(IR_RX_PORT, GPIO_InitStruct); EXTI_ClearITPendingBit(EXTI_LineX); EXTI_InitStructure.EXTI_Line EXTI_LineX; EXTI_InitStructure.EXTI_Mode EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger EXTI_Trigger_Rising_Falling; EXTI_Init(EXTI_InitStructure); NVIC_EnableIRQ(EXTIx_IRQn); __WFI(); // 等待中断唤醒 }6. 进阶应用场景6.1 多协议兼容设计通过协议自动识别技术实现万能遥控typedef enum { PROTOCOL_GREE, PROTOCOL_NEC, PROTOCOL_RC5, PROTOCOL_UNKNOWN } IRProtocolType; IRProtocolType DetectProtocol(const uint32_t* edges, uint16_t count) { if(count 0) return PROTOCOL_UNKNOWN; // 检测格力协议特征 if((edges[0] 8500) (edges[0] 9500) (edges[1] 4000) (edges[1] 5000)) { return PROTOCOL_GREE; } // 检测NEC协议特征 if((edges[0] 8000) (edges[0] 10000) (edges[1] 4000) (edges[1] 5000)) { return PROTOCOL_NEC; } return PROTOCOL_UNKNOWN; }6.2 云端联动实现通过MQTT协议将本地解码结果上传至物联网平台void PublishToCloud(const GreeControlFrame* frame) { char topic[50]; sprintf(topic, device/%s/ir, DEVICE_ID); cJSON* root cJSON_CreateObject(); cJSON_AddNumberToObject(root, power, frame-power); cJSON_AddNumberToObject(root, temp, 16 frame-temp); cJSON_AddStringToObject(root, mode, GetModeString(frame-mode)); char* jsonStr cJSON_PrintUnformatted(root); MQTT_Publish(topic, jsonStr, strlen(jsonStr), QOS1); cJSON_Delete(root); free(jsonStr); }在实际项目中建议结合信号质量分析工具如PulseView验证解码准确性。某次实测中发现格力新款空调在ECO模式下会额外发送一帧辅助控制指令这种情况需要特别处理。