PIC单片机红外遥控编码与解码的问题
2012-06-02
标签:

一般常用的红外遥控器编码规则都差不多,基本上都同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 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的单片机来做)

可能会用到的工具/仪表
相关文章
推荐文章
热门文章
章节目录
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号