一乐电子

一乐电子百科

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 2625|回复: 13
收起左侧

[51单片机] GPS+12864+18B20+IR+Key万年历,遥控求助

[复制链接]
发表于 2015-6-1 20:45 | 显示全部楼层 |阅读模式
仿做了这个万年历,遥控一直不能用,有那位大侠指教下看改动那里,才能配上这个遥控

#ifndef  _IR_H_
#define  _IR_H_

unsigned char keya,keyb,keyc,keyd,keye,keyf,keyg,keyh,keyi,keyj;
unsigned char key_add,key_minus,key_set,key_ok,key_up,
                          key_down,key_alARM,key_voioff,key_voion,key_light;

//bit  ala_flag=0;  //闹钟使能标志位
//bit  back_light_flag=0;//背光使能
sbit IRIN = P3^5; //红外接收器数据线

unsigned char IRCOM[]={0x00,0x00,0x00,0x00,0x10,0x10};
/***************************************************************
            外部中断0响应函数,完成对红外遥控的解码
-------------------------协议--------------------------   
----开始拉低9ms,接着是一个4.5ms的高脉冲,通知器件开始传送数据了
----接着是26位前导脉冲,用于识别该型号的摇控。                                 
----然后是发送8位数据的原码,接着又发送8位数据的反码.
----最后是一个长脉冲,和开始位一样,拉低9ms和一个4.5ms脉冲表示结束。
----每个按键不同这处只在于那8位数据的原码和反码,因些只须要识别
----8位原码就可以识别按键了
****************************************************************/
void delayA(unsigned char x)    //x*0.14MS
{
  unsigned char i;
  while(x--)
{
  for (i = 0; i<13; i++) {}
}
}
//=====================================================
void IR_IN() interrupt 0 //using 0
{
  unsigned char j,k,N=0;

     EX0 = 0;   
         delayA(15);
         if (IRIN==1)
     { EX0 =1;
           return;
          }
                           //确认IR信号出现
  while (!IRIN)            //等IR变为高电平,跳过9ms的前导低电平信号。
{delayA(1);}

for (j=0;j<4;j++)         //收集四组数据
     {
      for (k=0;k<8;k++)        //每组数据有8位
                  {
                           while (IRIN)            //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
                     {delayA(1);}//
                    while (!IRIN)          //等 IR 变为高电平
                           {delayA(1);}  //
                     while (IRIN)           //计算IR高电平时长
                      {
                      delayA(1);
                      N++;           
                      if (N>=30)
                                 { EX0=1;
                                 return;}                  //0.14ms计数过长自动离开。
                      }                        //高电平计数完毕               
              IRCOM[j]=IRCOM[j] >> 1;                  //数据最高位补“0”
              if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;}  //数据最高位补“1”
              N=0;
             }//end for k
    }//end for j

    if (IRCOM[2]!=~IRCOM[3])   //接收时间是否正确
    {
      EX0=1;
      return;
    }
/*================红外编码处理====================*/  
     switch(IRCOM[2])
            {
                case 0x00: keya=1;                  break;   //1
                case 0x01: keyb=1;                  break;   //2
                case 0x02: keyc=1;                  break;   //3
                case 0x03: keyd=1;                  break;   //4
                case 0x04: keye=1;                  break;   //5
                case 0x05: keyf=1;                  break;   //6
                case 0x06: keyg=1;                  break;   //7
//                case 0x07: keyh=1;                  break;   //8
                case 0x08: keyi=1;                         break;   //9
//                case 0x09: keyj=1;                  break;   //0
//遥控器1(电视遥控器)
/*
                case 0x13: key_minish=1;          break;   //-
                case 0x12: key_add=1;                  break;   //+
                case 0x18: key_manue=1;          break;   //菜单
                case 0x19: key_ok=1;                  break;   //OK
                case 0x15: key_alarm=1;     break;   //关闹钟的开与关
*/
//遥控器2(ALETNK遥控器)
                case 0x15: key_add=1;                 break;   //+
                case 0x07: key_minus=1;         break;   //-  
                case 0x44: key_set=1;                 break;   //菜单        
                case 0x40: key_ok=1;                  break;   //OK        
                case 0x47: key_alarm=1;     break;   //关闹钟的开与关
                case 0x45: key_light=1;        break; //背光控制

                case 0x10: key_up=1;        break;   //上
                case 0x11: key_down=1;      break;   //下
                case 0x14: key_voioff=1;    break;   //静音
                case 0x17: key_voion=1;     break;   //声音
                default:                                           break;   //别的键按下
        }
