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;