单片机与自动控制
-->

新手求助!这程式错在那里?红外遥控接收

83865

新版来袭 收藏
本人新学51单片机,写个红外遥控接收,调试总是不行,以下我只上了遥控接收部分。处理与显示我没上传,请高手指点错在那里!

  谢谢!


#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int

sbit ir_pin = p3^3;       //由于我的mcu p3^2烧了,只能用暂时代用p3^3

void delay_850us(n)       //延时函数 使用11.0592mhz
{
uint i;
for(;n!=0;n--)
for(i=95;i!=0;i--);
}

uchar ir()             //译码函数
{
uchar tempcode[4],i,j;   //遥控码临时存放区
while(ir_pin==0);       //等待4.5ms高电平出现  
delay_850us(5);
while(ir_pin==1);       //等待0.56ms低平出现
for(i=0;i<4;i++)
  {
    for(j=8;j!=0;j--)
      {
        tempcode>>=1;
        while(ir_pin==0);       //等待0.56高平出现
        delay_850us(1);
        if(ir_pin==1)
          {
            tempcode|=0x80;   //1处理
            while(ir_pin==1);   //等待1的高平消失
          }
        else if(ir_pin==0)
            tempcode|=0x00;   //0处理
      } //end j

  }//end i
if((tempcode[2]==~tempcode[3])&&(tempcode[0]==~tempcode[1])) return tempcode[2]; //比较是否正确,如正确返回遥控码
else return 0;                         //错误则返回0
}


int_0()interrupt 2 using 3   //中断函数
{
uchar i;
ea=0;
  for(i=10;i!=0;i--)     //确认是遥控不是干扰,重复检测10次
    {
      if(ir_pin==0)
      delay_850us(1);
      else
      {ea=1;return;}   //如9ms有高电平就退出,认定是干扰
    }
  p0=ir();           //调用译码函数
  ea=1;
  return;
}