/*   if(key_alarm==1)//闹钟的开与关的设置标志位
           {
                key_beep();
                key_alarm=0;
                ala_flag=~ala_flag;
                key_alarm=0;
           }
    if(key_light==1)
          {
           key_beep();
           key_light=0;
       back_light_flag=~back_light_flag;
           key_light=0;
           }
*/         
     EX0 = 1; //开中断
}
/**************************
  ALIENTEK遥控器键码值
        45H | 46H | 47H        
        ---------------
        44H | 40H | 43H
        ---------------
        07H | 15H | 09H
        ---------------
        16H | 19H | 0DH
        ---------------
        0CH | 18H | 5EH
        ---------------
        08H | 1CH | 5AH
        ---------------
        42H | 52H | 4AH
***************************/
#endif
1.jpg CAR.jpg PIC_20150601_202624_EE6.jpg

发表于 2015-6-1 20:58 | 显示全部楼层
孔开得不错。就是体积大了点,相对地字小了点。不如直接改成导航仪吧,装在车上起到提高X格的作用。
发表于 2015-6-1 21:23 | 显示全部楼层
延时函数。如果你用的晶振频率与原来的不一致,就会导致延时长短不一样。这个红外解码的关键就是时间
发表于 2015-6-1 21:24 | 显示全部楼层
本帖最后由 xrff_z 于 2015-6-1 21:29 编辑

延时函数。如果你用的晶振频率与原来的不一致,就会导致延时长短不一样。这个红外解码的关键就是时间
怎么一下回了三次

下面是用定时器来计时的,可以参考下

void ir_init()
{
   
    TMOD = (TMOD & 0xF0) | 0x01;  //定时器0工作模式=1 16位定时不可重装载模式  只设置定时器0的模式,不改变定时器1的模式
TH0=0;
TL0=0;
TR0=0;  //关闭定时器T0
p_ir=1;       //IO口初始化
IT1=1;    //外部中断1为下降沿中断方式
EX1=1;    //INT1外部中断开
}
/************************************************************
函数功能:对4个字节的用户码和键数据码进行解码
说明:解码正确,返回1,否则返回0
出口参数:dat
*************************************************************/
bit DeCode(void)        
{
    unsigned char  i,j;
unsigned char temp;    //储存解码出的数据
for(i=0;i<4;i++)      //连续读取4个用户码和键数据码
   {
   for(j=0;j<8;j++)  //每个码有8位数字
    {
          temp=temp>>1;  //temp中的各数据位右移一位,因为先读出的是高位数据         
            TH0=0;         //定时器清0
      TL0=0;         //定时器清0
      TR0=1;         //开启定时器T0
     while(!p_ir){
       LowTime=TH0*256+TL0;
    if(LowTime>2000)return 0;
    }   //如果是低电平就等待 低电平计时
      TR0=0;         //关闭定时器T0
      LowTime=TH0*256+TL0;    //保存低电平宽度
      
      TH0=0;         //定时器清0
      TL0=0;         //定时器清0
      TR0=1;         //开启定时器T0
      while(p_ir){HighTime=TH0*256+TL0;
    if(HighTime>4000)return 0;
    }  //如果是高电平就等待, 高电平计时
      TR0=0;        //关闭定时器T0
      HighTime=TH0*256+TL0;   //保存高电平宽度
               
//脉冲个数与频率有关 11.0592M 1ms~922个脉冲,12M 1ms=1000个脉冲,22.1184M 1ms ~1843个脉冲,30M ~2500个脉冲
//UPD6121 标准长度0.56ms。"0"发射、不发射0.56ms,”1” 发射0.56ms,不发射1.68ms。发射-低电平LowTime
//22.1184M 0.56ms=1032个脉冲  1.68=3096个脉冲
    if((LowTime<830)||(LowTime>1230))return 0; //如果低电平长度不在合理范围,则认为出错,停止解码   
    if((HighTime>830)&&(HighTime<1230)) temp=temp&0x7f;     //如果高电平时间在0.56ms左右 则该位是0
    if((HighTime>2900)&&(HighTime<3300))temp=temp|0x80; //如果高电平时间在1.68ms左右,则该位是1
       }//j循环8次,得到一个字节                 
ircode=temp; //将解码出的字节值储存在 ircode                     
    }//i循环4次,得到四个字节  
if(ircode[2]=~ircode[3])
return 1;   //验证键数据码和其反码是否相等,一般情况下不必验证用户码 解码正确,返回1
else
return 0;
}

