使用PIC:PIC16F88
赤外線リモコン受信モジュール:PL-IRM-2161-C438(秋月電子通商で購入)
使用リモコン:NECのテレビリモコン
参考サイト
PICとMikroCのTVリモコン信号の受信機 のコーナーは非常に参考になりました。
リモコンのフォーマットは 秋月電子通商のダウンロードコーナーの資料も大いに役立ちます。
手元にNECのテレビリモコンがあってラッキーでした。
タイマTMR0を使用しての時間の計測
内部クロックの周期は(1/4MHz)*4=1usとなる。
TMR0は8bitのカウンタであるため,
TMR0は,256us(1us * 256)までの時間を計測することができる。
これではリーダー部の9msを計測できないのでプリスケーラを設定する。
プリスケーラ1/64に設定
(1/4MHz)*4*64=64us=0.0664ms
TMR0は,16.384ms(64us * 256)までの時間を計測することができるようになる.
0.064msから16.384ms の間の時間を計測できる。
リーダ部の9ms を計測したい場合に必要なタイマーカウント、
9ms = 0.064ms * x
x = 9ms/0.064ms
x = 140.625 = 141回
/** 概要:TVリモコン信号(赤外線)受信器 (ボタンと押している間だけLED点灯、ボタンをはなすとLED消灯) Device Flags: _BODEN_OFF _BOREN_OFF _CP_OFF _PWRTE_ON _WDT_OFF _LVP_OFF _MCLRE_OFF _INTRC_OSC_NOCLKOUT PICとMikroCさん(http://kuri6005.sakura.ne.jp/pic/)のソースを PIC16F88 内蔵4MHzに変更 RB0:赤外線リモコン受信モジュール PL-TRM2161-C438 二個で100円 LED: RB2, RB3, RB4, RB5 動作確認用 電源:乾電池2本(3V) コンパイラ:MikroC 8.2.0.0 */ unsigned short int flag = 0; unsigned short int custom_a = 0; unsigned short int custom_b = 0; unsigned short int data_a = 0; unsigned short int data_b = 0; unsigned short int old_F2 = 0; unsigned short int old_F3 = 0; unsigned short int old_F4 = 0; unsigned short int old_F5 = 0; void interrupt() { //割込み関数 unsigned short int i, b; if(INTCON.INTF) { //割込み種がRB0/INT割込みの場合 INTCON.INTE = 0; //RB0/INT割込みの禁止 //リーダ部の確認 時間の計測にはタイマー0を割込みなしで使用 TMR0 = 0; //timer0リセット、タイマーは常に動作 while(PORTB.F0 == 0); //0Vの状態をカウント、5Vになるまでループ //カウンタの比較 if(TMR0 < 120) { // < 141 (=9.0ms * 4MHz/4 /64) 誤差を見越して120 flag = 1; //120より少なかったらヘッダではないので受信を終了し、 return; //メインルーチンに戻り、受信待ち状態にします } //120以上であれば次に進みます。 //リーダー部の残りの部分を判定 TMR0 = 0; //timer0リセット while(PORTB.F0 == 1); //5Vの状態をカウント if(TMR0 < 27) { // < 35 (=2.250ms * 4MHz/4 /64) flag = 1; return; }else if(TMR0 < 60) { // < 71 (=4.5ms * 4MHz/4 /64) //リピートリーダを受信した時 PORTB.F2 = old_F2; PORTB.F3 = old_F3; PORTB.F4 = old_F4; PORTB.F5 = old_F5; Delay_ms(96); flag = 1; return; } //リーダー部の確認終了 //custom codeの取得 custom_a = 0; for (i = 0; i < 8; i++) { //繰返し0-7になるまで TMR0 = 0; //timer0リセット while(PORTB.F0 == 0); //0Vの期間をカウント while(PORTB.F0 == 1); //5Vの期間をカウント if(TMR0 < 27) // < 18 (=1.125ms * 4MHz/4 /64) 誤差を見越して27(35より小さい値) b = 0; else // < 35 (=2.250ms * 4MHz/4 /64) b = 1; custom_a |= (b << i); //custom_aと(b << i)の論理和をcustom_aに代入する //bを左にiビットずらす } custom_b = 0; for (i = 0; i < 8; i++) { TMR0 = 0; //timer0リセット while(PORTB.F0 == 0); while(PORTB.F0 == 1); if(TMR0 < 27) // < 18 (=1.125ms * 4MHz/4 /64) b = 0; else // < 35 (=2.250ms * 4MHz/4 /64) b = 1; custom_b |= (b << i); } //custom codeの取得終了 //data codeの取得 data_a = 0; for (i = 0; i < 8; i++) { TMR0 = 0; //timer0リセット while(PORTB.F0 == 0); while(PORTB.F0 == 1); if(TMR0 < 27) // < 18 (=1.125ms * 4MHz/4 /64) b = 0; else // < 35 (=2.250ms * 4MHz/4 /64) b = 1; data_a |= (b << i); } data_b = 0; for (i = 0; i < 8; i++) { TMR0 = 0; //timer0リセット while(PORTB.F0 == 0); while(PORTB.F0 == 1); if(TMR0 < 27) // < 18 (=1.125ms * 4MHz/4 /64) b = 0; else // < 35 (=2.250ms * 4MHz/4 /64) b = 1; data_b |= (b << i); } //while(PORTB.F0 == 0); //ストップビット受信 //data_aとdata_bの各ビットを反転しその結果が同じか比較 if (data_a == ~data_b) { //data誤りのチェックOKの場合 switch (data_a) { case 0x11: //2チャンネルのボタンが押されている場合 PORTB.F2 = 1; //RB2ポートのLEDを点灯する。 PORTB.F3 = 0; PORTB.F4 = 0; PORTB.F5 = 0; break; case 0x13: //4チャンネルのボタンが押されている場合 PORTB.F2 = 0; PORTB.F3 = 1; PORTB.F4 = 0; PORTB.F5 = 0; break; case 0x15: //6チャンネルのボタンが押されている場合 PORTB.F2 = 0; PORTB.F3 = 0; PORTB.F4 = 1; PORTB.F5 = 0; break; case 0x17: //8チャンネルのボタンが押されている場合 PORTB.F2 = 0; PORTB.F3 = 0; PORTB.F4 = 0; PORTB.F5 = 1; break; default: PORTB.F2 = 0; PORTB.F3 = 0; PORTB.F4 = 0; PORTB.F5 = 0; break; } old_F2 = PORTB.F2; old_F3 = PORTB.F3; old_F4 = PORTB.F4; old_F5 = PORTB.F5; } } Delay_ms(40); flag = 1; } void main() { //使用変数の定義 unsigned short int i; PORTB = 0b00000000; //PORTBの中身をきれいにする OSCCON = 0b01100000; //内臓クロック4MHzに設定 TRISB = 0b00000001; //RB0を1:入力、他は0:出力に設定 //PIC稼働確認(LED点滅) for (i=0; i < 5; i++) { PORTB = 0b11111110; Delay_ms(50); PORTB = 0b00000000;; Delay_ms(50); } //timer0プリスケーラ64回に設定 OPTION_REG = 0b10000101; INTCON.INTE = 1; //RB0/INT割込みの許可 INTCON.GIE = 1; //全体割込み許可 do { if(flag == 1) { flag = 0; PORTB.F2 = 0; PORTB.F3 = 0; PORTB.F4 = 0; PORTB.F5 = 0; INTCON.INTE = 1; //RB0/INT割込みの許可 } }while(1); }
参考:5Vになるまでと表現していますが、実際には、受信センサーからの出力される電圧です。
0 件のコメント:
コメントを投稿