搜索
bottom↓
回复: 9

红外遥控解码不正确,请大家帮忙? (采用INT0和T2解码)

[复制链接]

出0入0汤圆

发表于 2007-9-20 09:25:11 | 显示全部楼层 |阅读模式
可以进INT0中断,当打开T2定时器时,接收的数据不对,请大家帮忙看看,谢了!
解码思路:第一次进入ITN0中断时,打开T2定时器,当再次时入INTO中断,计算两次中断的时间差,来确定是引导码,还是“0”或“1”。
           接收完32位数据时,关T2定时器。
编译器:ICC6.31
CPU: ATmega32L

源程序:


//T2中断初始化
void T2_Start(void)                     
{
     TIMSK|=(1<<TOIE2);                        //溢出中断使能
     TCCR2 = 0x00;              //关定时器
     TCNT2 = 0x00;
     TCCR2 = 0x07;              //1分频,定时35uS
}

//关T2中断         
void T2_Stop(void)                     
{
     TCCR2 =0x00;            
     TIMSK&=0x3f;                //关溢出中断
}

//INT0中断初始化
void INT0_Init(void)
{
    MCUCR|=(1<<ISC01);                //下降沿触发
    GICR |=(1<<INT0);                        //INT0中断使能
}

//T2中断程序
#pragma interrupt_handler T2_Interrupt:6
void T2_Interrupt(void)   
{
     if(IF_RecvDataCount>0)
         {
                   IF_RecvNewTime++;
         }         
}

//INTO中断程序
#pragma interrupt_handler INT0_Interrupt:2
void INT0_Interrupt(void)  
{
    unsigned char j,i,Temp,Mode,Dat,RcvFlag;
       
        CLI();
        IF_RecvDataCount++;                                   //中断次数计数       
       
        //PutString_Usart(IF_RecvDataCount);
       
        Temp=(IF_RecvNewTime-IF_RecvOldTime);                //中断间距
        IF_RecvOldTime=IF_RecvNewTime;                       
       
        if(IF_RecvDataCount==1)                              //第一次进中断
        {
                   T2_Start();                          //启动定时器,35us中断一次
                IF_RecvNewTime=0;
                IF_RecvOldTime=0;
        }
        else
        {
                   if( (Temp>310)&&(Temp<340) ) //重码不处理,退出
                {
                            T2_Stop();
                         IF_RecvDataCount=0;
                         IF_RecvNewTime=0;
                         IF_RecvOldTime=0;
                         IR_Addr=0;
                         IR_Data=0;
                         RcvFlag=0;
                }         
                if( (Temp>370)&&(Temp<400) ) //引导码
                {
                     RcvFlag=0;               
                }
          
                if( (Temp>25)&&(Temp<40) ) // 0
                {
                     Dat=0;
                     RcvFlag=1;                       
                }         
                  else if( (Temp>55)&&(Temp<70) ) // 1
                     {
                              Dat=1;
                              RcvFlag=1;       
                     }          

                 if(RcvFlag==1)
                 {                        
                         if( (IF_RecvDataCount>2)&&(IF_RecvDataCount<20) )
                         {
                                       IR_Addr|=Dat;
                                  if(IF_RecvDataCount<19) IR_Addr<<=1;
                                  RcvFlag=0;
                           }
                         else if( (IF_RecvDataCount>19)&&(IF_RecvDataCount<34) )
                              {
                                           IR_Data|=Dat;
                                           IR_Data<<=1;
                                         RcvFlag=0;
                                  }
                               else if(IF_RecvDataCount==34)
                                  {
                                        IR_Data|=Dat;
                                                            
                                        IF_RecvDataOver=0;
                                               
                                        T2_Stop();                  //接收完毕,清计数器
                                           IF_RecvDataCount=0;
                                        IF_RecvNewTime=0;
                                        IF_RecvOldTime=0;
                                        IR_Addr=0;
                                        IR_Data=0;
                                        RcvFlag=0;
                                  }
                   }                                 
         }
       SEI();
}


