(红外遥控)STM32+红外模块控制格力空调

 

其他红外介绍不多说了,下面介绍一下我使用stm32控制格力空调所遇到问题。

1.红外实现过程中遇到的问题

   网上大部分对格力空调红外编码的介绍都是

    起始码(S)+35位数据码+连接码(C)+32位数据码

 

0的电平宽度为:620us低电平+540us高电平,

1的电平宽度为:620us低电平+1620us高电平

起始码S电平宽度为:9000us低电平+4500us高电平

连接码C电平宽度为:620us低电平+20000us高电平

以上是在接受端的定义,要注意分辨。发射端是相反的

红外发射端的波形。

74815d1f91b445faa56bb5f20da38639.png

红外接受端是以下这种

366726d11e8d467a975c66096662340b.png

两者是不同的。网上大多是第二种容易产生误解。

格力空调的编码如下图——

d799f9a0f461468082b8a6ae26d8b2b7.png

网上的格式都大同小异对红外的编码产生的影响不大。

根据实际的使用,我发现我所使用的遥控器是如下这中格式,末尾的连接码不可缺少。

起始码(S)+35位数据码+连接码(C)+32位数据码+连接码(C)

而且红外遥控器会以两倍的连接码时间间隔发送两次命令。

以上是我实现红外过程中遇到的问题。

2.实现方法

使用stm32的pwm功能发出38kHz的载波,然后控制占空比以达到高低电平的实现。

//38kHz初始化
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);	//打开定时器2的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//打开GPIOA的时钟			/*注意:只有部分端口才有PWM功能*/

	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM2);	//设置定时器2的时钟源为内部时钟源
	
	TIM_TimeBaseInitTypeDef TimBaseInitStructure;		//设置时基单元
	TimBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;		
	TimBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; 	//设置计数模式为向上计数
	TimBaseInitStructure.TIM_Period = 101-1;		//ARR(自动重装器,设置计数峰值)
	TimBaseInitStructure.TIM_Prescaler = 19-1;		//PSC(预分频器,设置计时频率)
	TimBaseInitStructure.TIM_RepetitionCounter = 0;	//设置计数重装值
	TIM_TimeBaseInit(TIM2, &TimBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;		//设置输出比较单元
	TIM_OCStructInit(&TIM_OCInitStructure);		//先对TIM_OCInitStructure所有成员赋值,之后只会对部分成员重新赋值,防止出现部分成员未赋值情况
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;	//设置输出比较模式为PWM1模式
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;	//输出比较极性(设置REF,有效电平为高电平)
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//输出状态使能
	TIM_OCInitStructure.TIM_Pulse = 0;		//CRR(输出比较值)
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);	//使用输出比较通道2
  TIM_Cmd(TIM2,ENABLE);	//定时器2使能

编码格式的实现

typedef struct{
    // Byte 0
    uint8_t Mode      :3;
    uint8_t Power     :1;
    uint8_t Fan       :2;
    uint8_t SwingAuto :1;
    uint8_t Sleep     :1;
    // Byte 1
    uint8_t Temp        :4;
    uint8_t TimerHalfHr :1;
    uint8_t TimerTensHr :2;
    uint8_t TimerEnabled:1;
    // Byte 2
    uint8_t TimerHours:4;
    uint8_t Turbo     :1;
    uint8_t Light     :1;
    uint8_t anion     :1;  // model==YAW1F
    uint8_t Powersv   :1;
    // Byte 3
    uint8_t unknown0        :2;//00
    uint8_t TempExtraDegreeF:1;
    uint8_t UseFahrenheit   :1;
    uint8_t unknown1        :4;  // value=0b0101
    // Byte 4
    uint8_t SwingV      :4;
    uint8_t SwingH      :3;
    uint8_t unknown2     :1; //0
    // Byte 5
    uint8_t DisplayTemp :2;
    uint8_t IFeel       :1;
    uint8_t unknown3    :3;  // value = 0b100 
    uint8_t WiFi        :1;  //0
    uint8_t unknown4    :1;    //0
    // Byte 6
    uint8_t unknown5   :8;  //00000000
    // Byte 7
    uint8_t unknown6    :2; //00
    uint8_t Econo       :1;
    uint8_t unknown7    :1;//0
    uint8_t Sum         :4;
  }Protocol;
//红外码初始化

 以及发送过程,发送都是逆序的即从低向高为发送。

void IR_Send38kHz(uint16_t time,FunctionalState NewState){
	if(NewState == 1){
		TIM_SetCompare2(TIM2,0);
	  Delay_us(time);}
	else
	{
		TIM_SetCompare2(TIM2,50);
	  Delay_us(time);
	}
};

