テレビの「d」(データ放送)ボタンが故障したため、「d」だけを送信できる赤外線リモコンコード送信機を作ってみた。
マイコン PIC12F1822 (1個150円程度)と、Ir LED (10個で100円程度)を用いた。
回路
PIC12F1822 プログラム
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <xc.h> /* PIC Configuration 1 */ __CONFIG(FOSC_INTOSC & // INTOSC oscillator: I/O function on CLKIN pin WDTE_OFF & // WDT(Watchdog Timer) disabled PWRTE_ON & // PWRT(Power-up Timer) disabled MCLRE_OFF & // MCLR pin function is digital input CP_OFF & // Program memory code protection is disabled CPD_OFF & // Data memory code protection is disabled BOREN_OFF & // BOR(Brown-out Reset) disabled CLKOUTEN_OFF & // CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin IESO_OFF & // Internal/External Switchover mode is disabled FCMEN_OFF); // Fail-Safe Clock Monitor is disabled /* PIC Configuration 2 */ __CONFIG(WRT_OFF & // Flash Memory Self-Write Protection : OFF VCAPEN_OFF & // VDDCORE pin functionality is disabled PLLEN_OFF & // 4x PLL disabled STVREN_ON & // Stack Overflow or Underflow will not cause a Reset BORV_HI & // Brown-out Reset Voltage Selection : High Voltage DEBUG_OFF & // In-Circuit Debugger disabled, ICSPCLK and ICSPDAT are general purpose I/O pins LVP_OFF); // Low-voltage programming : disable #ifndef _XTAL_FREQ /* 例:4MHzの場合、4000000 をセットする */ #define _XTAL_FREQ 4000000 #endif // NECコードの場合 //#define TIMING_START_HI 9000 //#define TIMING_START_LO 4500 //#define TIMING_SIGNAL_HI 560 //#define TIMING_SIGNAL_1_LO 1690 //#define TIMING_SIGNAL_0_LO 560 // 家電協コードの場合 #define TIMING_START_HI 3500 #define TIMING_START_LO 1600 #define TIMING_SIGNAL_HI 540 #define TIMING_SIGNAL_1_LO 1200 #define TIMING_SIGNAL_0_LO 360 // シャープのTVの「d」ボタンの例 unsigned char code_1 = 0x55; unsigned char code_2 = 0x5A; unsigned char code_3 = 0xF1; unsigned char code_4 = 0x48; unsigned char code_5 = 0x7A; unsigned char code_6 = 0x44; //待ち時間が変数設定できるarg_delay_ms()関数を定義 //(__delay_ms()は引数に変数設定が出来ない為) void arg_delay_ms(unsigned int x) { while(x) { __delay_ms(1); x--; } } void arg_delay_us(unsigned int x) { while(x) { __delay_us(1); x--; } } void decode_bit(unsigned char c){ for(int i=0; i<8; i++){ if(c & (0x80 >> i)){ CCP1CON = 0b00001100; __delay_us(TIMING_SIGNAL_HI); CCP1CON = 0b00000000; __delay_us(TIMING_SIGNAL_1_LO); } else{ CCP1CON = 0b00001100; __delay_us(TIMING_SIGNAL_HI); CCP1CON = 0b00000000; __delay_us(TIMING_SIGNAL_0_LO); } } } int main(int argc, char** argv) { // 基本機能の設定 OSCCON = 0b01101010; // 内部オシレーター 4MHz TRISA = 0b00101011; // IOポートRA0(AN0),RA1(SCL),RA5(RX)を入力モード(RA3は入力専用)、RA2(SDA),RA4(TX)を出力モード APFCONbits.RXDTSEL = 1; // シリアルポート RXをRA5ピンに割付 APFCONbits.TXCKSEL = 1; // シリアルポート TXをRA4ピンに割付 ANSELA = 0b00000000; // A/D変換をAN0,AN1,AN2,AN4を無効 PORTA = 0; CCP1SEL = 0; // RA2をCCP1(PWM)のP1Aで用いる CCP1CON = 0b00000000; // PWM(シングル) T2CON = 0b00000000; // TMR2プリスケーラ値を1倍に設定, Timer2はこの時点ではOFF // PR2 = Fosc / (Fpwm * 4 * Prescale) + 1 = 4000000 / (38000 * 4 * 1) + 1 = 27 PR2 = 0x19; // 27→25 CCPR1L = 0x0c; // PR2=0x19の場合デューティ値は6bitで、デューティ比50%の設定 CCPR1H = 0; TMR2 = 0; // Timer2カウンタを0 // PWM開始 TMR2ON = 1; // 0.05秒待つ __delay_ms(50); // スタートビット(リーダ) CCP1CON = 0b00001100; __delay_us(TIMING_START_HI); CCP1CON = 0b00000000; __delay_us(TIMING_START_LO); // 送信データ本体 decode_bit(code_1); decode_bit(code_2); decode_bit(code_3); decode_bit(code_4); decode_bit(code_5); decode_bit(code_6); // ストップビット(トレーラ) CCP1CON = 0b00001100; __delay_us(TIMING_SIGNAL_HI); CCP1CON = 0b00000000; __delay_us(TIMING_SIGNAL_HI); /* 終了 (無限ループでこれ以降何もしない) */ while(1){ __delay_ms(1000); } return (EXIT_SUCCESS); }