Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1927405
  • 博文数量: 187
  • 博客积分: 1457
  • 博客等级: 上尉
  • 技术积分: 2422
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-13 09:41
个人简介

如需要绘制PCB,设计电路可以和我联系。sunhenu@163.com.

文章分类

全部博文(187)

文章存档

2017年(2)

2016年(2)

2015年(7)

2014年(13)

2013年(80)

2012年(83)

分类: LINUX

2012-12-20 12:06:09

力天电子开发板,上面存在一个TL1838红外接收头,我们可以利用它做一些遥控器之类的,关于TL1838的资料,可以在网络上收集到,我不多说了,具体原理也同样,文章最后我留一个网友博客链接自己参考。
下面看程序,在力天开发板上,TL1838接在PD6上,PD6有ICP功能,就是输入捕捉功能,具体你可以看AVR的datasheet,我的开发环境为IAR5.11B,晶振16M,
先看第一种方法:
void TL1838_init()                                               //初始化函数
 DDRD_Bit6=0;                                                   //设置ICP1引脚为输入
 PORTD_Bit6=1;                                                  //使能ICP1引脚上拉电阻 
 TCNT1=0x00;                                                    //初值为0
 TIMSK_TICIE1=1;                                                //输入捕抓中断使能; 
 TCCR1B=(1<//下降沿触发,8分频,0.5us. 
 __enable_interrupt();
}
#pragma vector = TIMER1_CAPT_vect
/*这里我解释一下,输入捕捉产生中断的时候,就TCNT1寄存器的值赋值到ICR1中这样我们就可以获得2个下降沿见的时间间隔,由于,我TCNT1清零了,所以,每次在中断函数中读取的ICR1就是2个下降沿见的时间间隔,我们就直接可以进行判断了。在进入中断函数的时候,中断标志自动清零,软件不需要清零。*/
__interrupt void TIMER1_CAPT(void) 
 TCNT1=0x00; 
 ICP_CurrentValue=ICR1;                                      //读取ICP输入捕捉事件的发生时刻
 if(ICP_CurrentValue>1900&&ICP_CurrentValue<2450)
   Inter_Time=0;
  else if(ICP_CurrentValue>4100&&ICP_CurrentValue<4690)
   Inter_Time=1; 
  else if(ICP_CurrentValue>26650&&ICP_CurrentValue<27200)    //判断前导码
       {
          TL1838_Address=0;
          TL1838_KeyData=0;
          count=0;
          return;
       }
  else {return;} 
  count++;
  if(count<16)
  {
    TL1838_Address=TL1838_Address|Inter_Time;
    TL1838_Address=TL1838_Address<<1;
  }
  else if(count==16)
    TL1838_Address=TL1838_Address|Inter_Time;
  else if(count<32)
  {
    TL1838_KeyData=TL1838_KeyData|Inter_Time;
    TL1838_KeyData=TL1838_KeyData<<1;
  }
  else if(count==32)
  {
    TL1838_KeyData=TL1838_KeyData|Inter_Time; 
    Uart_Transmit(0x11); 
    Uart_Transmit(TL1838_KeyData&0x00ff); //接收完32位后通过串口发送键值
    Uart_Transmit(TL1838_KeyData>>8);
  }    
  
}

接下来看第二种方法:
第二种方法,我是参考网友的,主要的区别是在ICR1的值。
void TL1838_init()                                               //初始化函数
 DDRD_Bit6=0;                                                   //设置ICP1引脚为输入
 PORTD_Bit6=1;                                                  //使能ICP1引脚上拉电阻 
 TCNT1=0x00;                                                    //初值为0
 TIMSK_TICIE1=1;                                                //输入捕抓中断使能; 
 TCCR1B=(1<
 __enable_interrupt();
}
#pragma vector = TIMER1_CAPT_vect
/*主要的区别是,
中断产生以后没有清零TCNT1,下次捕捉中断读取的ICR1值是在前一次中断ICR1的基础上累积的值,所以TCNT1肯定会计数到OXFFFF,然后从0开始计数,这样就会发生ICP_LastValue大于ICP_CurrentValue的情况,所以,我要先给ICP_CurrentValue加上一个0xFFFF+1,然后再减去ICP_LastValue。所以我在这里说明一下,网友是按照这个思路来写程序的。*/
__interrupt void TIMER1_CAPT(void) 
  ICP_CurrentValue=ICR1;                                      //读取ICP输入捕捉事件的发生时刻
 
 if(ICP_LastValue>ICP_CurrentValue)
       Inter_Time=0xffff+ICP_CurrentValue+1-(ICP_LastValue);  //计算两个下降沿之间用去的时间
    else 
   Inter_Time=ICP_CurrentValue-ICP_LastValue;
 //TIFR|=BIT(ICF1);                                  //该语句可要可不要,因为中断执行                                                              //时ICF1自动清0,也可用该语句来实现软件清0
 ICP_LastValue=ICP_CurrentValue;
 if(Inter_Time>1900&&Inter_Time<2450)
   Inter_Time=0;
  else if(Inter_Time>4100&&Inter_Time<4690)
        Inter_Time=1; 
  else if(Inter_Time>26650&&Inter_Time<27200)//判断前导码
       {
          TL1838_Address=0;
          TL1838_KeyData=0;
          count=0;
          return;
       }
  else {return;}                            
//去除干扰,当接收的是准备进前导码时的下降沿和截止码时,
//该语句起作用,没有该语句,则只能接收一次 
  count++;
  if(count<16)
  {
    TL1838_Address=TL1838_Address|Inter_Time;
    TL1838_Address=TL1838_Address<<1;
  }
  else if(count==16)
    TL1838_Address=TL1838_Address|Inter_Time;
  else if(count<32)
  {
    TL1838_KeyData=TL1838_KeyData|Inter_Time;
    TL1838_KeyData=TL1838_KeyData<<1;
  }
  else if(count==32)
  {
    TL1838_KeyData=TL1838_KeyData|Inter_Time; 
    Uart_Transmit(0x11); 
    Uart_Transmit(TL1838_KeyData&0x00ff);
    Uart_Transmit(TL1838_KeyData>>8); //接收完32位后发送键值到串口
  } 
   
  
}

程序烧写到AVR里面,需要一个红外遥控器,然后就可以利用串口调试助手接收键值了,
我没有遥控器,所以我就利用了一下,正点原子STM32开发板上配带的红外遥控器了,因为频率是38KHZ,所以也可以使用TL1838来接收。下面看图片,左边是我从串口手抄下来的键值,和右边的遥控器一一对应。
上面的图片,第一个数据5D2A,应该是5DA2,我抄错了,下图片是我重新读取的,同是也读取了用户识别码,为Ox00FF.

网友的博客链接,可以参考一下。
http://liziqiang261.blog.163.com/blog/static/1506444902011215113933154/
http://www.ichanging.org/infra-red-decode.html
http://www.ourmpu.com/mcujx/hwyk11.htm

阅读(3875) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~