テレビの「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);
}