/************************************************************
函数功能:红外线触发的外中断处理函数
*************************************************************/
void ir_read(void) interrupt 2
  {
     EX0=0;     //关闭外中断0,
  EX1=0;     //关闭外中断1,不再接收二次红外信号的中断,只解码当前红外信号
  delay_ms(1);
  if (p_ir==1)
     { EX1=1;
    EX0=1;
    return;
   }
   TH0=0;         //定时器清0
      TL0=0;         //定时器清0
      TR0=1;       //开启定时器T0
           while(!p_ir){
       LowTime=TH0*256+TL0;
    if(LowTime>20000){p_ir=1;TR0=0;EX1=1;EX0=1;return;}
    }   //如果是低电平就等待 低电平计时
         TR0=0;         //关闭定时器T0
      LowTime=TH0*256+TL0;    //保存低电平宽度
      TH0=0;         //定时器清0
      TL0=0;         //定时器清0
      TR0=1;         //开启定时器T0
      while(p_ir){HighTime=TH0*256+TL0;
    if(HighTime>10000){TR0=0;EX1=1;EX0=1;return;}
    }  //如果是高电平就等待
      TR0=0;        //关闭定时器T0
      HighTime=TH0*256+TL0;   //保存高电平宽度

//脉冲个数与频率有关 11.0592M 1ms~922个脉冲,12M 1ms=1000个脉冲,22.1184M 1ms ~1843个脉冲,30M ~2500个脉冲
//UPD6121 引导码 发射(低电平)9ms(前面延时1ms,为8ms),不发射(高电平)4.5ms
if((LowTime>13000)&&(LowTime<16600)&&(HighTime>6450)&&(HighTime<10000))
   { // led_1=1;
    if(DeCode()==1)irsuccess=1;
   }
p_ir=1;
EX1=1;
EX0=1;
  }
#endif
 楼主| 发表于 2015-6-1 21:47 | 显示全部楼层
多谢 xrff_z 兄弟,我现在还只会改改字体,改下端口定义,其它的就不懂啦,万年历 晶振是11.0592
发表于 2015-6-1 23:07 | 显示全部楼层
楼上很认真,我很惭愧,附上一个珍藏的红外解码库,此处应向原作者致敬。
此库需占用定时器0。
使用方法:改后缀为.h,包含到main中。
修改文件中的红外引脚和晶振频率。
先调用初始化函数。
主循环中检查IR_BT标志,若为1,则解码成功,数据在数组NEC[]内。

IR.txt (4.47 KB, 下载次数: 44)



发表于 2015-6-2 08:32 | 显示全部楼层
epwdh 发表于 2015-6-1 21:47
多谢 xrff_z 兄弟,我现在还只会改改字体,改下端口定义,其它的就不懂啦,万年历 晶振是11.05 ...

不用谢,互相帮助。

还有一点,不同的单片机,执行速度是不一样的,这也会导致延时函数的时间不一样。
用定时器计时的话,会好一点。可以用楼上兄弟提供的标准库试试,改下端口,频率就行了
发表于 2015-6-2 09:17 | 显示全部楼层
有完整的源程序吗,给发个,这个界面我喜欢,尤其是时钟的字体!~
发表于 2015-6-3 22:53 | 显示全部楼层
我用的和楼主一样的解码程序,我的是点阵屏的,可遥控时干扰显示程序,不知怎么回事。有知道怎么回事的吗?
发表于 2015-6-3 23:32 | 显示全部楼层
山东人 发表于 2015-6-3 22:53
我用的和楼主一样的解码程序,我的是点阵屏的,可遥控时干扰显示程序,不知怎么回事。有知道怎么回事的吗?

软件延时的原因,点阵屏是靠单片机扫描,LCD自己扫描。

本版积分规则

QQ|一淘宝店|手机版|商店|电子DIY套件|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2024-4-28 00:15 , Processed in 0.072319 second(s), 45 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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