元器件交易网-中发网全新升级平台
关注我们:
首页 > 解决方案 > 正文

单片机红外解码实例

  一般常用的红外遥控器编码规则都差不多,基本上都同6221原理一样

  PIC单片机接收时:

  如果用54,57这类片子做的话有一定的难度(假如要做成实时控制的;比如说你还要驱动显示,驱动步进电机,在加上几个按键)原因就是这类片子没有中断

  例程如下(用来解6221;分频比为256)

  RF:

  BTFSC PORTB,2;;B2口用做接收口

  GOTO RF1

  BTFSS DOWNBIT;;检测下降沿标制

  CLRF RTCCOUNT

  BSF DOWNBIT;制下降沿标制

  BTFSS UPBIT;;检测上升沿标制

  RETLW 0

  BTFSC IDBIT;;检测码头标制

  GOTO RF3

  MOVLW 2AH

  SUBWF RTCCOUNT,0

  BTFSS ler_541.do" target="_blank">STATUS,0

  GOTO RF2

  MOVLW 36H

  SUBWF RTCCOUNT,0

  BTFSC STATUS,0

  GOTO RF2

  BTFSC IDBIT

  GOTO RF3

  MOVLW .8

  MOVWF LOOP

  MOVLW .3

  MOVWF LOOPCOUNT

  CLRF DATACOUNT

  BSF IDBIT

  BSF DOWNBIT

  BCF UPBIT

  CLRF RTCCOUNT

  RETLW 0

  RF1:

  BTFSS DOWNBIT

  RETLW 0

  BSF UPBIT

  RETLW 0

  RF2:

  BCF DOWNBIT

  BCF UPBIT

  BCF IDBIT

  CLRF RTCCOUNT

  RETLW 0 ;遥控接收

  RF3:

  MOVLW 02H

  SUBWF RTCCOUNT,0

  BTFSS STATUS,0

  GOTO RF4

  MOVLW 0CH

  SUBWF RTCCOUNT,0

  BTFSS STATUS,0

  GOTO RF4

  GOTO RF2

  RF4:

  MOVLW 08H

  SUBWF RTCCOUNT,0

  BTFSC STATUS,0

  BSF 3H,0

  MOVLW 07H

  SUBWF RTCCOUNT,0

  BTFSS STATUS,0

  BCF 3H,0

  RLF DATACOUNT,1

  BSF DOWNBIT

  BCF UPBIT

  CLRF RTCCOUNT

  DECFSZ LOOP,1

  RETLW 0

  MOVLW .8

  MOVWF LOOP

  DECFSZ LOOPCOUNT

  RETLW 0

  BSF RFBIT;;制接收完标制

  BCF DOWNBIT

  BCF UPBIT

  BCF IDBIT

  CLRF RTCCOUNT

  RETLW 0

  //////////////////////////////////////////////////////////

  TIME:

  BTFSC TIMEPD1

  GOTO TIME1

  MOVF RTCC,0;;(

  MOVWF TIMEONE

  BSF TIMEPD1

  RETLW 0 ;定时查寻

  TIME1:

  MOVF RTCC,0

  SUBWF TIMEONE,0

  BTFSC STATUS,2

  RETLW 0

  BCF TIMEPD1

  INCF RTCCOUNT,1

  RETLW 0

  ////////////////////////////////////////////////

 

  在这里我是用查询的方式来定时的(RTCCOUNT)只是在解码时不需要去追求时间精度;我是去查RTCC有没有发生跳变如有则表示时间过了 256US---RTCCOUNT加一;这样做有一个好处---你不必去管RTCC具体的值是多少,(RTCC去做精确的时钟定时;在这个查询的子程序中你可以去判断键扫,显示刷新,驱动步进电机等等)

  相应的C代码如下:

  unsigned char rfcount,

  loop,

  rftime,//查询定时器

  k;

  bit rfbit, //接收完标制

  lowbit1,

  lowbit2,

  downbit,

  rfgobit;

  unsigned char dispcount[5];//结果

  #define rfin RC6

  ////////////////////////////////////////////////////////////////////////////////

  rf( )//遥控接收

  {

  if(rfbit==0)

  {

  if((lowbit1==0)&&(rfin==0))

  {

  downbit=1;

  rftime=0;

  lowbit1=1;

  return;

  }

  if((lowbit1==1)&&(rfin==1))

  {

  lowbit2=1;

  return;

  }

  if((lowbit1==1)&&(lowbit2==1)&&(RC6==0))

  {

  lowbit1=0;

  lowbit2=0;

  if((rftime>=40)&&(downbit==1))//遥控接收;

  {

  rfgobit=1;

  loop=0;

  rfcount=0;

  k=1;

  rftime=0;

  return;

  }

  rfcount=rfcount+1;

  loop=loop+1;

  if(rfcount>=31)

  {

  rfgobit=0;

  downbit=0;

  rfcount=0;

  rfbit=1;

  loop=0;

  return;

  }

  if((rftime>=7)&&(rfgobit==1))

  {

  dispcount[k]=dispcount[k]|0x80;

  rftime=0;

  if(loop==8)

  {

  k=k+1;

  loop=0;

  return;

  }

  dispcount[k]=dispcount[k]》1;

  return;

  }

  if((rftime<5)&&(rfgobit==1))

  {

  dispcount[k]=dispcount[k]&0x7f;

  rftime=0;

  if(loop==8)

  {

  k=k+1;

  loop=0;

  return;

  }

  dispcount[k]=dispcount[k]》1;

  return;

  }

  }

  }

  }

  (查询子程序同汇编)

  假如用中断的话也可用时间查询的方法,只是接收口改用带中断的口线;RB4--RB7,CCP1,CCP2,都可以。建议不要用RB0(他当按键输入最好用);

  还有就是解码时的容陷和误码处理(有一种写法是在解码移位时利用进位标制C同时移位;我个人认为不太好,因为只要差一位没接收到,整个接收到的都是误码且浪费时间)

  2 再谈PIC单片机发送

  原理是接收的逆过程

  例程如下(用来发6221;分频比为256)

 

  ;///////////////////////////////////////////////////////////////////////////////////////////////

  READDIGT:

  MOVF SENDLOOP,0

  ADDWF PC,1

  GOTO SENDC4

  GOTO SENDC3

  GOTO SENDC2

  GOTO SENDC1

  GOTO SENDC0

  ;///////////////////////////////////

  SENDC0:

  MOVF C4COUNT,0;;读要发的数据(假设要发5个字)

  RETURN

  SENDC1:

  MOVF C3COUNT,0

  RETURN

  SENDC2:

  MOVF C2COUNT,0

  RETURN

  SENDC3:

  MOVF C1COUNT,0

  RETURN

  SENDC4:

  MOVF C0COUNT,0

  RETURN

  ;///////////////////////////////////

  SENDBIT:

  CLRF TIME

  BCF PORTB,1

  SENDBIT1:

  CLRWDT

  MOVLW .35

  SUBWF TIME,0

  BTFSS STATUS,2

  GOTO SENDBIT1

  CLRF TIME

  BSF PORTB,1

  SENDBIT2:

  CLRWDT

  MOVLW .18

  SUBWF TIME,0

  BTFSS STATUS,2

  GOTO SENDBIT2

  CLRF SENDLOOP ;码头数据发送

  //////////////////////////////////////////////

  SENDBIT3:

  CLRWDT

  BCF INTCON,7

  CALL READDIGT

  MOVWF SENDCOUNT

  BSF INTCON,7

  CALL SENDDIGT

  INCF SENDLOOP,1

  MOVLW .5

  SUBWF SENDLOOP,0

  BTFSS STATUS,2

  GOTO SENDBIT3

  CLRF TIME

  BCF PORTB,1

  SENDDIGT5:

  CLRWDT

  MOVLW .2;;加发一个结束位

  SUBWF TIME,0

  BTFSS STATUS,2

  GOTO SENDDIGT5

  BSF PORTB,1

  BSF STARTBIT

  RETURN

  ;/////////////////////////////////////////////////////////////////////////////////////////

  SENDDIGT:;;实现0和1的发送

  MOVLW .8

  MOVWF LOOPSENDCOUNT

  SENDDIGTGO:

  BTFSS SENDCOUNT,7

  GOTO ZERSEND

  CLRF TIME

  SENDDIGT1:

  CLRWDT

  BCF PORTB,1

  MOVLW .2

  SUBWF TIME,0

  BTFSS STATUS,2

  GOTO SENDDIGT1

  CLRF TIME

  SENDDIGT2:

  CLRWDT

  BSF PORTB,1

  MOVLW .6

  SUBWF TIME,0

  BTFSS STATUS,2

  GOTO SENDDIGT2

  GOTO SENDOVER

  ZERSEND:

  CLRF TIME

  SENDDIGT3:

  CLRWDT

  BCF PORTB,1

  MOVLW .2

  SUBWF TIME,0

  BTFSS STATUS,2

  GOTO SENDDIGT3

  CLRF TIME

  SENDDIGT4:

  CLRWDT

  BSF PORTB,1

  MOVLW .2

  SUBWF TIME,0

  BTFSS STATUS,2

  GOTO SENDDIGT4

  SENDOVER:

  RLF SENDCOUNT,1

  DECFSZ LOOPSENDCOUNT

  GOTO SENDDIGTGO

  RETURN

  相应的C代码如下:(C5口是发送口)

  #include

  #include

  #include

  unsigned char dispcount[5];//要发送的码值

  unsigned char i,k,data,rfbit,zbit,rfgobit;

  #pragma interrupt_level 1

  interrupt adint(void)

  {

  if(TMR1IF==1)

  {

  TMR1IF=0;

  TMR1H=0b11111100;

  TMR1L=0b00010111;

  rfbit=rfbit+1;//发送指针加一

  send( );

  }

  }

  //////////////////////////////////////////

  send( )

  {

  if(rfgobit==0)

  {

  switch(rfbit)

  {

  case 1 :

  RC5=0;

  break;

  case 6 :

  RC5=1;

  break;

  case 7 :

  RC5=0;

  rfgobit=1;//制发送完标制

  rfbit=0;

  break;

  default :

  break;

  }

  }

  if(rfgobit==1)

  {

  zbit=dispcount[i]&0b00000001;

  switch(rfbit)

  {

  case 1:

  RC5=1;

  break;

  case 2 :

  if(zbit==0)

  {

  RC5=0;

  rfbit=0;

  rf( );

  }

  break;

  case 3 :

  if(zbit==1)

  {

  RC5=0;

  rfbit=0;

  rf( );

  }

  break;

  default :

  break;

  }

  }

  }

  //////////////////////////////////////////////

  rf( )

  {

  k=k+1;

  if(k==8)

  {

  i=i+1;

  k=0;

  if(i==6)

  {

  i=1;

  rfgobit=0;

  TMR1H=0;

  TMR1L=0;

  RC5=1;

  dispcount[1]=0xaa;

  dispcount[2]=0xbb;

  dispcount[3]=0xcc;

  dispcount[4]=0xdd;

  dispcount[5]=0xee;

  }

  return;

  }

  dispcount[i]=dispcount[i]》1;

  }

  //////////////////////////////////////

  main( )

  {

  di( );

  TRISC=0b11011111;

  TRISA=0b111111;

  TRISB=0b11111111;

  i=1;

  k=0;

  TMR1H=0b11111100;

  TMR1L=0b00010111;

  T1CON=1;

  TMR1IE=1;

  RC5=1;

  PEIE=1;

  ei( );

  dispcount[1]=0xaa;

  dispcount[2]=0xbb;

  dispcount[3]=0xcc;

  dispcount[4]=0xdd;

  dispcount[5]=0xee;

  while( 1 )

  {

  ;

  }

  }

  这两个程序只是一个演示例程

  在实际运用中可变通的把这种发送与接受用于两机之间的通讯(好处是移植性好,抗干扰好且一发一收只要两根线或一根线)另外如要产生载波(38KHZ)的话可用其输出口去调制38KHZ发生源(比如555电路,PWM)来得到,或干脆用软件来实现(不过难度较大;不如用带38KHZ的单片机来做)

扫描左侧的二维码

科技圈最新动态一手掌握
每日砸蛋,中奖率100%