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