본문 바로가기

PIC/XC8

[XC8]18F452에서 IR 리모콘 구현

일단은 테스트할수 있는 티비가 삼성것 뿐이라 삼성 코드만 입력해놨습니다.
최대한 주석 단다고 해놨는데 초보자 분들도 이해 하실지 모르겠습니다.

지금은 시리얼로 버튼 번호를 넘겨주면 그 코드들 실행시키는 프로그램입니다. 

원래는 메인 파일에 이렇게 많이 적는거 싫어 하는데 
초보자분들이 ctl+c, ctl+v 하실 수 있도록 메인 파일에 모든 소스를 넣었습니다. 

다른 부분은 리모콘 포멧 관련되서 조금이라도 자료 찾아보신 분들은 이해 하실 수 있으실겁니다. 
혹시 전혀 이해 되지 않는다면 리모콘 포멧 쪽을 찾아보시고 다시 방문해 주세요.
(나중에 시간되면 리모콘 포멧 관련 자료도 업로드 하겠습니다.)

큐 부분은 원형 큐가 뭔지 모르시면 이해가 안되실텐데 그냥 데이터 손실 방지하려고 만든겁니다.
9600으로 통신하면서 데이터 손실 걱정하는것도 그렇지만 예전부터 데이터는 큐에 먼저 넣는 것이 버릇이되서 저는 이게 편하더군요.
필요없으신분들은 지우셔도 무방합니다. 큐 부분만 빠져도 코드가 많이 줄어들겁니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/* 
 * File:   main.c
 * Author: JangSeongJin
 *
 * Created on 2014년 1월 2일 (목), 오후 5:49
 */
 
#include <xc.h> //XC 컴파일러는 기본으로 추가
#include <pic18F452.h>
 
#pragma config OSCS = OFF
#pragma config OSC = HS
#pragma config WDT = OFF
#pragma config LVP = ON
 
#define _XTAL_FREQ 20000000 //크리스탈 클럭 20MHz
 
#define ON 1
#define OFF 0
 
#define Que_SIZE 10
 
typedef unsigned char BYTE;
typedef unsigned int  WORD;
 
BYTE ms_count = 0;
 
BYTE QueData[Que_SIZE];
BYTE QueHead = 0;
BYTE QueTail = 0;
 
BYTE Command_Code[24][4] = {
        {0x07, 0x07, 0x02, 0xFD}, //0x00 : 전원
        {0x07, 0x07, 0x01, 0xFE}, //0x01 : 외부입력
        {0x07, 0x07, 0x11, 0xEE}, //0x02 : 0
        {0x07, 0x07, 0x04, 0xFB}, //0x03 : 1
        {0x07, 0x07, 0x05, 0xFA}, //0x04 : 2
        {0x07, 0x07, 0x06, 0xF9}, //0x05 : 3
        {0x07, 0x07, 0x08, 0xF7}, //0x06 : 4
        {0x07, 0x07, 0x09, 0xF6}, //0x07 : 5
        {0x07, 0x07, 0x0A, 0xF5}, //0x08 : 6
        {0x07, 0x07, 0x0C, 0xF3}, //0x09 : 7
        {0x07, 0x07, 0x0D, 0xF2}, //0x0A : 8
        {0x07, 0x07, 0x0E, 0xF1}, //0x0B : 9
        {0x07, 0x07, 0x1F, 0xE0}, //0x0C : 화면표시
        {0x07, 0x07, 0x27, 0xD8}, //0x0D : TV/유선
        {0x07, 0x07, 0x00, 0xFF}, //0x0E : 음성다중
        {0x07, 0x07, 0x3E, 0xC1}, //0x0F : 회면크기
        {0x07, 0x07, 0x23, 0xDC}, //0x10 : +100
        {0x07, 0x07, 0x13, 0xEC}, //0x11 : 앞채널
        {0x07, 0x07, 0x12, 0xED}, //0x12 : 채널 위로
        {0x07, 0x07, 0x10, 0xEF}, //0x13 : 채널 아래로
        {0x07, 0x07, 0x07, 0xF8}, //0x14 : 음량 크게
        {0x07, 0x07, 0x0B, 0xF4}, //0x15 : 음량 작게
        {0x07, 0x07, 0x1A, 0xE5}, //0x16 : 메뉴
        {0x07, 0x07, 0x0F, 0xF0}, //0x17 : 조용히
    };
 
//-----------------------------------------------------------------
// UART 초기화
//-----------------------------------------------------------------
void Initial_UART(void) {
    TXSTAbits.TXEN = 1; //Transmit Enable bit
    TXSTAbits.BRGH = 1; //High Baud Rate Select bit
    RCSTAbits.SPEN = 1; //Serial Port Enable bit
    RCSTAbits.CREN = 1; //Continuous Receive Enable bit
    SPBRG = 129; //9600 데이터 시트 확
}
 
//-----------------------------------------------------------------
// 인터럽트 초기화
//-----------------------------------------------------------------
void Initial_INTERRUPT(void) {
    RCONbits.IPEN = 1; //Interrupt Priority Enable bit
 
    INTCONbits.GIE = 1; //Global Interrupt Enable bit
    INTCONbits.PEIE = 1; //Peripheral Interrupt Enable bit
 
    PIE1bits.RCIE = 1; //USART Receive Interrupt Enable
    IPR1bits.RCIP = 1; //USART Receive Interrupt Priority bit
}
 
