---
---
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数と内容合成
}