NEC红外线编码协议

红外遥控协议-NEC协议

为方便理解所看到的波形是从红外接收管出来的信号,跟协议所说的信号高低(0或1)刚好相反

NEC协议是众多红外遥控协议的其中一种,除NEC外,还有RC5、RC6等其它的。市面上买到的非学习型万能电视遥控器大多集成一种或多种编码是NEC型的,我买的二个遥控器中就有三种以上编码是NEC的。

NEC编码的一帧(通常按一下遥控器按钮所发送的数据)由引导码、地址码及数据码组成,,如下图所示,把地址码及数据码取反的作用是加强数据的正确性。

IR NEC Protocol

引导码及数据的定义如下图所示,当一直按住一个按钮的时候,会隔110ms左右发一次引导码(重复),并不带任何数据

引导码及数据

以下是用示波器采集到的一直按住某个按钮时的波形:

image

按一下按钮的波形:

image


一、遥控器解码说明

1、遥控器的编码格式常见有两种,一种是NEC 格式,一种是RC5 格式。遥控器发出的信号,通过一个红外的接收头之后,信号被送到MCU 的一个中断引脚。通过MCU 来识别不同的时序,来实现遥控器按键信号的解码。

2、遥控器时序图及数据格式(NEC 格式)

数据格式:

 

   遥控器发送的数据码由以下部分组成:引导码,8位的客户码,8位客户码的补码,8位的按键值,8位按键值的补码; 

具体的时序:

单次按键时的时序:

 注: 一个完整的周期是108 ms 

连续按键时的时续:

在单次按键的时序之后,紧跟如下时序:(周期也是108ms)

 

二、软件设计思想及处理函数 

根据遥控器信号时序的特点,在设计软件时,需要利用时序,首先找到引导区,再读取客户码(可以一次读取16位),识别是否为厂家所制定的数值;之后读取8位的按键值,并将读取到的数据保存起来

需要定义的在遥控器解码过程中用到的状态值:

#define         IR_STATE_IDLE                0x00
#define         IR_STATE_LEAD_ON             0x01
#define         IR_STATE_LEAD_OFF            0x02
#define         IR_STATE_CUSTOM              0x03
#define         IR_STATE_DATA1               0x04
#define         IR_STATE_DATA2               0x05

同时定义一下描述高低电平持续时间的一个常量

复制代码
#define      IR_R_Max                         40
#define      IR_R_Min                         30
 
#define      IR_H_Max                         40
#define      IR_H_Min                         30
 
#define      IR_L_Max                         20
#define      IR_L_Min                         15
复制代码

定义以下变量:

static unsigned char IrState ; 
static unsigned char IrData; 
static unsigned short IrCustom; 

解码的过程如下:遥控器的解码是在中断处理函数中完成的,当MCU 的中断引脚发生电平变化时,会引发中断; 

void interrupt NEC_IR(void)

{

-------------------------------------

  NEC遥控器中断处理 

------------------------------------

}

 

关于RC5 格式的遥控器解码

RC5 格式的遥控器除了时序和NEC格式的遥控器有一点差别之外,软件的解码过程基本类似,不再单独描述。

 

三、遥控器信号解码的流程

 

四、实现的代码(基于PIC芯片)

