---
---
18F14K50のBootLoader基本ボードを使い、赤外線リモコンの受信機を作成しました。
基本ボードのコネクタにに赤外線リモコン受光モジュールを接続すれば、テレビリモコンのチャンネル「1」を押せば、端のLEDが。 テレビリモコンのチャンネル「2」を押せば、隣のLED点灯し、「1」-「4」までのリモコンボタンに4つのLEDが対応して点灯します。
赤外線リモコンが大量生産されるようになったため、高機能な赤外線リモコン受光モジュールも安価で入手できるようになりました。今回使用したPL-IRM2161-C438には、赤外線を受けるフォトダイオード、アンプ、フィルター、検波回路などが6mm角の小さな樹脂容器に納められています。使い方は簡単です。モジュールに+5V電源を接続すれば、赤外線入力に対応したロジック出力が得られます。ただし、基板のコネクタPIN配列とモジュールのPIN配列が異なるためモジュールの足を多少無理してコネクター配列に合わせ挿入しています。
main.c
//*************************************************************** // PIC18F14K50 // 赤外線リモコンを受信しLEDに表示 // 1)Define I/O PORT // PORTA(3)pin 4 : PushSW // PORTC(0)pin16 : LED // PORTC(1)pin15 : LED // PORTC(2)pin14 : LED // PORTC(3)pin 7 : LED // PORTC(4)pin 6 : Ir入力 // 2)OSC // 48MHz (12MHz Xtal) //***************************************************************/ #include <p18f14k50.h> #include <delays.h> #include <timers.h> #define ctmCode 0x0055 // 赤外線カスタマーコード(現在は無効) #define L_ON_Min 234 // 5msec リーダーの最小継続時間 #define DataTH 47 // 1msec データの「1」「0」境界時間 #define D_Off_Max 94 // 2msec データ「0」の最大継続時間 #define IrIN PORTCbits.RC4 #define T0IF INTCONbits.TMR0IF #define LED1 LATCbits.LATC0 #define LED2 LATCbits.LATC1 #define LED3 LATCbits.LATC2 #define LED4 LATCbits.LATC3 //------------ リセット ベクトルの移動----------------------- #define REMAPPED_RESET_VECTOR_ADDRESS 0x1000 extern void _startup (void); #pragma code reset_vect = REMAPPED_RESET_VECTOR_ADDRESS void _reset (void){_asm goto _startup _endasm} //------------------------------------------------------------ // ----- 関数プロトタイピング ----- int irRcv(void); #pragma code //****** メイン ************************ void main(void){ int rcvData; unsigned char cmd,n_cmd; PORTA = 0x00; PORTB = 0x00; PORTC = 0x00; TRISA = 0b11111111; //PortA すべて入力 TRISB = 0b11111111; //PortB すべて入力 TRISC = 0b11110000; //PortC 0-3出力 ANSEL = 0b00000000; //すべてデジタル ANSELH = 0b00000000; OpenTimer0( // Timer0を初期化 TIMER_INT_OFF & T0_8BIT & T0_SOURCE_INT & T0_PS_1_256 ); // --- 以下は受信の繰り返し --- while(1){ // ------- Start Bit (リーダー)の確認 --------------- //OnおよびOFFの時間を確認しノイズか有効データか判断する // ----------------------------------------- while(1){ while(IrIN); // 信号 待ち TMR0L = 0; // -- リーダーのON 時間測定 T0IF = 0; // while(!IrIN); // IrOFF 待ち if((TMR0L < L_ON_Min) // リーダーの最小継続時間以下 && !T0IF)continue; // ならノイズなので戻る TMR0L = 0; // -- リーダーのOFF時間測定 T0IF = 0; // while(IrIN && !T0IF); // IrON 待ち if(!T0IF) break; // 5.5mS以下ならOK(受信開始) } // ------- カスタムコードの確認 ------------------- // 受信が16ビット未満、または、カスタムコードが異なれば 再受信 // ----------------------------------------- rcvData=irRcv(); //8ビット受信 if((rcvData & 0xFF00) != 0x0800)continue; //受信ビット数確認 // if((rcvData & 0x00FF) != ctmCode>>8)continue; //カスタマコード確認 rcvData=irRcv(); if((rcvData & 0xFF00) != 0x0800)continue; // if((rcvData & 0x00FF) != ctmCode & 0xFF)continue; // ------- コマンドコードの確認 -------------------- // コマンドおよび反転コマンドを受信して比較異なれば 再受信 // ----------------------------------------- rcvData=irRcv(); if((rcvData & 0xFF00) != 0x0800)continue; cmd = rcvData & 0x00FF; rcvData=irRcv(); if((rcvData & 0xFF00) != 0x0800)continue; n_cmd = rcvData & 0x00FF; if(cmd != ~n_cmd)continue; // ---- 受信コマンドの処理 ------------------- switch (cmd){ case 1: // コマンドが「1」ならLED1を点灯 LED1 = 1;LED2 = 0; LED3 = 0; LED4 = 0; break; case 2: LED1 = 0; LED2 = 1; LED3 = 0; LED4 = 0; break; case 3: LED1 = 0; LED2 = 0; LED3 = 1; LED4 = 0; break; case 4: LED1 = 0; LED2 = 0; LED3 = 0; LED4 = 1; break; default: LED1 = 0; LED2 = 0; LED3 = 0; LED4 = 0; break; } } } //****** 1Byteを受信する ******************************* // 8ビット受信する。 // 受信したビット数を上位8ビット // 受信データを 下位8ビットに組み合わせて 戻る // 「1「0」判定は「0」の時間を DataTH と比較する //****************************************************** int irRcv(void){ unsigned char i,period,data; data = 0; for(i = 0; i < 8; i++){ data >>= 1; // 1ビットずつ8回繰り返す while(!IrIN); // IrOFF 待ち TMR0L = 0; // -- BitのOFF時間測定 T0IF = 0; // while(IrIN && TMR0L < D_Off_Max); // IrON 待ち period = TMR0L; // 時間取得 if(period > DataTH) // 「1「0」判定 data += 0x80; // 「1」を立てる if(period>= D_Off_Max) break; // 2mS以上ならStop } return (int)i * 256 + data; // 受信Bit数と内容合成 }