原创 PIC16F887红外解码程序

2009-8-12 11:06 3934 5 6 分类: MCU/ 嵌入式

//----------------------------------------------------------------
//PIC16F887 红外解码程序
//指令周期1us,
#include <htc.h>                // header file with compiler macros, for
                                // example __CONFIG
                                // the processor header file, with register
                                // and bit definitions (pic16f887.h) is
                                // automatically included
#define uchar unsigned char
#define uint unsigned int
// __CONFIG sets the PIC16F887 Configuration Words.  See bottom of the header
// file pic16f887.h for fuse option constants.
    __CONFIG(INTCLK & WDTDIS & PWRTDIS & MCLRDIS & UNPROTECT & DUNPROTECT & BORDIS & IESODIS & FCMDIS & LVPDIS);
    __CONFIG(BORV40); // 2nd config word
////// ///////////////////////////////////////////////////////////////////////////
uint shuju[3]={0};   //存放数据
uint temp="0";     //临时变量
uchar i,j;     //数组及移位计数用
uchar biaozhi="0";   //起始码标志位
uchar flag="1";    //有键按下,打开定时器
void init_io(void)   //初始化函数
{
    TRISC = 0xFF;   //置CCP1口为输入态
    TRISD = 0x00;   //置D口为输出态
 CCP1CON=0x04;   //CCP1模块工作于捕捉方式
 CCP1IE=1;    //开中断
 CCP1IF=0;    //清捕捉标志位
 PEIE=1;     //开外部中断


 T1CON=0;    //配置定时器T1不分频,使用内部时钟,且先禁止T1
    ei();                   // enable global interrupts
 TMR1H=0;    //计数值清0
 TMR1L=0;
 PORTD=0;    //输出清0
}
main()
{
init_io();     //初始化函数
while(1);     //等待CCP1模块中断产生
}


void interrupt interrupt_service(void)  //中断
{
    if (CCP1IE && CCP1IF)     //判断是否为CCP1模块中断,当在一个系统中时会用
        {
  if(flag==1)         
   {
   TMR1H=0;
   TMR1L=0;
   TMR1ON=1;      //开定时器
   flag=0;
   }
  else
   {
   TMR1ON=0;       //先停定时器
   temp=TMR1L+TMR1H*256;   //取数据并判断
   TMR1H=0;      //清0计数值
   TMR1L=0;
   TMR1ON=1;      //开定时器等待下一个脉冲到来
    if(temp>12600&&temp<14600&&biaozhi==0)     //起始码
     {
     biaozhi=1;          //当检测到起始码时,下次直接进行入数据判断
     i=0;
     j=0;
     }
    else         //数据判断区
     {
     if((temp < 3200)&&(temp > 1200)) //时间在2.2ms左右的为数码0
      {shuju=shuju<<1;j++;}
     else
      if((temp < 5000)&&(temp > 3000)) //时间在4ms左右的为为数码1
       {shuju=(shuju<<1)+1;j++;}
      else
       biaozhi=0;      //否则为终止码,清0起始码标志位,准备下一次按键的接收
     }
    if(j==16&&i<2)      //数组递加,当第一个数组接收满后,开始对下一个数组进行接收
     {i++;j=0;}
    else
     {
     if(j==16&&i==2)     //当接收满后(共48位),对数据输出
      {
      if(shuju[0]==0xeb14)  //为对应的某一按键值
      PORTD=0x10;     //相应端口输出
      if(shuju[0]==0xee11)  //另一键值
      PORTD=0xa0;     //输出
      biaozhi=0;     //接收完成,复位相应标志位
      flag=1;
      i=0;
      j=0;
      }
     
     }
   }    
         TMR1IF = 0;             // clear Timer0 interrupt flag
   CCP1IF=0;        //每次必须对CCP1IF位软件清0
  }
}





用单片机解码红外遥控器<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


