打印
[51单片机]

帮忙看看这个红外解码程序

[复制链接]
1082|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
喜马拉雅虎|  楼主 | 2014-11-16 16:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
引导码为9ms+4.5ms,红外接收头任意连接单片机。
void time0(void) interrupt 1
{
   IR_NEC();
   XS();        
}
#define  USER_H     0x80                         //用户码高8位
#define  USER_L     0x7F                         //用户码低8位
#define  Check_EN   0                             //是否要校验16位用户码:不校验填0,校验则填1       
#define  CPU_Fosc   12000000             //输入主频,自适应解码(单位:Hz,范围:6MHz ~ 40MHz)
#define  CA_S       8                             //长按时间设置,单位:108mS(即 108mS整数倍,10倍以上为宜)

sbit IR = P3^6;                                  //红外线接口(任意引脚)

#define  Step       400                             //红外采样步长:400us
#define  TH_H       ((65536-Step*(CPU_Fosc/300)/40000)/256)  //定时器高8位基准赋值
#define  TH_L       ((65536-Step*(CPU_Fosc/300)/40000)%256)  //定时器低8位基准赋值

uint8   IR_BT;                         //解码效果返回:0无效,1有效,2短按,3长按
uint8   NEC[4];                         //解码存放:16位用户码、操作码正反码
uint8   cntCA;                         //长按计数
uint16  cntStep;                         //步数计
bit     IRa,IRb;                         //电位状态保存
bit     IRsync;                                 //同步标志
uint8   BitN;                //位码装载数


/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:红外线解码初始化
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void IR_Init()
{
        TMOD &= 0xF0;           //清定时器0
        TMOD |= 0x01;           //定时器0:16位定时器
        TL0 = TH_L;               //每步时间
        TH0 = TH_H;
        ET0 = 1;
        EA  = 1;
        TR0 = 1;
}

/*┈┈┈┈┈┈┈┈┈┈ 基准 ┈┈┈┈┈┈┈┈┈┈┈*/
#define    Boot_Limit            (((9000+4500) +2000)/Step)          //引导码周期上限   
#define    Boot_Lower            (((9000+4500) -2000)/Step)          //引导码周期下限   
#define    Bit1_Limit       ((2250 +800)/Step)                  //“1”周期上限
#define    Bit0_Limit       ((1125 +400)/Step)                          //“0”周期上限
/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
函数:红外线NEC周期采样解码法(定时中断,下降沿查询周期时间)
全局变量:IR_BT = 0无效
                  1有效,待继续判断长、短按(如不需要判断长、短按,则直接使用)
                              2短按
                              3长按
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
void IR_NEC()
{          
        TL0 = TH_L;               //重赋值
        TH0 = TH_H;       

        cntStep++;                   //步数采样
        if(IR_BT==1)if(cntStep>300)IR_BT=2;//解码有效后,如果无长按,120ms(400us×300)后默认短按

        IRb = IRa;                   //上次电位状态
        IRa = IR;                   //当前电位状态
       
        if(IRb && !IRa)                                            //是否下降沿(上次高,当前低)
        {
                if(cntStep > Boot_Limit)      //超过同步时间?
                {       
                    if(IR_BT==1)if(++cntCA>CA_S)IR_BT=3; //解码有效后,继续按住遥控>CA_S即长按
                        IRsync=0;                                  //同步位清0
                }
                else if(cntStep > Boot_Lower){ IRsync=1; BitN=32; }//同步位置1,装载位码数                          
                else if(IRsync)                                                       //如果已同步
                {
                        if(cntStep > Bit1_Limit)IRsync=0;                   
                        else
                        {       
                                NEC[3] >>= 1;                               
                                if(cntStep > Bit0_Limit)NEC[3] |= 0x80;    //“0”与“1”
                if(--BitN == 0)                               
                                {
                                        IRsync = 0;                                     //同步位清0
                            #if (Check_EN == 1)                                       
                                        if((NEC[0]==USER_H)&&(NEC[1]==USER_L)&&(NEC[2]==~NEC[3])) //校验16位用户码、操作码正反码
                                         {  IR_BT=1; cntCA=0;  }             //解码有效,接下来判断:短按?长按?
                                        #else
                                        if(NEC[2]==~NEC[3]){ IR_BT=1; cntCA=0; } //校验操作码正反码
                                        #endif                                       
                                }
                                else if((BitN & 0x07)== 0)       //NEC[3]每装满8位,移动保存一次(即 BitN%8 == 0)
                                {        NEC[0]=NEC[1]; NEC[1]=NEC[2]; NEC[2]=NEC[3];   }
                        }
                }
                cntStep = 0;   //步数计清0
        }
}

//取消相关宏定义
#undef CPU_Fosc

#endif
可以帮忙看看Boot_Limit,Boot_Lower,Bit1_Limit,Bit0_Limit是如何计算出来的?还有IR_NEC是如何解码的?它是一次中断就完成了解码?还是反复多次?谢谢  

相关帖子

沙发
as564335sa| | 2014-11-16 18:10 | 只看该作者
解码的方式有很多,建议仔细看看红外码的波形,看懂了就什么都明白了,这一下贴一堆代码,看代码是很头疼的事

使用特权

评论回复
板凳
喜马拉雅虎|  楼主 | 2014-11-16 18:19 | 只看该作者
以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”,就是他那个'1'周期上限和‘0’周期上限,为什么要(2250+800)/中断时间啊?谢谢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

2

帖子

0

粉丝