打印

PIC 红外遥控解码

[复制链接]
3029|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
892953881|  楼主 | 2015-1-27 20:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我调试这个程式用来做NEC协议的红外遥控解码,但是有问题,我找不到,请给位大神帮帮忙看看是哪里有问题。或者谁有已经调试好的PIC单片机程序红外线解码程序 给我参考一下也可以,先谢谢各位了!!!
我调试时候的现象是没有 解出code_data的值。
#include <pic.h>           //调用PIC16F87XA单片机的头文件


__CONFIG(HS&WDTDIS&LVPDIS);


//---------------------------------------
//1602液晶相关I/O设置


//---------------------------------------
//红外解码寄存器设置
unsigned char tmr_times;
unsigned char code_data;
unsigned char code;
unsigned char int_times;
unsigned char buf1;
bit head_ok;         
bit code_ok;
//---------------------------------------


//---------------------------------------
//名称:解码错误处理函数
//---------------------------------------
void wrong(void)  //如果有错误,将相应寄存器清零,准备下一次接收
{
          int_times=0;
          tmr_times=0;
          head_ok=0;
          code_data=0;         
          code_ok=0;
}

//---------------------------------------
//名称:0或1判断函数
unsigned char one_zero(void)
{         
        //0编码的脉冲周期为1.12ms
        //时间中断为0.25ms,所以我们判定取大于0.75ms小于1.5ms的脉冲均为0编码
          if((tmr_times>3)&(tmr_times<6))
          {
            return 0;
          }
        //1编码的脉冲周期为2.24ms
        //时间中断为0.25ms,所以我们判定取大于1.75ms小于2.75ms的脉冲均为0编码
          else if((tmr_times>7)&(tmr_times<11))
          {
            return 1;
          }
        //如果脉冲周期不在0.75-1.5ms或者1.75-2.75ms区间的,我们认为是错码,返回2
          return 2;
}

//---------------------------------------
//名称:中断服务程序
//---------------------------------------
void interrupt ISR(void)   //PIC单片机的所有中断都是这一个入口
{
    if(T0IF==1)          //需要进一步判断是否是T0中断
    {
        TMR0=0x13;         //定时器中断后,要重置初值,以备下次中断
        T0IF=0;            //清中断标志位,以备下次中断
    //***此处用户自行添加定时器T0中断处理程序***
                tmr_times++;       //每250us计数一次
    //******************************************
    }
        if(INTF==1)            //需要进一步判断是否是INT中断
    {
        INTF=0;            //清中断标志位,以备下次中断     
                GIE=0;                                  //全局中断关掉,以避免解码过程进入其他中断         
                  int_times++;                   //捕捉中断计次       
                  if(head_ok==0)              //如果还没接收到头码,那么先判断脉冲编码是否为头码
                  {
                        //参看遥控器芯片HT6221的说明书,发射代码的头码由一个9ms的起始码和一个4.5ms的结果码组成
                        //本例中,时间中断为0.25ms,所以我们判定大于12.5ms小于14.5ms的脉冲均为13.5ms的头码编码
                    if(tmr_times>50&tmr_times<58)               
                    {
                              head_ok=1;          //有效头码标志位置一,以示头码接收完成
                              int_times=0;    //外部中断计次寄存器清零,以准备接收后面的4组共32个脉冲
                              tmr_times=0;    //定时器中断计次寄存器清零,准备开始对后面的脉冲计时               
                    }
                    else
                    {
                              wrong();        //如果不是有效的头码,转入错误处理程序
                    }
                  }
                  else                        //如果已经接收到头码,那么开始对后面的32个脉冲进行解码                    
                  {          //我调试的时候程序没有进入这个地方
                    code_data=code_data>>1; //将接收缓冲区右移一位,以准备接收下一位
                        buf1=one_zero();                    //判断编码是0或1,或者是错码
                        tmr_times=0;                      //时间中断计次寄存器清零                       
                    if(buf1==1)                        //如果是编码1
                    {
                              code_data|=0x80;          //将1移入code_data的最高位
                    }           
                        else if(buf1==0)                        //如果是编码0
                {
                              code_data&=0x7f;          //将0移入code_data的最高位
                    }   
                        else                            //编码非0非1,即为错码,
            {
                                wrong();                       //调用错误处理程序
                                return;
                        }                                                   
                    if(int_times==8)        //如果收到了8个编码脉冲,意味着低8位地址码已经接收完
                    {
                                //本遥控器的低8位地址码为0X00,这个是遥控器厂家决定的,如果要订做,可以随便改
                        if(code_data!=0x00)  //如果不是0x00 ,说明不是我们提供的遥控器,我们不予识别
                        {
                                wrong();         //调用错误处理程序      
                                        return;  
                        }                   
                    }
                    else if(int_times==16)        //如果收到了16个编码脉冲,意味着高8位地址码已经接收完
                    {
                                //本遥控器的低高8位地址码为0XFF
                        if(code_data!=0xFF)  //如果不是0xff ,说明不是我们提供的遥控器,我们不予识别
                        {
                            wrong();         //调用错误处理程序      
                                        return;
                        }                                       
                    }
                    else if(int_times==24)    //收到的第三组8位字节即为8位数据码
                    {
                              code=code_data;    //将这个8位数据码暂存至code_data1                         
                    }
                    else if(int_times==32)    //收到的第四组8位字节即为8位数据码的反码
                    {
                              int_times=0;                //清零中断次数寄存器,以便下次从头开始               
                              head_ok=0;            //将头码标志位清零,以便下次再接收时,从头码开始                                                   
                              if((code+code_data)==0xff)    //判断第三组数据和第四组数据是否互为反码                         
                              {                                 
                            code_ok=1;                      //如果互为反码,说明接收来的编码为正确,置位标志位,以通知液晶显示       
                    }                             
                    }
                  }
                  GIE=1;           //开放全局中断                 
          }          
}

