论坛风格切换切换到宽版
  • 3764阅读
  • 8回复

新手求助!这程式错在那里?红外遥控接收 [复制链接]

上一主题 下一主题
离线邓福强
 
发帖
34
只看楼主 倒序阅读 0楼 发表于: 2007-09-17
本人新学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);
}
离线VR2ZUY
发帖
1621
只看该作者 1楼 发表于: 2007-09-17
硬件上那个p3...上拉了没有?
离线bd7bq
发帖
1491
只看该作者 2楼 发表于: 2007-09-18
一点意见供参考:
1,延时最好用定时器精确延时.
2,注意接收管要好.我测试过很多,在没有38k红外线遥控信号的时候也有干扰脉冲输出.模块内部一般都有上拉的,上拉不一定能解决问题.要不选用好的接收模块,要不在程序内做滤波.你可以写个简单程序判断下接收模块在无信号的时候有无错误输出.再决定下一步.
3,编码芯片上的发送波形在接收上可能是反相的,也注意一下.
欢迎高手对我的拙见拍砖.
离线邓福强
发帖
34
只看该作者 3楼 发表于: 2007-09-21
'
一点意见供参考:
1,延时最好用定时器精确延时.
2,注意接收管要好.我测试过很多,在没有38k红外线遥控信号的时候也有干扰脉冲输出.模块内部一般都有上拉的,上拉不一定能解决问题.要不选用好的接收模块,要不在程序内做滤波.你可以写个简单程序判断下接收模块在无信号的时候有无错误输出.再决定下一步.
3,编码芯片上的发送波形在接收上可能是反相的,也注意一下.
欢迎高手对我的拙见拍砖.
'



延时函数上面有,按这程式有没有错?接收模块有信号出,反相也注意到了!
离线bd7bq
发帖
1491
只看该作者 4楼 发表于: 2007-09-21
那个延时函数不会是准确的400us的,你改成定时器延时好些.
离线BG4UVR
发帖
11288
只看该作者 5楼 发表于: 2007-09-22
这是一个已经测试过的接收代码,请自己研究一下

  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. }
离线bd7bq
发帖
1491
只看该作者 6楼 发表于: 2007-09-23
我也再贴一个,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可能也可以使用,我把判断范围定得很大.
离线邓福强
发帖
34
只看该作者 7楼 发表于: 2007-10-12
谢谢bd7bq、bg4uvr , 我还是闭关学好c语言先!
离线邓福强
发帖
34
只看该作者 8楼 发表于: 2007-11-15
终于成功了,初学单片机,注释可能不是正确,请大家不要见笑,下面是我和代码




/****************************************************************
            功能: 红外线遥控接收
            时锺: 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);
}