红外通信
-
对空调信号进行解码
-
利用发射管 PWM 38K载波发射 编码信号
所以需要学习如何使用38K载波 完成编码信号的发送
一.红外通信简介
适用于:
- 空调,电动窗帘,灯具灯,控制简单,成本低
组成:
- 遥控端和接收端
- 遥控端:红外发射管有3mm和5mm的。其中5mm外观比3mm的要大,而且5mm直插的功率会比3mm的大,还有5mm的红外线接收管抗高温要好些。
- 接收端:红外接收管,将红外光信号转化为电信号(即发射端发光 接收端CPU输出0,不发光则输出1,即发射端发射的波的高低与接收端接收到的相反)
二.红外编码
1.本质:
多种适用于红外通信的通信协议(编码格式),目的在于防止在红外通信时接收端接收到的信息与发射端发送的信息不匹配。
2.类型:
一般有NEC和RC5协议 NEC协议更简单常用
3.简述NEC协议
- 使用38K载波频率,消除其他光源的干扰
- 发射引导码:
- 即发射端发射9mm的高波(1)和4.5mm的低波(0),以表示开始通信
- 使用16位客户代码:
1.即每一个功能对应着一个十六位的二进制数(16位数据代码)
- 数据传输时使用16位数据代码和16取反的数据代码:
1.即每一个功能·要完成时发射端会将数据代码和取反的数据代码一起发送
- 逻辑‘0’和逻辑‘1’的发射方式:
-
逻辑‘0’:0.56ms38KHZ载波和0.56ms无载波间隔组成
-
逻辑‘1’:0.56ms38KHZ载波和1.68ms无载波间隔组成
末.简析载波和载波频率
- 载波是一个特定频率的无线电波,单位Hz,是一种在频率、调幅或相位方面被调制以传输光,语言、音乐、图象或其它信号的电磁波。
- 载波频率是在信号传输的过程中,并不是将信号直接进行传输,而是将信号负载到一个固定频率的波上,这个过程称为加载,这样的一个固定频率。严格的讲,就是把一个较低的信号频率调制到一个相对较高的频率上去,这被低频调制的较高频率就叫载波频率,也叫基频。就比如说,我们看到红外发射管是一直亮着的,但其实它发送的信号是亮灭相间的,对应波形就是高低相间的。
- 载波的作用:消除其他光源的干扰。比如太阳光中也包含红外光,但太阳光的频率与所载波频率不同,因此采用了特定频率载波的红外通信,接收端在接收到太阳光中的红外光时就不会与红外发射管的红外观混淆在一起而做出错误判断。
YB0F2编码协议及其应用
格力空调遥控器(YB0F2)红外码组成如下,按解码顺序排列
1.数据组成
起始码(S)+35位数据码+连接码(C)+32位数据码
2.各数据电平
数据码由“0”“1”起始码、连接码组成:
1s=1000ms=1000000us
0的电平宽度为:600us低电平+600us高电平,
1的电平宽度为:600us低电平+1600us高电平
起始码S电平宽度为:9000us低电平+4500us高电平
连接码C电平宽度为:600us低电平+20000us高电平
3.数据码的形成机制
上表中,大于两位的数据都是逆序递增的,各数据的意义如下:(先逆序 后递增 再逆序回来)
4.校验码计算公式
校验码逆序值+换气(开+1 关-1)+左右扫风(开+1 关-1)+温度差(末-初)+模式二进制逆序值差(末-初)+开关(开+8 关 -8)
再逆序
5.计算实例
1.以**u8 air[9] ={0X3E,0X70,0X04,0X0A,0X51,0X00,0X80,0X01,0XC0};**数据的校验码为基准,此处写的是16进制数,先将其转换为二进制,再进行计算
2.将基准校验码逆序
3.套用上述公式计算
4.逆序 即得校验码
5.注意
- 当 校验码逆序值为 0000 再减一 变为 1111 再次减一正常运算即可
- 当 校验码逆序值 减八 小于0时 换为 加八即可(控制关空调)
- 不要使用自动模式 因为自动模式的温度值无法自己设置 校验码值具有不确定性
6.进制转换
u8 n = 0;
void hextobin(int hex)
{ //u8 n = 0;
switch(hex)
{
case 0:
air_condi[n]=0;
air_condi[n+1]=0;
air_condi[n+2]=0;
air_condi[n+3]=0;
break;
case 1:
air_condi[n]=0;
air_condi[n+1]=0;
air_condi[n+2]=0;
air_condi[n+3]=1;
break;
case 2:
air_condi[n]=0;
air_condi[n+1]=0;
air_condi[n+2]=1;
air_condi[n+3]=0;
break;
case 3:
air_condi[n]=0;
air_condi[n+1]=0;
air_condi[n+2]=1;
air_condi[n+3]=1;
break;
case 4:
air_condi[n]=0;
air_condi[n+1]=1;
air_condi[n+2]=0;
air_condi[n+3]=0;
break;
case 5:
air_condi[n]=0;
air_condi[n+1]=1;
air_condi[n+2]=0;
air_condi[n+3]=1;
break;
case 6:
air_condi[n]=0;
air_condi[n+1]=1;
air_condi[n+2]=1;
air_condi[n+3]=0;
break;
case 7:
air_condi[n]=0;
air_condi[n+1]=1;
air_condi[n+2]=1;
air_condi[n+3]=1;
break;
case 8:
air_condi[n]=1;
air_condi[n+1]=0;
air_condi[n+2]=0;
air_condi[n+3]=0;
break;
case 9:
air_condi[n]=1;
air_condi[n+1]=0;
air_condi[n+2]=0;
air_condi[n+3]=1;
break;
case 10:
air_condi[n]=1;
air_condi[n+1]=0;
air_condi[n+2]=1;
air_condi[n+3]=0;
break;
case 11:
air_condi[n]=1;
air_condi[n+1]=0;
air_condi[n+2]=1;
air_condi[n+3]=1;
break;
case 12:
air_condi[n]=1;
air_condi[n+1]=1;
air_condi[n+2]=0;
air_condi[n+3]=0;
break;
case 13:
air_condi[n]=1;
air_condi[n+1]=1;
air_condi[n+2]=0;
air_condi[n+3]=1;
break;
case 14:
air_condi[n]=1;
air_condi[n+1]=1;
air_condi[n+2]=1;
air_condi[n+3]=0;
break;
case 15:
air_condi[n]=1;
air_condi[n+1]=1;
air_condi[n+2]=1;
air_condi[n+3]=1;
break;
}
n+=4;
}
void change(u8* DATA)
{ u8 i=0,n=0,high=0,low=0;
for(i=0;i<9;i++)
{
high=DATA[i]/16;
low=DATA[i]%16;
for(n=0;n<2;n++)
{
if(n==0)
{
hextobin(high);
}
else if(n==1)
{
hextobin(low);
}
}
}
send_code_open(air_condi);
7.校验码计算代码
实参:需计算校验码的指令(九个十六进制数的前七个)
形参:通过计算校验码 改变形参数组元素【7】的最低位二进制和【8】的高三位二进制数
void Analyze(u8 *DATE1) 
{
int num0 = 0,num1 = 0,num3=0;
int x=0,y=0,i=0,sum=0,end=0,n=0;
DATE1[7]=0X00;
for(n=0;n<2;n++)//决定校验码的 模式 开关 温度
{
num0 = 0;
num1 = 0;
if(DATE1[n]/16!=templete[n]/16)
{
x = DATE1[n]/16;
y = templete[n]/16;
for(i=0;i<4;i++)
{
num0+=(y%2) * pow(2.0,4-i-1);
num1+=(x%2) * pow(2.0,4-i-1);//将拆分出来的16进制转换成8421BCD码再乘以相应的权值相加
y=y/2;
x=x/2;
}
sum+=(num1 - num0);
}
}
if((DATE1[3]/16)/8!=(templete[3]/16)/8) //换气
{
sum+=1;
}
if((DATE1[4]%16)%2!=(templete[4]%16)%2) //扫风
{
sum+=1;
}
end=begin+sum;
if(end<0)
{
end=-end;
end=16-end;
}
for(i=0;i<4;i++)
{
num3+=(end%2) * pow(2.0,4-i-1);
end=end/2;
}
if(num3>7)
DATE1[7]=0X01;
if(num3==7||num3==15)
DATE1[8]=0Xe0;
if(num3==6||num3==14)
DATE1[8]=0Xc0;
if(num3==5||num3==13)
DATE1[8]=0Xa0;
if(num3==4||num3==12)
DATE1[8]=0X80;
if(num3==3||num3==11)
DATE1[8]=0X60;
if(num3==2||num3==10)
DATE1[8]=0X40;
if(num3==1||num3==9)
DATE1[8]=0X20;
if(num3==0)
DATE1[8]=0X00;
}