//-----------------------------------------------------------------
// PWM 초기화
//-----------------------------------------------------------------
void Initial_PWM(void) {
    CCP1CONbits.CCP1M = 0b1100; //CCPx Mode Select bits
 
    //CCPR1L = 0x2C; //20e-6*CCPR1L:CCP1CONbits.DC1B = 8.8us 1/3 Duty Cycle
    CCPR1L = 0x00;
    CCP1CONbits.DC1B = 0b00;
}
 
//-----------------------------------------------------------------
// 타이머 초기화
//-----------------------------------------------------------------
void Initial_TIMER(void) {
    T2CONbits.TMR2ON = 1; //Timer2 On bit
    T2CONbits.T2CKPS = 0b00; //Timer2 Clock Prescale Select bits
    PR2 = 131; //20e6/4/1/(PR2+1) = 37.88kHz
}
 
//-----------------------------------------------------------------
// 포트 초기화
//-----------------------------------------------------------------
void Initial_PORT(void) {
    TRISD = 0x00; //LED OUTPUT 설정
    PORTD = 0x00; //LED 전부 0 출력
 
    TRISCbits.RC2 = 0; //PWM OUTPUT 설정
 
    TRISAbits.RA4 = 0; //Timer 0 OUTPUT 설정
}
 
//-----------------------------------------------------------------
// 큐 초기화
//-----------------------------------------------------------------
void Initial_QUE(void) {
    QueHead = 0;
    QueTail = 0;
}
 
//-----------------------------------------------------------------
// UART로 데이터를 내보낸다.
//-----------------------------------------------------------------
void putch(BYTE data) {
    while(!TXIF) continue;
    TXREG = data;
}
 
//-----------------------------------------------------------------
// UART에서 데이터를 가져온다.
//-----------------------------------------------------------------
BYTE getch(void) {
    while(!RCIF) continue;
 
    return RCREG;
}
 
//-----------------------------------------------------------------
// 큐에 데이터가 있는지 확인 있으면 1, 없으면 0 반환
//-----------------------------------------------------------------
BYTE IsDataQue(void) {
    if(QueHead == QueTail) {
        return 0;
    }
    return 1;
}
 
//-----------------------------------------------------------------
// 큐에 데이터를 넣는다.
//-----------------------------------------------------------------
void PushQue(BYTE data) {
    QueData[QueHead++] = data;
    if(QueHead >= Que_SIZE) {
        QueHead = 0;
    }
}
 
//-----------------------------------------------------------------
// 큐에서 데이터를 뺀다.
//-----------------------------------------------------------------
BYTE PopQue(void) {
    BYTE data;
    data = QueData[QueTail++];
    if(QueTail >= Que_SIZE) {
        QueTail = 0;
    }
    return(data);
}
 
//-----------------------------------------------------------------
//Interrupt Service Routine
//-----------------------------------------------------------------
void interrupt isr(void) {
    if(RCIE && RCIF) {
        PushQue(getch());
    }
}
 
 
//-----------------------------------------------------------------
// 적외선 ON, OFF
//-----------------------------------------------------------------
void IR(BYTE i) {
    if(i) {
        CCPR1L = 0x2C; //20e-6*CCPR1L:CCP1CONbits.DC1B = 8.8us 1/3 Duty Cycle
        CCP1CONbits.DC1B = 0b00;
    }
    else {
        CCPR1L = 0x00; //20e-6*CCPR1L:CCP1CONbits.DC1B = 8.8us 1/3 Duty Cycle
     CCP1CONbits.DC1B = 0b00;
    }
    
}
 
void Lead_CODE(void) {
    IR(ON);
    __delay_us(4500);
    IR(OFF);
    __delay_us(4500);
}
 
void Bit_CODE(BYTE data) {
    if(data) {
        IR(ON);
        __delay_us(560);
        IR(OFF);
        __delay_us(1690);
    }
    else {
        IR(ON);
        __delay_us(560);
        IR(OFF);
        __delay_us(565);
    }
}
 
void Code_Generator(BYTE value) {
    int i, j;
    Lead_CODE();
    for(i=0;i<4;i++) {
        for(j=0;j<8;j++) {
            Bit_CODE((Command_Code[value][i] >> j)& 0x01);
        }
    }
    Bit_CODE(1);
}
 
void main(void) {
    
    int i;
    BYTE temp;
 
    Initial_PORT();
    Initial_UART();
    Initial_PWM();
    Initial_TIMER();
    Initial_QUE();
    Initial_INTERRUPT();
 
    while (1) {
        if(IsDataQue()) {
            temp = PopQue();
            Code_Generator(temp);
        }
    }
}


'PIC > XC8' 카테고리의 다른 글

[XC8]18F452에서 PWM 사용하기  (0) 2014.01.03
[XC8]18F452 UART 시리얼 통신  (0) 2014.01.02
[XC8]18F452 PORT Control  (0) 2014.01.02