遥控器使用方便,功能多.目前已广泛应用在电视机、VCDDVD、空调等各种家用电器中,且价格便宜,市场上非常容易买到。如果能将遥控器上许多的按键解码出来.用作单片机系统的输入.则解决了常规矩阵键盘线路板过大、布线复杂、占用IO口过多的弊病。而且通过使用遥控器,操作时可实现人与设备的分离,从而更加方便使用。谈谈如何用常用的51系统单片机进行遥控的解码。


一、编码格式


101的编码


遥控器发射的信号由一串O1的二进制代码组成.不同的芯片对01的编码有所不同。通常有曼彻斯特编码和脉冲宽度编码。TC9012-p.htm" target="_blank" title="TC9012货源和PDF资料">TC9012O1采用PWM方法编码,即脉冲宽度调制,其O码和1码如图1所示(以遥控接收输出的波形为例)O码由O56ms低电平和056ms高电平组合而成.脉冲宽度为112ms1码由056ms低电平和169ms高电平组合而成.脉冲宽度为225ms。在编写解码程序时.通过判断脉冲的宽度,即可得到01


2、按键的编码


当我们按下遥控器的按键时,遥控器将发出如图2的一串二进制代码,我们称它为一帧数据。根据各部分的功能。可将它们分为5部分,分别为引导码、地址码、地址码、数据码、数据反码。遥控器发射代码时.均是低位在前。高位在后。由图2分析可以得到.引导码高电平为45ms,低电平为45ms。当


接收到此码时.表示一帧数据的开始。单片机可以准备接收下面的数据。地址码由8位二进制组成,共256种.图中地址码重发了一次。主要是加强遥控器的可靠性.如果两次地址码不相同.则说明本帧数据有错.应丢弃。不同的设备可以拥有不同的地址码.因此。同种编码的遥控器只要设置地址码不同,也不会相互干扰。图中的地址码为十六进制的0EH(注意低位在前)。在同一个遥控器中.所有按键发出的地址码都是相同的。数据码为8位,可编码256种状态,代表实际所按下的键。数据反码是数据码的各位求反,通过比较数据码与数据反码.可判断接收到的数据是否正确。如果数据码与数据反码之间的关系不满足相反的关系.则本次遥控接收有误.数据应丢弃。在同一个遥控器上.所有按键的数据码均不相同。在图2中,数据码为十六进制的0CH,数据反码为十六进制的0F3H(注意低位在前).两者之和应为0FFH


二、单片机遥控接收电路


红外遥控接收可采用较早的红外接收二极管加专用的红外处理电路的方法。如CXA20106,此种方法电路复杂,现在一般不采用。较好的接收方法是用一体化红外接收头,它将红外接收二极管、放大、解调、整形等电路做在一起,只有三个引脚.分别是+5V电源、地、信号输出。常用的一体化接收头的外形及引脚见图3和图4。红外接收头的信号输


出接单片机的INTOINTl脚.典型电路如图5所示.图中增加了一只PNP型三极管对输出信号进行放大。


三、遥控信号的解码算法及程序编制


平时。遥控器无键按下。红外发射二极管不发出信号,遥控接收头输出信号1。有键按下时.O1编码的高电平经遥控头倒相后会输出信号O.由于与单片机的中断脚相连,将会引起单片机中断(单片机预先设定为下降沿产生中断)。单片机在中断时使用定时器0或定时器1开始计时.到下一个脉冲到来时,即再次产生中断时,先将计时值取出。清零计时值后再开始计时.通过判断每次中断与上一次中断之间的时间间隔。便可知接收到的是引导码还是 O1。如果计时值为9ms。接收到的是引导码,如果计时值等于112ms,接收到的是编码O。如果计时值等于2 25ms.接收到的是编码1。在判断时间时,应考虑一定的误差值。因为不同的遥控器由于晶振参数等原因,发射及接收到的时间也会有很小的误差。


以接收TC9012-p.htm" target="_blank" title="TC9012货源和PDF资料">TC9012遥控器编码为例,解码方法如下:


(1)设外部中断0(或者1)为下降沿中断,定时器0(或者1)16位计时器.初始值均为O


