核心提示:NEC红外遥控协议是一种通用型红外遥控信号协议,适用于电视(TV),磁带录像机(VTR),激光唱机等设备的遥控操作。市场上,以NEC红外遥控协议为核心的红外遥控器被广泛使用且价格便宜。本文将着重讨论NEC红外遥控解码程序的设计。 |
NEC红外遥控协议是一种通用型红外遥控信号协议,适用于电视(TV),磁带录像机(VTR),激光唱机等设备的遥控操作。市场上,以NEC红外遥控协议为核心的红外遥控器被广泛使用且价格便宜。本文将着重讨论NEC红外遥控解码程序的设计。
1 NEC的遥控信号
NEC红外遥控的协议,请网友可以到网络上搜索一下,本站不就做深入的讨论了。见下图是NEC红外遥控协议的波形示意图。具体见下:


遥控编码脉冲由引导码、用户码、功能码和功能码的相反码组成,用户码是同一组码发送两次,如图2所示。用户码为8位,所以整个脉冲码为32位。引导码作为接收数据的准备脉冲,他由8TCP(4.5 ms)的高电平和8TCP(4.5 ms)的低电平组成。用户码和功能码采用脉冲位置调制(PPM)方式编码,根据脉冲之间的时间间隔来区分码值的"0"或"1"。对应于二进制数字信号的"0"或"1",脉冲时间间隔分别为2TCP(1.125 ms)和4TCP(2.25 ms),而每一脉冲的宽度仍不变,均为TCP(0.562 6 ms)。由于用户码发送两次,功能码与其相反码一起发送,因此系统的误动作很少。
NEC遥控器采用第一次发送的遥控信号的编码脉冲(图3所示)和第二、第三次连续发送的遥控信号的编码脉冲(图4所示)不同的工作方式。这样,当按键一直按着的时候,从第二次连续发送开始,只发送引导码和用户码第一位SO的相反码SO,因此可减少接收处理时间和红外发光二极管功耗,遥控编码脉冲经脉冲载波调制后由TC9021F的第脚输出,再经激励器驱动红外发光二极管,发送出波长为940nm的脉冲红外光。假设用户码为十六进制的76H则第一次发送的遥控信号的编码脉冲如图3所示。


由图2和图3可以看出,遥控编码脉冲波形的输出时间为192TCP或224TCP,α为用户码(8位)的输出时间。当α≥26TCP时,遥控编码脉冲波形输出时间为224TCP.另外,对于连续发送的编码脉冲中用户码第一位的相反码的脉冲间隔时间,当SO="1"时,则SO="0",该时间为2TCP,当SO="0"时,则SO="1",该时间为4TCP.2解码器硬件设计
解码器硬件以AT89C51单片机为核心,如图5所示,图中只给出接收红外遥控信号的部分电路。红外遥控信号经过红外接收模块接收后,解调为遥控信号的编码脉冲由输出端A输出,其波形如图3和图4所示,此信号直接输出到AT89C51的外部中断INT0输入端.单片机通过运行程序对红外遥控器所发出的编码脉冲进行接收和译码。

具体的程序代码见下:
bit int0bh_pending = 0;
unsigned char th1_val = 0, th1_old = 0;
unsigned char c_last = 0;
unsigned char c_bits = 8;
unsigned char c_index = 0;
unsigned char c_code;
bit c_error = 0;
#define T_100US (F_OSC1/12/10000)//100uS. 12M
//#define T_100US (F_OSC/12/8000)//100uS. 9.6M
#define T_ZERO_MIN (T_100US*10)//遥控码低电平最小宽度
#define T_ZERO_MAX (T_100US*18)//遥控码低电平最大宽度
#define T_ONE_MIN (T_100US*20)//遥控码高电平最小宽度
#define T_ONE_MAX (T_100US*28)//遥控码高电平最大宽度
#define T_REP_MIN (T_100US*110)//遥控码重复码最小宽度
#define T_REP_MAX (T_100US*120)//遥控码重复码最大宽度
#define T_START_MIN (T_100US*130)//遥控启始码最小宽度
#define T_START_MAX (T_100US*150)//遥控启始码最大宽度
#define TH_ZERO_MIN (T_ZERO_MIN>>8)
#define TH_ZERO_MAX (T_ZERO_MAX>>8)
#define TH_ONE_MIN (T_ONE_MIN>>8)
#define TH_ONE_MAX (T_ONE_MAX>>8)
#define TH_REP_MIN (T_REP_MIN>>8)
#define TH_REP_MAX (T_REP_MAX>>8)
#define TH_START_MIN (T_START_MIN>>8)
#define TH_START_MAX (T_START_MAX>>8)
#define CODE1 0x83//遥控代码
#define CODE2 0x7c//遥控反代码
#define INIT_T0 (65536L - (F_OSC/12)/HZ)
#define INIT_TH0 (INIT_T0 >> 8)
void int0_bh(void)
{
unsigned char temp = th1_val;
th1_val -= th1_old;
if (temp < th1_old)
th1_val -= INIT_TH0;
th1_old = temp;
// if (th1_val > TH_START_MAX)
// goto err_out;
if (th1_val >= TH_START_MIN)
goto reset_out;
// if (th1_val > TH_REP_MAX)
// goto err_out;
if (th1_val >= TH_REP_MIN) {
if (key_last == KEY_INC || key_last == KEY_DEC)
key_on = 1;
goto reset_out;
}
if (c_error)
return;
// if (th1_val > TH_ONE_MAX)
// goto err_out;
if (th1_val >= TH_ONE_MIN) {
c_last = (c_last >> 1) | 0x80;
goto bit_rcv;
}
// if (th1_val > TH_ZERO_MAX)
// goto err_out;
if (th1_val >= TH_ZERO_MIN) {
c_last >>= 1;
goto bit_rcv;
}
goto err_out;
bit_rcv:
if (--c_bits)
return;
switch (c_index++) {
case 0:
if (c_last != CODE1)//if(c_last ==CODE1)goto out;
goto err_out; //else goto out;
goto out;
case 1:
if (c_last != CODE2)
goto err_out;
goto out;
case 2:
c_code = c_last;
goto out;
case 3:
if (c_last != ~c_code)
goto err_out;
break;
}
if (key_on) {
goto reset_out;
}
switch (c_code) {
// case 0x03:
// key_last = KEY_POWER;
// break;
case 0x07:
key_last = KEY_MENU;
break;
case 0x0e:
key_last = KEY_INC;
break;
case 0x0c:
key_last = KEY_DEC;
break;
case 0x09:
key_last = KEY_UP;
break;
case 0x11:
key_last = KEY_DOWN;
break;
// case 0x17:
// key_last = KEY_VIDEO;
// break;
default:
key_last = KEY_INVALID;
goto reset_out;
}
key_on = 1;
goto reset_out;
err_out:
c_error = 1;
goto out;
reset_out:
c_error = 0;
c_index = 0;
goto out;
out:
c_last = 0;
c_bits = 8;
}
注意:需要在程序初始化部分,将INT0设置为下降沿中断。


RSS订阅






