/*=========================================================================== * 赤外線リモコンの信号解析 * v001 Ex-INTでデータを一括受信し、その後MAINでRS出力する * 最初のコマンドでは正常に動作、以降はパルスの途中で起動。リーダ部を未認識 * v002 リーダ部の誤認識を改良する(未完) * v003 一部変更(if文の=が一つだった)(コマンド42ビット受信確認) * v004 コマンドを6バイトで表現する(確認) * v005 割込み処理内にコマンドバイト生成ルーチンを組み込む(確認) * v006 コマンドをEPROMに記憶して入力信号を区別する(確認)これで一旦完成 * --------------------------------------------------------------------------- * v010 新しい小型リモコンに合わせた変更。ビット=32パルス数33。 * Leader = 9.26 / 4.42 msec * data = 0.6 / 0.58 msec, 0.66 / 0.52 * data = 0.66 / 1.58 , 0.62 / 1.62 * コマンド数は17個 * * * =========================================================================== */ // PIC16F876A Configuration Bit Settings // 'C' source line config statements // CONFIG #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled) #pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled) #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) //------------------------------------------------------------------------- // プログラム初期設定 //------------------------------------------------------------------------- #include #include #include //PICのクロック設定 #define _XTAL_FREQ 20000000 //PICのクロックをHzで設定(20MHz) //------------------------------- // Defineエリア //------------------------------- #define monitor RA0 // モニター用LED //---------------------------------------- // 関数の定義 //---------------------------------------- void interrupt RB0_int(void); void RS_init(void); void RS_write(unsigned char); void TMR1write(int); void PIC_ini(void); //---------------------------------------- // 変数の定義 //---------------------------------------- int TMR1data, TM1H, TM1L; unsigned char STARTflg, RSoutH, RSoutL, CMDflg, FINDflg; unsigned char CMD_data[4], outdata; int cmd_max = 17; unsigned int cmd_entry; int cmd_num; eeprom unsigned int command[17] = {// 3 and 4 of CMD_data[n] should be used. 0x4ab5, //0 0x6897, //1 0x9867, //2 0xb04f, //3 0x30cf, //4 0x18e7, //5 0x7a85, //6 0x10ef, //7 0x38c7, //8 0x5aa5, //9 0x629d, //UP 0xa857, //DW 0xc23d, //RT 0x22dd, //FT 0x02fd, //OK 0x42bd, //* 0x52ad, //# }; int i, j, Bcnt; int LDH = 8700, LDL = 8300, DTLH = 817, DTLL = 604, DTHH = 1615, DTHL = 1194; void main(void) { //-------------------- // PIC初期化 //-------------------- PIC_ini(); //---------------------- // 起動確認 //---------------------- monitor = 0; __delay_ms(1000); monitor = 1; __delay_ms(1000); //------------ // RS232 初期化 //------------ RS_init(); //------------------------- // フラグチェック //------------------------- FINDflg = 0; //------------------ // RB0外部割込み許可 //------------------ INTF = 0; // 割り込みFLG解除 INTE = 1; // RB0割込み許可 GIE = 1; // 全割込み許可 //----------------- // TMR1リセットスタート //----------------- TMR1write(0); TMR1ON = 1; // TMR1 on //---------------------------------------------------- // メイン繰り返し処理バッファー内容をRSで一括送信する //---------------------------------------------------- while (1) { while (CMDflg == 0) { //コマンド全ビット受信完了になるまで待つ } COMP: //------------------------------------------ // 解析後のコマンド4バイトを送信(デバッグ用) //------------------------------------------ for (i = 0; i <= 3; i++) { RS_write(CMD_data[i]); } //--------------------- // コマンド解析 //--------------------- GIE = 0; // 全割込み禁止 cmd_entry = CMD_data[2]; cmd_entry = cmd_entry << 8; cmd_entry = cmd_entry | CMD_data[3]; for (i = 0; i <= cmd_max; i++) { if (cmd_entry == command[i]) break; } cmd_num = i; // コマンド番号をcmd_numにセット //----------------------------------------------- // PORTBのビット1?7に二進でコマンド番号を表示する //----------------------------------------------- switch (cmd_num) { // max 17 cases case 0: outdata = 0 << 1; break; case 1: outdata = 1 << 1; break; case 2: outdata = 2 << 1; break; case 3: outdata = 3 << 1; break; case 4: outdata = 4 << 1; break; case 5: outdata = 5 << 1; break; case 6: outdata = 6 << 1; break; case 7: outdata = 7 << 1; break; case 8: outdata = 8 << 1; break; case 9: outdata = 9 << 1; break; case 10: outdata = 10 << 1; break; case 11: outdata = 11 << 1; break; case 12: outdata = 12 << 1; break; case 13: outdata = 13 << 1; break; case 14: outdata = 14 << 1; break; case 15: outdata = 15 << 1; break; case 16: outdata = 16 << 1; break; case 17: outdata = 17 << 1; break; break; } PORTB = ~outdata; //------------- // フラグチェック //------------- CMDflg = 0; INTF = 0; // 割り込みFLG解除 GIE = 1; // 全割込み許可 TMR1write(0); FINDflg = 0; } } //=============================================================== // サブルーチン関数の記述 //=============================================================== //-------------------------------- // RB0ポート割り込み処理 //-------------------------------- void interrupt RB0_int(void) { //----------------------------------- // リーダ部、'0'、'1'、のTMR1カウント範囲 //----------------------------------- INTF = 0; // 割り込みFLG解除 TM1H = TMR1H; TM1L = TMR1L; TMR1write(0); TMR1data = (TM1H << 8) | TM1L; if (FINDflg == 1) goto FIND; //リーダ部がすでに検出すみならFINFへ if ((TMR1data <= LDH) && (TMR1data >= LDL))//リーダ部ならフラグ立てる { FINDflg = 1; Bcnt = 0; i = 0; j = 0; CMD_data[j] = 0; return; //リーダ部は読み飛ばす } else { // リーダ部でなければタイマーリセットして次のパルスをまつ FINDflg = 0; return; } FIND: if ((TMR1data <= DTLH) && (TMR1data >= DTLL)) { CMD_data[j] = CMD_data[j] & 0b11111110; // Bit0 = 0 } if ((TMR1data <= DTHH) && (TMR1data >= DTHL)) { CMD_data[j] = CMD_data[j] | 0b00000001; // Bit 0 = 1 } Bcnt = Bcnt + 1; // バイト数カウント i = i + 1; // ビット数カウント if (i >= 32) { // コマンドのビット総数 CMDflg = 1; //フラグをセットしてコマンド処理終了 FINDflg = 0; return; } if (Bcnt >= 8) { Bcnt = 0; j = j + 1; CMD_data[j] = 0; } else { CMD_data[j] = CMD_data[j] << 1; } return; } //----------------------------- // TMR1への書き込み //----------------------------- void TMR1write(int timerVal) { T1CONbits.TMR1ON = 0; // Write to the Timer1 register TMR1H = (timerVal >> 8); TMR1L = timerVal; // Start the Timer after writing to the register T1CONbits.TMR1ON = 1; } //----------------------------- // RS232 書き込み //----------------------------- void RS_write(unsigned char send_1B) { while (TXSTAbits.TRMT == 0) { } //TRMTが1になるまで待つ TXREG = send_1B; //データを送信レジスタにセット } //------------------------------- // RS232初期化 //------------------------------- void RS_init(void) { //送信レジスタ設定 TRISC7 = 1; //set input for RX TRISC6 = 0; //set output for TX TXSTA = 0b00100100; //非同期、8ビット、高速送信モード(bit2=1 ) //TXSTA = 0b00100000; //非同期、8ビット、低速モード) //SPBRG = 129; //2400 bps低速モード(20MHz低速モード) //SPBRG = 96; //3600bpsモード(20MHz) //SPBRG = 64; //4800 bps低速(20MHz)かなり取りこぼしあり SPBRG = 129; //9600 bpsモード(20MHz高速モード) //SPBRG = 20; // 57600 bpsモード(20MHz高速モード) //SPBRG = 64; // 9600 bps モード(10MHz)高速モード) //SPBRG = 10; // 57600 bpsモード(10MHz高速モード) //受信レジスタ設定 RCSTA = 0b10010000; //シリアル通信、8ビット、連続受信モード PIR1bits.RCIF = 0; //RCIFクリア } //----------------------------------- // PIC 16F876 初期設定(一般) //----------------------------------- void PIC_ini(void) { //アナログ設定、PICのポート設定 ADCON0 = 0b00000000; //アナログ使用しない ADCON1 = 0b00000110; //For degital I/O //割り込み不使用 INTCON = 0b00000000; //TMRをフリーランで使用 OPTION_REG = 0b00000000; GIE = 0; // 全体割り込み禁止 TMR0 = 0; //周辺機器割り込み不使用 PIE1 = 0; //周辺機器割り込みフラグクリア PIR1 = 0; TRISA = 0b00000000; TRISB = 0b00000001; TRISC = 0b00000000; // OUT = TX PORTA = 0b11111110; // Monitor LED RA0 PORTB = 0b11111111; PORTC = 0b11111111; //------------------- // TMR1タイマー設定 //------------------- T1CON = 0b00110000; // Prescale 1:8, TMR1 = not START TMR1ON = 0; // TMR1スタート(未) TMR1IE = 0; // TMR1オーバーフローで割り込み発生(OFF) //------------------ // RB0外部割込み設定 //------------------ GIE = 0; // 全割込み禁止 INTE = 0; // RB0割込み禁止 INTF = 0; // RB0割込み発生FLG INTEDG = 0; // RB0立下りで割り込み }