上一篇
[LPC54102]红外遥控介绍与接收
https://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=461935&fromuid=194541
(出处: 电子工程世界-论坛)
中描述的接收到的MARK 与SPACE 红色部分有500 550 600 650 700 感觉数据很乱的感觉
原因在于接收的芯片的处理能力,以及遥控器本的时序、空气中的的环境影响,等等原因造成这样的结果。
我的遥控器是格力GREE,型号YB0FB2 ,在网上找了很久才找到如下这份资料
格力空调遥控器(YB0F2)红外码组成如下,按解码顺序排列
起始码(S)+35位数据码+连接码(C)+32位数据码
1、各种编码的电平宽度:
数据码由“0”“1”起始码、连接码组成:
0的电平宽度为:600us低电平+600us高电平,
1的电平宽度为:600us低电平+1600us高电平
起始码S电平宽度为:9000us低电平+4500us高电平
连接码C电平宽度为:600us低电平+20000us高电平
2、数据码的形成机制 前35位数据码形成如下图所示:
前35位数据码形成如下图所示:
上表中,大于两位的数据都是逆序递增的,各数据的意义如下:
校验码的形成机制如下:
校验码 = [(模式 – 1) + (温度 – 16) + 5 +左右扫风+换气+节能]取二进制后四位,再逆序;
例如:如果需要设置一下的状态,模式4,30℃,左右扫风,换气关闭,节能关闭,那么校验码为:
(4 – 1)+(30-16)+5+1+0+0 = 15,取低四位为0111,逆序后为1110
注意:为了方便编码,在编码时可以正序,解码端再逆序,解码的时候先解码低字节,再解码高字节的位。另外定时数据对最后的校验码的影响没有测试,因为很少会用到这个功能。
编码与解码,如果知道红外的协议就很容易编码与解码。但现在的关键在于对图 MARK与SPACE 的持续时间500 550 600 650 700 ,对应应该是600us
引入容错机制,如下所示
int MATCH(int measured, int desired) {return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);}
对于持续时间只要在600 的误差允许范围内都识为是600us
关键代码如下:
// Marks tend to be 100us too long, and spaces 100us too short
// when received due to sensor lag.
#define MARK_EXCESS 100
#define TOLERANCE 25 // percent tolerance in measurements
#define LTOL (1.0 - TOLERANCE/100.)
#define UTOL (1.0 + TOLERANCE/100.)
#define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK))
#define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1))
int MATCH(int measured, int desired) {return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);}
int MATCH_MARK(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us + MARK_EXCESS));}
int MATCH_SPACE(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us - MARK_EXCESS));}
对于格力的接收红外的解码代码如下:
long IRrecv_decodeGREE(decode_results_t *results)
{
long data[3] = {0};
long datavalue = 0;
long temp = 0;
int offset = 1; // Skip first space
// Initial mark
if (!MATCH_MARK(results->rawbuf[offset], GREE_HDR_MARK)) {
return ERR;
}
offset++;
if (irparams.rawlen < 2 * GREE_BITS + 6) {
return ERR;
}
// Initial space
if (!MATCH_SPACE(results->rawbuf[offset], GREE_HDR_SPACE)) {
return ERR;
}
offset++;
//first data 35bit
for (int i = 0; i < 32; i++) {
if (!MATCH_MARK(results->rawbuf[offset], GREE_BIT_MARK)) {
return ERR;
}
offset++;
if (MATCH_SPACE(results->rawbuf[offset], GREE_ONE_SPACE)) {
data[0] = (data[0] << 1) | 1;
}
else if (MATCH_SPACE(results->rawbuf[offset], GREE_ZERO_SPACE)) {
data[0] <<= 1;
}
else {
return ERR;
}
offset++;
}
for (int i = 0; i < 3; i++) {
if (!MATCH_MARK(results->rawbuf[offset], GREE_BIT_MARK)) {
return ERR;
}
offset++;
if (MATCH_SPACE(results->rawbuf[offset], GREE_ONE_SPACE)) {
data[1] = (data[1] << 1) | 1;
}
else if (MATCH_SPACE(results->rawbuf[offset], GREE_ZERO_SPACE)) {
data[1] <<= 1;
}
else {
return ERR;
}
offset++;
}
// Com mark
if (!MATCH_MARK(results->rawbuf[offset], GREE_COM_MARK)) {
return ERR;
}
offset++;
// Com space
if (!MATCH_MARK(results->rawbuf[offset], GREE_COM_SPACE)) {
return ERR;
}
offset++;
//second data 32bit
for (int i = 0; i < 32; i++) {
if (!MATCH_MARK(results->rawbuf[offset], GREE_BIT_MARK)) {
return ERR;
}
offset++;
if (MATCH_SPACE(results->rawbuf[offset], GREE_ONE_SPACE)) {
data[2] = (data[2] << 1) | 1;
}
else if (MATCH_SPACE(results->rawbuf[offset], GREE_ZERO_SPACE)) {
data[2] <<= 1;
}
else {
return ERR;
}
offset++;
}
datavalue = data[0]&0x0000007f;//7 b0001010
temp = data[1]&0x00000007;
datavalue = (datavalue<<3)|temp;//3 b010
temp = (data[2]>>28)&0x00000007;
datavalue = (datavalue<<3)|temp;//3 b000
temp = (data[2]>>24)&0x00000007;
datavalue = (datavalue<<3)|temp;//3 b000
temp = (data[2]>>6)&0x0000ffff;
datavalue = (datavalue<<16)|temp;//16 b 0001 0000 0000 0000
if( datavalue != 0x14801000 ) //b0001 0100 1000 0000 0001 0000 0000 0000
return ERR;
if( (data[2]&0x00000010)!=0)
return ERR;
datavalue = data[0]&0xffffff80;
temp = (data[2]&0x80000000)>>(31-7);
datavalue = datavalue|temp;
temp = (data[2]&0x08000000)>>(27-6);
datavalue = datavalue|temp;
temp = (data[2]&0x00c00000)>>(22-4);
datavalue = datavalue|temp;
temp = (data[2]&0x00000020)>>(5-3);
datavalue = datavalue|temp;
// Success
results->bits = GREE_BITS;
results->greeCRC = data[2]&0x0000000f;
results->value = datavalue;
results->decode_type = GREE;
return DECODED;
}
最后通过 value 得到 值以与 greeCRC得到检验码
格力 开机按键
关机
注意HEX 码
0x30300000 与0x20300000
实际上只有1bit的数据发生变化