//主程序
void main(void)
{
           //IO PORT INIT
         PORTA = 0xFF;
         DDRA  = 0xFF;
         
         PORTB = 0xFF;
         DDRB  = 0xBF;         
         
         PORTC = 0xFF;
         DDRC  = 0xFF;
         
         PORTD = 0xFF;
         DDRD  = 0xFA;

     //INT0 INIT
     INT0_Init();        //INT0初始化       

     SEI();
         
         while(1)
         {         
             ;
         }
   
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2007-9-20 09:43:08 | 显示全部楼层
不要用那么频繁的中断去解码,我也用过,蛮麻烦的,除非你的系统时间要求那么高,必须得中断。

直接调用delay.h的函数去延时吧,这样非常简单。

出0入0汤圆

 楼主| 发表于 2007-9-20 09:46:40 | 显示全部楼层
lvhaian你好,能不能把你的程序贴出来看看,谢谢了!

出0入0汤圆

发表于 2007-9-20 11:07:54 | 显示全部楼层
给一个给你参考一下,IRDATA为红外输入脚:
#include <*mcu*.h>

unsigned char space_key_time,work_mode;
unsigned char recedata()
{
unsigned char i;
unsigned int key_data,temp_key;
unsigned int irdatatime_s,irdatatime_m,irdatatime_e;
unsigned int irdatatime_hw,irdatatime_lw;

irdatatime_s=TM00;//read start time
temp_key=0x800;
key_data=0;
for(i=12;i!=0;i--)
    {
     do//IRDATA==0
       {
        irdatatime_m=TM00;//read mid time
        irdatatime_lw=irdatatime_m-irdatatime_s;
        if(irdatatime_lw>IRDATAL_MAX) return 1;//rece error
       }
     while(IRDATA==0);
     if(irdatatime_lw<IRDATAH_MIN) return 1;//rece error
   
     do//IRDATA==1
       {
        irdatatime_e=TM00;//read end time
        irdatatime_hw=irdatatime_e-irdatatime_m;
        if(irdatatime_hw>IRDATAL_MAX)

{
           if(i!=1) return 1;//rece error,isn't last bit
           else goto REC2;
          }
       }
     while(IRDATA==1);

    REC2:
     if(irdatatime_hw<IRDATAH_MIN) return 1;//rece error
   
      
      
     if(i==1)//last bit
       {
       if((IRDATAL_MIN<irdatatime_lw)&&(irdatatime_lw<IRDATAL_MAX))
         {//DATA IS 1
          key_data=key_data|temp_key;
         }
       else
         {//data is 0
          if((IRDATAH_MIN<irdatatime_lw)&&(irdatatime_lw<IRDATAH_MAX));
          else return 1;//rece error
         }
       }
     else

{
        if((irdatatime_hw+irdatatime_lw)>(IRDATAL_MAX+IRDATAH_MAX))
          {
           if(i!=1) return 1;//isn't last bit
          }
      
        if((IRDATAH_MIN<irdatatime_hw)&&(irdatatime_hw<IRDATAH_MAX)&&(IRDATAL_MIN<irdatatime_lw)&&(irdatatime_lw<IRDATAL_MAX))
          {//DATA IS 1
           key_data=key_data|temp_key;
          }
        else
          {//data is 0
           if((IRDATAL_MIN<irdatatime_hw)&&(irdatatime_hw<IRDATAL_MAX)&&(IRDATAH_MIN<irdatatime_lw)&&(irdatatime_lw<IRDATAH_MAX));
           else return 1;//rece error
          }
       }
      
     temp_key=temp_key>>1;
     irdatatime_s=irdatatime_e;
    }
switch(key_data)
       {
        case key_data1:
             {
              work_mode1();
              break;
             }
            
        case key_data2:
             {
              work_mode2();

              break;
             }
  
        case key_data3:
             {
              work_mode3();

              break;
             }
            
        default:return 1;
       }

}

void main()

{

do
   {
    WDOG;//run watchdog
    io_init();//i/o口初始化
    if(IRDATA==0) recedata();//如红外I/O口有信号
   }
while(1);
}

/*******************************************************************************/
一起进步一起成长!
欢迎登陆我的blog:blog.sina.com.cn/suzhoumcu
/******************************************************************************/

出0入0汤圆

发表于 2007-9-20 11:26:28 | 显示全部楼层
没有带阿,在家里,晚上发

出0入0汤圆

 楼主| 发表于 2007-9-20 12:11:33 | 显示全部楼层
好,谢谢!
这是我用INT0中断+延时做的,接收始终为0XFFFF,请大家看看问题在哪里?多谢!

源程序:
INT0的初始化就不发了,上面有

#pragma interrupt_handler INT0_Interrupt:2
void INT0_Interrupt(void)  
{
    unsigned char i;
       
    CLI();
    //GICR &=~(1<<INT0);                                   //关INT0中断使能
   
    for(i=0;i<3;i++)                                  //去除干扰
    {
             delay_nms(1);                              //delay 1ms
             if(PIND&0X04)
             {
                    IF_RecvAddr=0;
                   IF_RecvData=0;
                     goto ret;
            }   
    }
   while( PIND&0x04 );                 //等待高电平,延时4.5ms

   while( !(PIND&0x04) );                    //等待低电平
       
   //开始接收用户码
   for(i=0;i<16;i++)  
   {
         while( PIND&0x04 );                          
        delay_nus(230);                              //delay 700us
         if(PIND&0x04)         
         {
                IF_RecvAddr|=(1<<i);  
                while( !(PIND&0x04) );              
         }
         else
            {
                IF_RecvAddr&=~(1<<i);
             }
    }

   //开始接收数据
   for(i=0;i<16;i++)
    {  
        while( PIND&0x04 );  
        delay_nus(230);                             //delay 700us
        if(PIND&0x04)
        {
                IF_RecvData|=(1<<i);
                while( !(PIND&0x04) );
        }
        else
            {
                IF_RecvData&=~(1<<i);
            }
    }

        ret://GICR |=(1<<INT0);                        //INT0中断使能
            SEI();
}

出0入0汤圆

发表于 2007-9-20 16:55:46 | 显示全部楼层
楼主,如果你定时器是用溢出方式的,那确实不准的,我以前也是搞了很久才发现溢出中断不准。

建议红外解码用输入捕抓来做,很简单,也很准确

出0入0汤圆

 楼主| 发表于 2007-9-20 17:35:50 | 显示全部楼层
谢谢eagle2006提醒,T2定时器确实是用溢出方式的。
输入捕抓脚被其它脚占用,板了已经做好不可能再更了,
没办法,不准也只能这样了

出0入0汤圆

发表于 2007-9-21 14:27:41 | 显示全部楼层
要配合示波器仔细调整溢出时间.

出0入0汤圆

发表于 2008-3-21 17:57:14 | 显示全部楼层
ym_avr,看到你的帖子,不知道你的问题解决没有,我也正遇到和你一样的问题,解码的方法和你一样,不知道是否可以交流下?
QQ:517077621
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-13 14:02

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表