复制代码
//----------------------------------------------------------------------------
// Function Name: NEC_IR
// Description:IR interrupt manage
// Params: None
// Returns: None
// Notes: SYS INT service process
//----------------------------------------------------------------------------
void interrupt NEC_IR(void) 
{ 
    unsigned char t0; 
    //here first things to disable the interupt!
    GIE=0;
    //IR Intrupt input here.
    //preamble=9ms" --|__|--" + 4.5ms"_|--|_",others Data high 2.25ms and low 1.25ms;
    //Data =" --|__|--" + "_|--|_" high 2.25ms and low 1.25ms.
    //Repeat==9ms" --|__|--" + 2.25 ms"_|--|_".
    if(INTF)
    {
        t0 = TMR0;
        TMR0 = 0;
        switch (IrState)
        {
            case IR_STATE_IDLE:
                INTEDG = 1;//Rising edge trigger
                IrState = IR_STATE_LEAD_ON;
                break;
            case IR_STATE_LEAD_ON:
                INTEDG = 0;//Falling edge trigger
                if((t0 > Pream_L_Min) && (t0 < Pream_L_Max))
                {
                    IrState = IR_STATE_LEAD_OFF;
                }
                else
                {
                    IrState = IR_STATE_IDLE;
                }
                break;
            case IR_STATE_LEAD_OFF:
                if ((t0 > Pream_S_Min) && (t0 < Pream_S_Max))
                {
                    IrState = IR_STATE_CUSTOM;
                    IrCustom = 0;
                    BitCounter = 0;
                    Repeat = 0;
                }
                else
                {
                    if ((t0 > IR_R_Min) && (t0 < IR_R_Max))
                    {
                        if ((Repeat)&&(SystemState == POWER_ON_STATE))
                        { 
                            Repeat = 0;//IR key Repeat
                        }
                    }
                    else
                    {
                        Repeat = 0;
                    }
                    
                    INTEDG = 0;
                    IrState = IR_STATE_IDLE;
                }
                break;
            case IR_STATE_CUSTOM:
                if ((t0 > IR_L_Min) && (t0 < IR_L_Max))
                {
                    IrCustom >>= 1; 
                }
                else
                {
                    if ((t0 > IR_H_Min) && (t0 < IR_H_Max))
                    {
                        IrCustom = ((IrCustom >> 1) | 0x8000); 
                    }
                    else
                    {
                        INTEDG = 0;
                        IrState = IR_STATE_IDLE;
                        Repeat = 0;
                        break;
                    }
                }
                
                
                if (++BitCounter == 16)
                {
                    if (IrCustom != CustomCode)
                    {
                        INTEDG = 0;
                        IrState = IR_STATE_IDLE;
                        Repeat = 0;
                        break;
                    }
                    IrState = IR_STATE_DATA1;
                    BitCounter = 0;
                    IrKeyCode = 0;
                }
                break;
            case IR_STATE_DATA1:
                BitCounter++;
                if ((t0 > IR_L_Min) && (t0 < IR_L_Max))
                {
                    IrKeyCode >>= 1; 
                }
                else
                {
                    if ((t0 > IR_H_Min) && (t0 < IR_H_Max))
                    {
                        IrKeyCode = ((IrKeyCode >> 1) | 0x80); 
                    }
                    else
                    {
                        INTEDG = 0;
                        IrState = IR_STATE_IDLE;
                        Repeat = 0;
                        break;
                    }
                }
                if (BitCounter == 8)
                {
                    IrState = IR_STATE_DATA2;
                    BitCounter = 0;
                    IrData = 0;
                }
                break;
            case IR_STATE_DATA2:
                BitCounter++;
                if ((t0 > IR_L_Min) && (t0 < IR_L_Max))
                {
                    IrData >>= 1; 
                }
                else
                {
                    if ((t0 > IR_H_Min) && (t0 < IR_H_Max))
                    {
                        IrData = ((IrData >> 1) | 0x80); 
                    }
                    else
                    {
                        INTEDG = 0;
                        IrState = IR_STATE_IDLE;
                        Repeat = 0;
                        break;
                    }
                }
                if (BitCounter == 8)
                {
                    INTEDG = 0;
                    IrState = IR_STATE_IDLE;
                    IrData = ~IrData;
                    if (IrKeyCode == IrData)
                    {
                                                    // Check if data is valid
                    }
                    else
                    {
                        Repeat = 0;
                    }
                }
                break;
        }
        INTF=0; 
    }
    GIE=1;
}

  • 5
    点赞
  • 35
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:技术黑板 设计师:CSDN官方博客 返回首页
评论

打赏作者

酒馆【酒友】

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值