//---------------------------------------
//名称: 主函数
//---------------------------------------
void main(void)            //主函数,单片机开机后就是从这个函数开始运行
{

    TRISB=0B11111111;      //初始化RB7-RB0的输入输出方向
    TRISD=0B00000000;      //初始化RD7-RD0的输入输出方向
    PORTB=0B00000000;      //初始化RB7-RB0的数值
    PORTD=0B00000000;      //初始化RD7-RD0的数值
    //***定时器TMR0初始化***
    T0CS=0;                //TMRO时钟源选择内部指令周期时钟(Fosc/4)
    PSA=1;                 //预分频器分配给WDT
    TMR0=0x13;             //定时250微秒,置初值为256-250+13
    T0IF=0;                //清除TMR0的中断标志
    T0IE=1;                //TMR0中断允许
    //**********************

        //***外部中断RB0/INT初始化***
    INTEDG=0;             //设置RB0/INT为下降沿触发
    INTF=0;               //清除RB0/INT的中断标志
    INTE=1;               //设置RB0/INT中断允许
    //***************************

    //***开全局中断设置****
    //外部中断RB0/INT设置了中断允许,此处要开全局中断
    GIE=1;                 //开全局中断
    //外部中断RB0/INT设置了中断允许,此处要允许所有未被屏蔽的外设中断
    PEIE=1;                //允许外设中断
    //*********************

    while(1)                   //死循环,单片机初始化后,将一直运行这个死循环
    {
                if(code_ok==1)         //如果接收到了有效地的遥控器按键码
            {
                    code_ok=0;         //清掉该标志位
                    if(code==0x16) PORTD=0B00000001;
            if(code==0x0c) PORTD=0B00000010;
            if(code==0x18) PORTD=0B00000100;
            if(code==0x5e) PORTD=0B00001000;
            if(code==0x08) PORTD=0B00010000;
            if(code==0x1c) PORTD=0B00100000;
            if(code==0x5a) PORTD=0B01000000;
            if(code==0x42) PORTD=0B10000000;                               
              }           
        }
沙发
892953881|  楼主 | 2015-1-27 20:37 | 只看该作者
问题出在INT中断中解码这块。麻烦给位前辈给我看下

使用特权

评论回复
板凳
JY-DX-JY| | 2015-1-28 17:50 | 只看该作者
要看你测得周期准不准。

使用特权

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

本版积分规则

13

主题

42

帖子

2

粉丝