STM32解析美的空调红外遥控器

STM32解析美的空调红外遥控器

1.红外线简介

  在光谱中波长自760nm至400um的电磁波称为红外线,它是一种不可见光。目前几乎所有的视频和音频设备都可以通过红外遥控的方式进行遥控,比如电视机、空调、影碟机等,都可以见到红外遥控的影子。这种技术应用广泛,相应的应用器件都十分廉价,因此红外遥控是我们日常设备控制的理想方式。

2.美的空调红外遥控器协议R05D

  美的空调红外遥控器采用R05D格式,载波频率为38KHZ。
数据格式引导码+48位数据+分隔码+48位数据(LAA’BB’CC’ S LAA’BB’CC’)

  L为引导码;
  ABC为实际数据,A’为A的反码,B’为B的反码,C’为C的反码;
  S为分隔码;
  第二帧数据和第一帧一样;

L引导码4.5ms低电平+4.5ms高电平(以解析方分析,编码方刚好相反,下面不再概述)
在这里插入图片描述

数据A:A为识别码(A=10110010=0xB2,预留方案时A=10110111=0xB7)

数据B
在这里插入图片描述
数据C
在这里插入图片描述
在这里插入图片描述

关机键值
 关机为固定编码键值:
  A=1011 0010 --0xB2
  B=0111 1011 --0x7B
  C=1110 0000 --0xE0

3.数据0格式

在这里插入图片描述

4.数据1格式

在这里插入图片描述

5.分隔码

在这里插入图片描述

6.完整时序图

在这里插入图片描述

7.软件设计

  本次采用外部中断+定时器方式完成红外数据解析。
  1.红外数据解析程序

/*********红外线初始化************
**
**REMOTE_IN --PB9
**
***********************************/
void HS0038_Init(void)
{
  RCC->APB2ENR|=1<<3;//PB
  GPIOB->CRH&=0xFFFFFF0F;
  GPIOB->CRH|=0x00000080;
  EXTI_Config(GPIO_B,9,EXTI_FTSR);//下将沿触发
  STM32_NVIC_SetPriority(EXTI9_5_IRQn,0,0);//设置优先级
  TIMx_Init(TIM1,72,65535);//定时器1初始化
}
/*************获取高电平时间****************/
u16 Infrared_GetTimeH(void)
{
  TIM1->CNT=0;//清空计数器值
  TIM1->CR1|=1<<0;
  while(REMOTE_IN);//等待引脚拉低
  TIM1->CR1&=~(1<<0);
  return TIM1->CNT;
}
/******************获取低电平时间**************/
u16 Infrared_GetTimeL(void)
{
  TIM1->CNT=0;//清空计数器值
  TIM1->CR1|=1<<0;
  while(REMOTE_IN==0);//等待引脚拉高
  TIM1->CR1&=~(1<<0);
  return TIM1->CNT;
}
//美的空调17~30℃数据顺序排放
const char r05d_temp[15]={0,1,3,2,6,7,5,4,12,13,9,8,10,11,14};//温度数据,17~30
u32 infrared_data=0;//保存解析的32位数据
u8 infrared_stat=0;//解析成功标志位
u8 infrared_buff[6]={0};
/*******EXTI5~9中断服务函数**********/
void EXTI9_5_IRQHandler(void)
{
  u16 time;
  u8 i=0,j=0;
  EXTI->PR|=1<<9;//清除标志位
  /*1.接收引导码:4.5ms低电平+4.5ms高电平*/
  time=Infrared_GetTimeL();
  if(time<=3500 || time>=5500)return;
  time=Infrared_GetTimeH();
  if(time<3500 || time>5500)return ;  
  for(i=0;i<6;i++)
  {
    for(j=0;j<8;j++)
    {
      time=Infrared_GetTimeL();//间隔码:540us低电平
      if(time<350 || time>650)return ;
      time=Infrared_GetTimeH();
      if(time>=1550 &&  time<=1850)
      {
        infrared_buff[i]<<=1;
        infrared_buff[i]|=0x01;
      }
      else if(time>=420 && time<=700)
      {
        infrared_buff[i]<<=1;
      }
     else return ;
    }
  }
  infrared_stat=1;//数据解析完成
}

  2.主函数