(2)第一次进入遥控中断后,开始计时。


(3)从第二次进入遥控中断起,先停止计时。并将计时值保存后,再重新计时。如果计时值等于前导码的时间,设立前导码标志。准备接收下面的一帧遥控数据,如果计时值不等于前导码的时间,但前面已接收到前导码,则判断是遥控数据的O还是1


(4)继续接收下面的地址码、数据码、数据反码。


(5)当接收到32位数据时,说明一帧数据接收完毕。此时可停止定时器的计时,并判断本次接收是否有效.如果两次地址码相同且等于本系统的地址,数据码与数据反码之和等于0FFH,则接收的本帧数据码有效。否则丢弃本次接收到的数据。


(6)接收完毕,初始化本次接收的数据,准备下一次遥控接收。



四、遥控代码与键盘码的转换


在应用系统中,带遥控器的仪器设备一般都带按键。而且二者功能相同。将遥控键值转换成标准的按键值后。遥控按键散转表格可以与键盘散转表格复用。转换方法可用查表法。通过查表。使遥控的按键值转换成本机键盘的值。这样既可以使用按键操作,也可以使用遥控操作,而且相应的处理程序非常简单。


以上以Tc9012编码格式为例,说明了解码的原理与方法。只要注意一帧数据的格式及引导码、O码和1码的时间长度.其它编码芯片如 HT6121M50560LC7461等也非常容易解码。


 


注:本程序使用的是TOYO空调的遥控器,起始码为13.6ms,0码为2.2ms,1码为4ms,停止码为9ms.共48位数据,单片机的指令周期为1us,这个程序还没有加校验. 


图片传不上去.


 



 


 


 

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1402089 2009-8-12 13:54

把上面程序中的 uint shuju[3]={0};修改为uchar shuju[6]={0}; if(j==16&&i<2)修改为if(j==8&&i<5) if(j==16&&i==2)修改为if(j==8&&i==5) if(shuju[0]==0xeb14)修改为if(shuju[0]==0xeb&&shuju[1]==14) if(shuju[0]==0xee11)修改为if(shuju[0]==0xee&&shuju[1]==11) 后,即用8位数组来接收数据 则程序接收不到内容,数组内容全为0. 高手请帮忙.谢谢了! QQ:286416912
相关推荐阅读
用户1402089 2011-08-23 20:46
关于70箱的弱磁调速知识点
1 弱磁调速原理<?XML:NAMESPACE PREFIX = O />      由它励直流电动机的机械特性方程式可知:        n=U/(CeΦ)-RT/(CeΦ<?X...
用户1402089 2011-08-23 20:37
PIC 汇编控制字格式
#include <p16F887.inc>    __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF &...
用户1402089 2011-03-25 21:48
变频器与传动,电路知识
变频器使用中的一些常见问题                                             --------采用问答方式 1。问:1台变频器带多台电机时,怎么选定变频器容量?...
用户1402089 2010-12-08 17:04
买房五步:明确买房目的了解楼市状况
买房第一步:明确购房目的  1.买房的资金准备———您准备用多少钱买房?4 ~5 h2 p2 y+ h% g! r  购楼者(潜在业主)在购楼前需要无数遍地问自己两个问题:为什么要买房?到底需要什么样...
用户1402089 2010-11-23 18:11
三极管型号对应标识
SMD(SOT-23封装)三极管表示方法* \5 `; ~8 F: j% ?, ?) _. O8 Q4 _三极管型号标识方法  BC846A 1A1 n- z+ u8 t' t# K' c! YMMB...
用户1402089 2010-11-06 18:00
VB窗体最小化到托盘
可以用API来实现,不过还是采用微软封装好的控件来实现比较方便,不过改控件并不在VB安装目录中,需要找到VB的安装盘的COMMON\TOOLS\VB\UNSUPPRT\SYSTRAY目录,将Systr...
EE直播间
更多
我要评论
1
5
关闭 站长推荐上一条 /3 下一条