赞
踩
通信协议分为发送端和接收端,接收端的波形与发射端刚好相反。
NEC IR 协议使用 32 位帧格式对密钥进行编码,如下所示
地址码0 | 地址码1 | 命令码 | 命令码反码 |
---|---|---|---|
LSB-MSB(0-7) | LSB-MSB(8-15) | LSB-MSB(16-23) | LSB-MSB(24-31) |
在标准的NEC协议中,地址码1为地址码0的反码,而在许多遥控器中,地址码0和地址码1共同作为红外遥控器的编码值。
每个位都使用如图所示的脉冲距离进行传输。
逻辑“0”:562.5μs高电平,562.5μs低电平,总时长为1.125ms
逻辑“1”:562.5μs高电平,1.6875ms低电平,总时长为2.25ms
在遥控器上按某个键时,传输的消息将按顺序包含以下内容:
引导码:持续9ms 高电平,4.5ms低电平,作为启动信号;
紧接着是32bit的数据,按照上述的NEC帧格式的顺序;最后以562.5μs脉冲高电平结尾,表示一帧消息传输结束。
数据位的四个字节首先发送最低有效位。
下图示例展示了NEC 红外传输帧的格式,以地址为 00h (00000000b) 和 ADh (10101101b) 的命令码为例。
传输一个消息帧总共需要 67.5ms。它需要27ms来传输16位地址(地址+地址反码)和16位命令(命令+命令反码)。
重复码
如果遥控器上的键保持按下状态,则会发射重复码,通常在完整的一帧消息结束后约40ms后发送;重复码将继续以 108 ms的间隔发出,直到红外遥控按键被释放。
重复码按顺序包含以下内容:
波形如下图所示:
由于接收端的波形与发射端的波形刚好相反,在下述程序中,只需要一个定时器即可解码红外NEC协议,包含了红外重复码的检测,可区别红外遥控长按和短按事件。
#define IR_IN GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) // PA1 红外接收DQ引脚 unsigned char ir_code[4]; // 解码值保存变量 unsigned char ir_decode_ok_flag = RESET; // 解码成功标志位 /* NEC红外编码: 引导码 + 地址码 + 地址码(取反) + 数据 + 数据(取反) 引导吗:0.56ms(低电平) + 2.25ms(高电平) 数据1: 0.56ms(低电平) + 1.12ms(高电平) */ // 红外解码程序,100us定期执行就可以,将该函数放在100us的定时器中即可。 void Ir_Decode(void) { static unsigned int l_cnt = 0; // 低电平时间计数 static unsigned int h_cnt = 0; // 高电平时间计数 static unsigned int l_cnt_save = 0; // 保存低电平时长 static unsigned int h_cnt_save = 0; // 保存高电平时长 static unsigned char falling_edge_valid_flag = RESET; // IR电平由高变低标志位 static unsigned char rcv_sync_ok_flag = RESET; // 同步码接收成功标志位 static unsigned char bit_value = 0; // 位解码值 static unsigned char bit_rcv_cnt = 0; // 位接收个数变量 if( RESET == IR_IN ) { if( 0 == l_cnt ) // IR由高变低后立马记录上次测得的高电平时长 { h_cnt_save = h_cnt; falling_edge_valid_flag = SET; } l_cnt ++; if( l_cnt > 1600 ) // 防止计数溢出 { l_cnt = 1600; } h_cnt = 0; // 计数清零 } else { if( 0 == h_cnt ) // IR由低变高后立马记录上次测得的低电平时长 { l_cnt_save = l_cnt; } h_cnt ++; if( h_cnt > 1600 ) // 防止计数溢出 { h_cnt = 1600; } l_cnt = 0; // 计数清零 if(ir_decode_ok_flag == 1) { if(h_cnt > 1200) ir_decode_ok_flag = 2; // 短按 } } if( SET == falling_edge_valid_flag ) { falling_edge_valid_flag = RESET; /* 位解码 */ if( ((l_cnt_save >= 3)&&(l_cnt_save <= 9)) && // 560us低电平, 560us高电平 ((h_cnt_save >= 3)&&(h_cnt_save <= 9)) ) { bit_value = 0; } else if( ((l_cnt_save >= 3)&&(l_cnt_save <= 9)) && // 560us低电平,1680us高电平 ((h_cnt_save >= 14)&&(h_cnt_save <= 20)) ) { bit_value = 1; } else { bit_value = 2; } if( SET == rcv_sync_ok_flag ) { if((1 == bit_value) || (0 == bit_value) ) { if( bit_rcv_cnt < 8 ) { ir_code[0] |= (bit_value<< (bit_rcv_cnt%8)); } else if( bit_rcv_cnt < 16 ) { ir_code[1] |= (bit_value<< (bit_rcv_cnt%8)); } else if( bit_rcv_cnt < 24 ) { ir_code[2] |= (bit_value<< (bit_rcv_cnt%8)); } else if( bit_rcv_cnt < 32 ) { ir_code[3] |= (bit_value<< (bit_rcv_cnt%8)); } if( bit_rcv_cnt >= 31 ) { ir_decode_ok_flag = SET; rcv_sync_ok_flag = RESET; } bit_rcv_cnt ++; } else { rcv_sync_ok_flag = RESET; // 位接收错误,重新解码 } } if( ((l_cnt_save >= 87)&&(l_cnt_save <= 93)) && ((h_cnt_save >= 42)&&(h_cnt_save <= 48)) ) // 同步码,9ms低电平,4.5ms高电平 { rcv_sync_ok_flag = SET; bit_rcv_cnt = 0; ir_code[0] = 0; ir_code[1] = 0; ir_code[2] = 0; ir_code[3] = 0; } else if(((l_cnt_save >= 87)&&(l_cnt_save <= 93)) && ((h_cnt_save >= 20)&&(h_cnt_save <= 25)) ) { printf("repeate code\r\n"); ir_decode_ok_flag = 3; //长按 } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。