PIC16F1459の基本動作から応用プログラムまでを学びます。

ホーム
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
    
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
省電力 赤外線受信機

赤外線リモコンの信号を受信しボードのLEDを点灯させるプログラムです。
リモコンの「1」ボタンを押すと「LED D1」 が点灯します。
再び「1」を押すとLEDは消灯します。
同様に、リモコンの「2」「3」「4」がそれぞれ LED「D2」「D3」「D4」に対応します。

PICのペリフェラルは以下の用途に使用しています。

Timer1
信号の継続時間測定に使用
250KHz/4をカウントするので、16us単位となる。
赤外線センサー
B7で常にモニタしている。無信号時はPICがSLEEP状態になり、消費電力を最小に抑えているが、センサーからの信号が変位することで、SLEEPからWeak-up する。
システムクロック
クロックを250kHzまで下げて、極力消費電力を少なくしている。

赤外線リモコンの波形

この受信機は、JVCTVリモコンの使用を想定したプログラムになっています。JVCは、NECが設定した赤外線リモコン仕様に準拠しており、以下のフォーマット仕様です。

キャリア 赤外線(λp = 940nm) Data部 詳細 (T = 562μs)
サブキャリア fsc = 38kHz, 1/3duty Data の '1' Mark 1T + Space 3T
Leader 部 Mark 9mSec Space 4.5mSec Data の '0' Mark 1T + Space 1T
Data 部 固定長フレーム (16bit)
 8bitのカスタマーコード
 + 8bitのコマンドデータ
Stop bit Mark 1T
 
 

プログラム

プロジェクト B08_irRxSimple.zip

*注意*
 MPLAB X プロジェクト には、PICkit3で書き込む仕様とブートローダで書き込む2通りの仕が設定されています。どちらを利用するかをメインメニューバーのIDE Configuration pull down で選んでください。

// ----------------------------------------------------------------
//  NECタイプの赤外線リモコン受信 2017/1/14  OK
//  Notes: 250kHz 内部クロック
//    LED1 RC0,  LED2 RC1,  LED3 RC2,  LED4 RC3
//    Sencer  RB7
//    Language: MPLABX XC8
//    Target:   PIC16F1459
//      Rev2 Freq 250k 16bit data
// ----------------------------------------------------------------
#define _XTAL_FREQ  4000000/16   // delay_ms(x) のための定義  ==250k==
#define L_ON_Min    5000/16      // 5msec リーダーの最小継続時間
#define DataTH      1000/16      // 1msec データの「1」「0」境界時間
#define D_Off_Max   2000/16      // 2msec データ「0」の最大継続時間
#define IrIN        RB7          // 赤外線センサー入力
#define LED1        LATC0
#define LED2        LATC1
#define LED3        LATC2
#define LED4        LATC3

#include <xc.h>

#pragma config FOSC  = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = OFF
#pragma config CP  = OFF, BOREN = ON, CLKOUTEN = OFF, IESO  = OFF
#pragma config FCMEN = OFF, WRT = OFF, CPUDIV = NOCLKDIV
#pragma config USBLSCLK = 48MHz, PLLMULT = 3x, PLLEN = ENABLED
#pragma config STVREN = ON, BORV = LO, LPBOR = OFF, LVP = OFF

unsigned int IrCmdRcv(void);

// MAIN ********************************************************
void main(void){
    unsigned int revdData;
    OSCCON = 0b00011010;        // 内部クロック250khz
    LATC   = 0;                 // LED 初期化
    TRISC&=0xF0;
                                // Pin 状態変化 初期化
    IOCBNbits.IOCBN7 = 1;       // 負極性の変異でWake-up
    INTCONbits.IOCIE = 1;       // Wake-up 許可

    // Timer 1 設定 -------------------------------------------
    // リモコンパルス幅の計測に使用する Timer は、1カウント 16uS
    T1CON  = 0b00000000;        // Timer 1 FOSC/4 1/1(66mSecx16ごと)
    T1GCON = 0b00000000;        // Timer 1 Gate設定(使用せず)

    while(1){                   // 繰り返しループ
        TMR1ON = 0;                             // Timer1 OFF
        IOCBFbits.IOCBF7 = 0;                   // 入力変位フラッグ クリア
        SLEEP();                                // 無信号時はスリープ
        //--------------------
        TMR1ON = 1;                             // Timer1 ON
        revdData = IrCmdRcv();                  // データー取得
        if(revdData == 0) continue;             // データー無
        // ---- 受信データーの処理 -----------------------------------
        switch (revdData){
            case 0xC084: LED1 = !LED1; break;   // Key 1 LED1 反転
            case 0xC044: LED2 = !LED2; break;   // Key 2 LED2 反転
            case 0xC0C4: LED3 = !LED3; break;   // Key 3 LED3 反転
            case 0xC024: LED4 = !LED4; break;   // Key 4 LED4 反転
            default:     LATC = 0;     break;   // 他のKey 全消灯
        }
    }
}

//*************** 赤外線データーを受信する *****************************
// 正常にデーターを受信したときは、そのデーターを返り値とし
// 無信号、エラー時は、0を返す。
// ビクターの信号体系(NEC系)を受信
// リーダ受信確認、データ受信(16bits)する
//*******************************************************************
unsigned int IrCmdRcv(void){
    unsigned int rcvData = 0;
    if(IrIN) return 0;                    // 無信号「1」時は復帰

    // ------- Start Bit (リーダー)の確認 -----------------------------
    //OnおよびOFFの時間を確認しノイズか有効データか判断する
    // ---------------------------------------------------------------
    TMR1 = 0;                            // -- リーダーのON 時間測定
    while(TMR1 < L_ON_Min){              // リーダーの最小継続に達しないのに
        if(IrIN)return 0;                // IR Space「1」無信号になったら
    }                                    // ノイズと判断し復帰
    while(!IrIN);                        // IR Space 待ち
    TMR1 = 0;                            // -- リーダーのOFF時間測定
    while(IrIN){                         // リーダーの終了時間を越えても待ち
        if(TMR1 > L_ON_Min)return 0;     // data開始(IrON)しなければ復帰
    }
    // ------- dataの確認 -----------------------------------
    for(char i = 0; i < 16; i++){        // 1ビットずつ16回繰り返す
        rcvData <<= 1;
        while(!IrIN);                    // space 開始を待つ
        TMR1 = 0;                        //    Bitのspace時間測定開始
        while(IrIN)                      // space 終了を待つ
            if(TMR1 > D_Off_Max)         //    2mS以上ならStopなので
              return 0;                  //    復帰
        if(TMR1 > DataTH)                // 時間取得「1」「0」判定
            rcvData |= 1;                //   「1」を立てる
    }
    return rcvData;                      // 受信データを持って復帰
}