基于STM32的格力空调红外控制

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

2.格力空调红外协议学习分析
  要实现格力空调红外遥控功能,则首先要了解一下红外协议特性。在红外协议中一般由引导码、数据码、间隔码、重复码等几部分组成。接下来,将通过逻辑分析仪捕获一段格力空调的红外协议数据,实际分析其数据内容。

硬件设备:
1、STM32开发板
2、红外接收设备
3、逻辑分析仪
4、格力空调遥控器

2.1采集红外信号
  通过上图红外接收设备,捕获红外信号,利用逻辑分析仪分析捕获的数据内容。捕获波形如下:


  本次主要捕获的是开启空调和关闭空调两个键值数据。接下来则可进行数据分析。

2.波形数据分析
引导码



  引导码信号:9ms低电平+4.5ms高电平

数据0



  数据0:0.68ms低电平+0.53ms高电平

数据1



  数据1:0.68ms低电平+1.6ms高电平

分隔码



  分隔码:0.68ms低电平+20ms高电平

间隔码



  间隔码:0.68ms低电平+40ms高电平

开空调波形


关空调波形


3.输入捕获方式采集红外数据
  为了编译后续学习实现空调的开机和关键功能,首先可以通过红外接收头采集实际键值数据,通过定时器输入捕获方式将键值数据进行保存。
  本次红外案例红外接收头接入到开发板的PB9引脚,通过定时器4输入捕获进行数据采集。

定时器输入捕获配置

/***********************定时器4输入捕获配置***********************
**               没有重映像          完全重映像
**TIM4_CH1          PB6                   PD12
**TIM4_CH2          PB7                   PD13
**TIM4_CH3          PB8                   PD14
**TIM4_CH4          PB9                   PD15
**
******************************************************************/

void TIM4_Input_Init(u16 psc,u16 arr)//72
{
    RCC->APB2ENR|=1<<3;//PB
    GPIOB->CRH&=~(0xF<<1*4);
    GPIOB->CRH|=0x8<<1*4;
    /*定时器配置*/
    RCC->APB1ENR|=1<<2;//TIM4
    RCC->APB1RSTR|=1<<2;
    RCC->APB1RSTR&=~(1<<2);
    TIM4->CNT=0;
    TIM4->PSC=psc-1;
    TIM4->ARR=arr;
    /*配置定时器输入捕获模式*/
    TIM4->CCMR2|=0x1<<8;//CH4配置为输入,CCR4保存CH4数据
    TIM4->CCER|=1<<13;//捕获发生在下降沿
    TIM4->DIER|=1<<4;//开启捕获中断
    STM32_NVIC_SetPriority(TIM4_IRQn,1,1);//设置优先级
    TIM4->CCER|=1<<12;//开启CH1输入捕获
    TIM4->CR1|=1<<0;//开启定时器
}

红外数据采集示例

char buff[100];
u8 buff_data=0;
/**************TIM4中断服务函数***************/
void TIM4_IRQHandler(void)
{
    u16 time;
    u8 static recv_stat=0;
    u8 static i=0;
    if(TIM4->SR&1<<0)
    {

    }
    if(TIM4->SR&1<<4)//捕获中断
    {
        TIM4->CNT=0;
        time=TIM4->CCR4;
        if(TIM4_CH4)//上升沿触发
        {
            TIM4->CCER|=1<<13;//下一次捕获下降沿
            if(recv_stat==0)//开始接收引导码
            {
                if(time>=8000 && time<=10000)recv_stat=1;//成功接收9ms低电平
                else recv_stat=0;
            }
            else if(recv_stat==2)
            {
                //printf("引导码接收成功\r\n");
                if(time<550 || time>750) recv_stat=0;//650us间隔时间接收失败
            }
        }
        else //下降沿触发
        {
            TIM4->CCER&=~(1<<13);//下一次捕获上升沿
            if(recv_stat==1)
            {
                if(time>=3500 && time<=5500)recv_stat=2;//引导码接收成功:9ms低+4.5高
                else recv_stat=0;
            }
            else if(recv_stat==2)//开始接收实际数据
            {
                    if(time>=400 && time<=650)//数据0:650us低+530us高
                    {
                        buff[i++]=0;
                    }
                    else if(time>=1500 && time<=1700)//数据1:650us低+1.6ms高
                    {
                        buff[i++]=1;
                    }
                    else if(time>=18000 && time<=21000)
                    {
                        buff[i++]=2;//间隔
                    }
                    else if(time>=38000 && time<=42000)
                    {
                        //printf("i=%d\r\n",i);
                        buff_data=i;
                        recv_stat=0;
                        i=0;
                        infrared_flag=3;
                    }
                    else 
                    {
                        i=0;
                        recv_stat=0;
                        infrared_data=0;
                    }
            }
        }
    }
    TIM4->SR=0;//清除标志
}

4.开关机学习示例
硬件设备
STM32开发板
红外发送头


4.1 38KHZ载波信号发送
  本次使用的红外发射模块工作频率为38KHZ,发送数据高低电平采用1:1方式。发送高电平需要发送38KHZ的方波脉冲信号(高低电平1:1方式),发送第低低电平则直接将引脚拉低即可。

/*****************发送38KHZ载波*********************
**38KHZ载波:1/38000HZ=26us,按照高低电平1:1发送载波
**形参:u32 time --持续时间
**u8 stat --转态(1表示发送,0表示不发送)
*****************************************************/
void Infrared_Send38KHZ(u32 time,u8 stat)
{
    u32 i=0;
    if(stat)
    {
        for(i=0;i<time/13;i++)
        {
            RED_IE=!RED_IE;
            DelayUs(13);
        }
    }
    else//发送低电平
    {
        RED_IE=0;
        DelayUs(time);
    }
}

4.2 开关键值发送函数示例

//格力空调协议数据发送
void Infrared_GreeSendData(u8*data,int cnt)
{
    /*1.发送9ms低电平*/
    Infrared_Send38KHZ(9000,1);
    /*2.发送4.5ms高电平*/
    Infrared_Send38KHZ(4500,0);    
    u32 i;
    for(i=0;i<cnt;i++)
    {
        Infrared_Send38KHZ(650,1);//发送间隔时间,650us的低电平
        if(data[i]=='1')
            Infrared_Send38KHZ(1600,0);//数据1
        else if(data[i]=='0')
            Infrared_Send38KHZ(530,0);//数据0
        else if(data[i]=='2')
            Infrared_Send38KHZ(20000,0);//间隔码
    }
    Infrared_Send38KHZ(650,1);//发送间隔时间,650us的低电平
    Infrared_Send38KHZ(40000,0);//间隔码

    /*1.发送9ms低电平*/
    Infrared_Send38KHZ(9000,1);
    /*2.发送4.5ms高电平*/
    Infrared_Send38KHZ(4500,0);    
    for(i=0;i<cnt;i++)
    {
        Infrared_Send38KHZ(650,1);//发送间隔时间,650us的低电平
        if(data[i]=='1')
            Infrared_Send38KHZ(1600,0);//数据1
        else if(data[i]=='0')
            Infrared_Send38KHZ(530,0);//数据0
        else if(data[i]=='2')
            Infrared_Send38KHZ(20000,0);//间隔码
    }
    Infrared_Send38KHZ(650,1);//发送间隔时间,650us的低电平
}