void IR_SendGreeH(void){
    TIM_SetCompare2(TIM2,50);
	  Delay_us(GreeBitMark);
	  TIM_SetCompare2(TIM2,0);
	  Delay_us(GreeOneSpace);
};

void IR_SendGreeL(void){
    TIM_SetCompare2(TIM2,50);
	  Delay_us(GreeBitMark);
	  TIM_SetCompare2(TIM2,0);
	  Delay_us(GreeZeroSpace);
};

void IR_SendMsg(uint8_t cnt,uint8_t data){
     while(cnt--){
	   if(data&0x01){
     IR_SendGreeH();
		 data=data>>1;}
		 else{
		 IR_SendGreeL();
		 data=data>>1;
		 }
	 }
};

特别注意校验码的计算,网上有很多公式。下面我给出一种

校验码 = [(模式 – 1) + (温度 – 16) + 5 +左右扫风+换气+节能]取二进制后四位;

源码链接:

https://pan.quark.cn/s/a5cb41cadaec

参考博客

GitHub - crankyoldgit/IRremoteESP8266: Infrared remote library for ESP8266/ESP32: send and receive infrared signals with multiple protocols. Based on: https://github.com/shirriff/Arduino-IRremote/

【智能电表】格力空调遥控器红外协议_格力空调红外协议-CSDN博客

格力空调遥控器红外编码透析(长码)_格力空调红外编码-CSDN博客

[LPC54102]红外编码与解码——GREE格力遥控 - NXP MCU - 电子工程世界-论坛 (eeworld.com.cn)

 

 

 

 

  • 28
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
格力空调遥控信号的编码格式为自定义格式,需要先进行信号录制和解码,然后根据解码结果来编写解析程序。以下是基于 STM32格力空调遥控信号解析程序: ```c #include "stm32f10x.h" #define IR_PIN GPIO_Pin_0 #define IR_GPIO GPIOA #define IR_EXTI EXTI_Line0 #define IR_EXTI_PORT_SOURCE GPIO_PortSourceGPIOA #define IR_EXTI_PIN_SOURCE GPIO_PinSource0 #define IR_TIM TIM2 volatile uint32_t irData[128]; volatile uint8_t irCount = 0; volatile uint8_t irState = 0; void IR_TIM_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructure.TIM_Period = 8999; // 90us TIM_TimeBaseStructure.TIM_Prescaler = 71; // 1MHz TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(IR_TIM, &TIM_TimeBaseStructure); TIM_Cmd(IR_TIM, ENABLE); } void IR_EXTI_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = IR_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(IR_GPIO, &GPIO_InitStructure); GPIO_EXTILineConfig(IR_EXTI_PORT_SOURCE, IR_EXTI_PIN_SOURCE); EXTI_InitStructure.EXTI_Line = IR_EXTI; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void EXTI0_IRQHandler(void) { static uint16_t lastValue = 0; uint16_t duration = (uint16_t)(IR_TIM->CNT); IR_TIM->CNT = 0; if (duration < 10000) { // ignore noise if (irState == 0 && duration > 8000 && duration < 9000) { // start bit irCount = 0; irState = 1; } else if (irState == 1 && duration > 400 && duration < 600) { // 0 bit irData[irCount++] = 0; irState = 2; } else if (irState == 1 && duration > 1200 && duration < 1400) { // 1 bit irData[irCount++] = 1; irState = 2; } else if (irState == 2) { // next bit irState = 1; } else { // invalid bit irData[irCount++] = lastValue; // use previous value } lastValue = irData[irCount-1]; } else { // stop bit irState = 0; } EXTI_ClearITPendingBit(IR_EXTI); } int main(void) { IR_TIM_Config(); IR_EXTI_Config(); while(1) { if (irState == 0 && irCount == 70) { // valid data if (irData[0] == 0 && irData[1] == 1 && irData[2] == 0 && irData[3] == 1) { // check start code uint16_t addr = 0; uint16_t cmd = 0; for (int i = 0; i < 8; i++) { addr = (addr << 1) | irData[4+i]; } for (int i = 0; i < 8; i++) { cmd = (cmd << 1) | irData[20+i]; } // do something with addr and cmd } irCount = 0; } } } ``` 此程序可以解析格力空调遥控信号,使用了 TIM2 定时器和 EXTI 外部中断来计时和捕获信号。当接收到有效的红外线信号时,会将信号值存储在 `irData` 数组中,并根据信号格式和状态机来判断是否解析完整个数据包。如果解析成功,可以获取地址码和命令码并执行相应的操作。 需要注意的是,格力空调遥控信号的编码格式可能存在差异,此程序只是一个简单的解析例程,实际使用时需要根据具体的遥控器型号和编码格式进行修改和优化。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luxus0946

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值