void main()             //主函数
{

ex1=1;       //开外部1中断
ea =1;       //开总中断
// delay_850us(1);
while(1);
}
2007-09-17 21:48:10
回复
  • VR2ZUY(Lv6注册用户)
    1#
    硬件上那个p3...上拉了没有?
    2007-09-17 23:40:04
    回复
  • bd7bq(Lv6注册用户)
    2#
    一点意见供参考:
    1,延时最好用定时器精确延时.
    2,注意接收管要好.我测试过很多,在没有38k红外线遥控信号的时候也有干扰脉冲输出.模块内部一般都有上拉的,上拉不一定能解决问题.要不选用好的接收模块,要不在程序内做滤波.你可以写个简单程序判断下接收模块在无信号的时候有无错误输出.再决定下一步.
    3,编码芯片上的发送波形在接收上可能是反相的,也注意一下.
    欢迎高手对我的拙见拍砖.
    2007-09-18 22:18:04
    回复
  • 邓福强(Lv6注册用户)
    3#
    '
    一点意见供参考:
    1,延时最好用定时器精确延时.
    2,注意接收管要好.我测试过很多,在没有38k红外线遥控信号的时候也有干扰脉冲输出.模块内部一般都有上拉的,上拉不一定能解决问题.要不选用好的接收模块,要不在程序内做滤波.你可以写个简单程序判断下接收模块在无信号的时候有无错误输出.再决定下一步.
    3,编码芯片上的发送波形在接收上可能是反相的,也注意一下.
    欢迎高手对我的拙见拍砖.
    '



    延时函数上面有,按这程式有没有错?接收模块有信号出,反相也注意到了!
    2007-09-21 20:30:49
    回复
  • bd7bq(Lv6注册用户)
    4#
    那个延时函数不会是准确的400us的,你改成定时器延时好些.
    2007-09-21 21:15:11
    回复
  • BG4UVR(Lv6注册用户)
    5#
    这是一个已经测试过的接收代码,请自己研究一下

    1. void ir_in() interrupt 0
    2. {
    3.      unsigned char i,j,k,n=0 ;
    4.      ea = 0 ;
    5.      i1:
    6.      for (i=0 ;i<4 ;i++)
    7.      {
    8.            if (irin==0) break ;
    9.            if (i==3) {ea =1 ;return ;}
    10.      }
    11.      delay(20) ;                                    //延时2.8ms
    12.      if (irin==1) goto i1 ;            //确认ir信号出现
    13.      while (!irin)                    //等 ir 变为高电平
    14.            {delay(1) ;}
    15.      
    16.      for (j=0 ;j<4 ;j++)
    17.      {
    18.            for (k=0 ;k<8 ;k++)
    19.            {
    20.                  while (irin)         //等 ir 变为低电平
    21.                  {delay(1) ;}
    22.                  while (!irin)       //等 ir 变为高电平
    23.                  {delay(1) ;}
    24.                  while (irin)       //计算ir高电平时长
    25.                  {
    26.                        delay(1) ;
    27.                        n++ ;      
    28.                        if (n>=30) {ea=1 ;return ;}
    29.                  }
    30.                  ircom[j]=ircom[j] >> 1 ;                                    //把ircom右移一位
    31.                  if (n>=8) {ircom[j] = ircom[j] | 0x80 ;}            //如果高电平时间太于8*0.14=1.12ms,就将此为置1(否则为0)
    32.                  n=0 ;
    33.            }//end for k
    34.      }//end for j
    35.      
    36.      if ((ircom[0]!=~ircom[1])||(ircom[2]!=~ircom[3])){
    37.            ea=1 ;return ;
    38.      }
    39.      flag=1;                  //置接收有效标志
    40.      ea = 1 ;
    41. }
    42. //0.14ms延时
    43. void delay(unsigned char x)                        //x*0.14ms
    44. {
    45.      unsigned char i ;
    46.      while(x--)
    47.      {
    48.            for (i = 0 ; i<13 ; i++) {}
    49.      }
    50. }
    2007-09-22 08:02:29
    回复
  • bd7bq(Lv6注册用户)
    6#
    我也再贴一个,ht6221的

    sbit remo=p3^2;   //遥控接收输入脚
    uchar key_value; //定义键值变量,用于识别按键

    unsigned char k;

    void infraredkey()   //红外线键盘
    {
      uchar i=0,output=0;
      bit keyflag=0;
      uint time;
      tmod=0x01;
      tl0=0;
      th0=0;
      while(!keyflag)
      {
          k=0;
        th0=tl0=0;
        tr0=1;
        while(remo) if(th0>0x50) return;   //等待红外线信号
        th0=tl0=0;
        tr0=1;
        while(!remo) if(th0>0x50) return;   //等待高电平出现
        th0=tl0=0;
        tr0=1;       //打开计数器0
        while(remo)if(th0>0x50) return;   //等待高电平结束
        time=(th0<<8)+tl0;   //取得高电平宽度
        tr0=0;         //关计数器0
        if((time>1900) && (time<2700))
        {
         k=1;
        }
        else if((time>350)&&(time<750));   //是0保存 565
        else if((time>1300)&&(time<1750)) //是1保存 1690
        {
            if(i>16) output+=1<<(i-17); else; //取最后一字节的数据码(反码)
        }      
        else
        {
            output=0;
            i=0;
        }
        if(i++==24 )
        {
            key_value=output;
            keyflag=1;
         yk_proc(); 头 //接收到遥控码处理
        }
        tl0=0;
        th0=0;
        if(k) {yk_proc();}   //重复码
      }
    }

    void intt0(void) interrupt 0
    {
         infraredkey();
    }

    晶体是11.0592的,不过12m可能也可以使用,我把判断范围定得很大.
    2007-09-23 19:43:50
    回复
  • 邓福强(Lv6注册用户)
    7#
    谢谢bd7bq、bg4uvr , 我还是闭关学好c语言先!
    2007-10-12 20:01:07
    回复
  • 邓福强(Lv6注册用户)
    8#
    终于成功了,初学单片机,注释可能不是正确,请大家不要见笑,下面是我和代码




    /****************************************************************
                功能: 红外线遥控接收
                时锺: 11.0592mhz
                作者: 邓福强
                tel:   0769-21353277
                qq:   369127282(隐身)
                e-mail:wiseton@21cn.com
    /***************************************************************/
    #include <reg52.h>
    #define uchar unsigned char   //定义方便使用
    #define uint unsigned int    

    uchar key_value;
    sbit ir_pin = p3^3;         //由于我的mcu p3^2烧了,只能用暂时代用p3^3

    void int_t0_1120us()         //定时延时函数     延时1.12ms        
    {                     //初始化t0定时1120us;
      tf0=0;              
      tmod|=0x01;             //设t0工作在16位定时模式
      th0=(65536-1022)/256;      
      tl0=(65536-1022)%256;
      tr0=1;               //t0开始运行
    }

    void int_t0_2400us()         //定时延时函数     延时2.4ms        
    {                     //初始化t0定时2400us;
      tf0=0;              
      tmod|=0x01;             //设t0工作在16位定时模式
      th0=(65536-2200)/256;      
      tl0=(65536-2200)%256;
      tr0=1;               //t0开始运行
    }


    void int_t0_850us()         //定时延时函数     延时0.85ms      
    {                     //初始化t0定时850us;
      tf0=0;              
      tmod|=0x01;             //设t0工作在16位定时模式
      th0=(65536-775)/256;      
      tl0=(65536-775)%256;
      tr0=1;               //t0开始运行
    }


    ir()               //译码函数 此函数不能有while(ir_pin==1)的表达式,如有此表达式会偶然进入死循环,但可以用while(ir_pin==0)
    {
    uchar data tempcode[4],i,j; //遥控码临时存放区
    while(ir_pin==0);         //等待4.5ms高电平出现(重码为2.25ms)
    int_t0_2400us();         //延时2.4ms,理论要检测2.53125ms的电平
    while(tf0!=1);
    if(ir_pin==1)           //延时2.4ms后判断是高电平是为新码,低电平为重码
    int_t0_2400us();         //如是代电平则跳过4.5ms的引导码,理论要跳到4.78125ms
    while(tf0!=1);
    for(i=0;i<4;i++)         //接收4字节
      {                 //接收8位
        for(j=8;j!=0;j--)
          {
            while(ir_pin==0);       //等待0.56高平出现
            int_t0_850us();         //延时850us,检测延时0.85后的电平,高是1,低是0
            while(tf0!=1);
            tempcode>>=1;       //从低位开始接收,左移一位准备接收
            if(ir_pin==1)         //延时850us后,判断此时ir_pin的电平
              {
                tempcode|=0x80;   //1处理,0不用处理,0只是移位就ok
                int_t0_1120us();     //延时1120us,跳出1高电平
                while(tf0!=1);     //跳到1高平后(2.25-0.5625=1.69ms)的低电平,理论要跳到(2.25-0.5625+0.5625/2=1.96875ms)
                              //此处不能用while(ir_pin==1);如用while(ir_pin==0);在接收最后一位是1会有时会进入死循环?
              }
          } //end j               //下1字节
      }//end i
      if(tempcode[2]==~tempcode[3])       //比较是遥控码否正确,如要比较用户码用:if((tempcode[0]==~tempcode[1])&&(tempcode[2]==~tempcode[3]))
      key_value=tempcode[2];           //如正确返回遥控码
      else return;                 //错误则返回
    }


    int_2()interrupt 2 using 3           //中断函数
    {
    uchar i;
      for(i=10;i!=0;i--)             //确认是遥控不是干扰,重复检测10次 0.85*10=8.5ms
        {                    
          if(ir_pin==0)           //是否有低电平?
          {
            int_t0_850us();         //延时850us
            while(tf0!=1);
          }
          else
            return;             //如9ms有高电平就退出,认定是干扰
        }
      ea=0;                     //关中断,在接收过程中有中断将接收失败
      ir();                     //调用译码函数
      p0=key_value;
      ea=1;                     //开中断
    }


    void main()       //主函数
    {
    ex1=1;         //开外部1中断
    ea =1;         //开总中断
    while(1);
    }
    2007-11-15 16:51:33
    回复
欢迎加入讨论。
我是有底线的