int main()
{
  u8 i=0;
  u8 wind;
  u8 mode;
  u8 temp;
  Beep_Init();
  Led_Init();
  Key_Init();
  u8 data[6];
  Usartx_Init(USART1,115200,72);
  HS0038_Init();
  while(1)
  {
      if(infrared_stat==1)
      {
        BEEP=1;
        Delay_Ms(50);
        BEEP=0;
        for(i=0;i<6;i++)
        {
          if(data[i]!=infrared_buff[i])break;
        }
        if(i!=6)
        {
          for(i=0;i<6;i++)
          {
            data[i]=infrared_buff[i];
          }
          //printf("data:%#x\r\n",infrared_data);
          if(data[2]==0x7B && data[4]==0xE0)
          {
               printf("关机\r\n");
          }
          else if(data[2]==0x6b && data[4]==0xE0)
          {
            printf("左右扫风\r\n");
          }
          else if(data[0]==0xb5 && data[2]==0xf5)//其它
          {
            
          }
          else
          {
            wind=(data[2]>>5)&0x7;//风速
            mode=(data[4]>>2)&0x3;//模式
            temp=(data[4]>>4)&0xf;//温度
            //printf("风速:%d\r\n",wind);
            //printf("模式:%d\r\n",mode);
            //printf("温度:%#x\r\n",temp);
            if(wind==WIND_1)printf("自动,");
            else if(wind==WIND_2)printf("低风,");
            else if(wind==WIND_3)printf("中风,");
            else if(wind==WIND_4)printf("高风,");
            else if(wind==WIND_5)printf("固定风,");
            
            if(mode==MODE_1)printf("自动,");
            else if(mode==MODE_2)printf("制冷,");
            else if(mode==MODE_3 && temp==T_31)printf("送风,");
            else if(mode==MODE_3)printf("抽湿,");
            else if(MODE_4)printf("制热,");
            for(i=0;i<15;i++)
            {
              if(temp==r05d_temp[i])printf("温度:%d\r\n",17+i);
            } 
          }
        }
        infrared_stat=0;
      }
  }
}

  3.相关参数定义

//风速设置B(5,7)
typedef enum R05D_WIND
{
  WIND_1 =5,//B(5,7)=101,自动
  WIND_2 =4,//B(5,7)=100,低风
  WIND_3 =2,//B(5,7)=010,中风
  WIND_4 =1,//B(5,7)=001,高风
  WIND_5 =0,//B(5,7)=000,固定风
}R05d_W;
//模式C(2,3)
typedef enum R05D_Mode
{
  MODE_1 =2, //C(2,3)=10,自动
  MODE_2 =0, //C(2,3)=00,制冷
  MODE_3 =1, //C(2,3)=01,抽湿,送风
  MODE_4 =3, //C(2,3)=11,制热
}R05d_M;
//温度C(4,7)
typedef enum R05D_Temp
{
  T_17 =0,//C(4,7)=0000,17℃
  T_18 =1,//C(4,7)=0001,18℃
  T_19 =3,//C(4,7)=0011,19℃ 
  T_20 =2,//C(4,7)=0010,20℃ 
  T_21 =6,//C(4,7)=0110,21℃ 
  T_22 =7,//C(4,7)=0111,22℃  
  T_23 =5,//C(4,7)=0101,23℃ 
  T_24 =4,//C(4,7)=0100,24℃
  T_25 =12,//C(4,7)=1100,25℃  
  T_26 =13,//C(4,7)=1101,26℃
  T_27 =9,//C(4,7)=1001,27℃ 
  T_28 =8,//C(4,7)=1000,28℃   
  T_29 =10,//C(4,7)=1010,29℃   
  T_30 =11,//C(4,7)=1011,30℃  
  T_31 =14,//C(4,7)=1110,无定义,送风模式下使用
}R05d_T;

8.示例效果
在这里插入图片描述
在这里插入图片描述
参考示例:https://download.csdn.net/download/weixin_44453694/19830401

实现解析空调红外遥控信号需要了解红外遥控信号的编码格式和解码方法。常见的空调遥控信号编码格式为 NEC 格式,其数据由一个开始位、一个停止位和 32 个数据位组成,其中数据位分为两部分,16 位表示命令码和 16 位表示反码。解码方法可以使用定时外部中断捕获红外信号,然后解析数据位来获取命令码。 以下是基于 STM32NEC 空调遥控信号解析程序: ```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 = 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 irData = 0; irState = 1; } else if (irState == 1 && duration > 400 && duration < 600) { // 0 bit irData = (irData << 1) & 0xFFFF; irState = 2; } else if (irState == 1 && duration > 1200 && duration < 1400) { // 1 bit irData = ((irData << 1) | 0x0001) & 0xFFFF; irState = 2; } else if (irState == 2) { // next bit irState = 1; } else { // invalid bit irData = lastValue; // use previous value } lastValue = irData; } else { // stop bit irState = 0; } EXTI_ClearITPendingBit(IR_EXTI); } int main(void) { IR_TIM_Config(); IR_EXTI_Config(); while(1) { if (irState == 0 && irData != 0) { // valid data uint16_t cmd = (irData & 0xFF00) >> 8; uint16_t cmdInv = irData & 0x00FF; if (cmd == (~cmdInv & 0xFF)) { // check command // do something with cmd irData = 0; } } } } ``` 此程序可以解析 NEC 格式的空调遥控信号,使用了 TIM2 定时和 EXTI 外部中断来计时和捕获信号。当接收到有效的红外线信号时,会将信号值存储在 `irData` 变量中,并根据数据位和状态机来判断是否解析完整个数据包。如果解析成功,可以获取命令码并执行相应的操作。 需要注意的是,此程序只是一个简单的空调遥控信号解析例程,实际使用时需要根据具体的遥控型号和编码格式进行修改和优化。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IT_阿水

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

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

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

打赏作者

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

抵扣说明:

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

余额充值