スイッチモジュール2用プログラム(slave_switch_0x38_18f26k22.c)

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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
// --------------------------------------------------
// Global Versatile Controler http://www.gvc-on.net/
// --------------------------------------------------
// --------------------------------------------------
// Revision Memo (Y.M.D Editor/Memo)
// --------------------------------------------------
//
// スイッチモジュール用
//
// スイッチはリレーをON/OFFをするだけ。
// 弱電・強電ともにRA4をLOにすることで、リレーが短絡してスイッチONとなる。
// RA4はSTATUS LEDと共用なので、ピカピカさせないこと。
//
// ------------------------------
// BASE
// ------------------------------
// 2013.06.14 T.Kabu Rev.2用
 
//---------------------------------------------------
// Include Header
//---------------------------------------------------
// ----------------------------------------
// Standard Header
// ----------------------------------------
#include <xc.h>
#include <plib.h>
#include <htc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
// ----------------------------------------
// User Header
// ----------------------------------------
// Pragma Header
#include "pragma.h"
 
// PIC Parameter define and initialize
#include "pic_init.h"
 
// GVC Parameter define and initialize
#include "gvc_init.h"
 
// --------------------------------------------------
// Const Define
// --------------------------------------------------
#define VERSION "=== GVC SLAVE MODULE DEVICE PROGRAM for 18F26K22 (SWITCH) ==="
 
// ------------------------------
// PICのI2Cアドレス、適時変更すること
// ------------------------------
#define I2C_ADDR            0x38                    // モジュールごとにアドレスを変えること!!
 
// 受信バッファサイズ
#define SERIAL_RCV_BUFFSIZE 16
#define SERIAL_RCV_BUFFRING 15                      // SERIAL_RCV_BUFFSIZEから1減らした値を設定
 
// シリアルバッファサイズ
#define SERIAL_BUFF_SIZE    512
 
// I2Cバッファサイズ
#define RX_BUFF_SIZE        512
#define TX_BUFF_SIZE        512
 
// シリアルバッファとI2Cバッファは、それぞれのGVCモジュールで想定しているデータに合わせたサイズにすること
// 赤外線データだけは、どうがんばっても3096バイトをひとつ確保したら終わりなので、それぞれで使い回しをしないといけないので、使い方に注意すること
 
 
// --------------------------------------------------
// Variable Param
// --------------------------------------------------
// 割り込み処理内でのレジスタの値を格納する変数はここで宣言すること、割り込み処理内で宣言してはいけない!! T.Kabu 2013.05.14
unsigned char reg_RCSTA1;                           // 受信ステータスレジスタ
unsigned char reg_SSP1STAT;                         // SSP1ステータスレジスタ
unsigned char temp_buffer;                          // SSP1BUFの空読み用
GVC_I2C_MESSAGE_t * gvc_i2c_message;                // GVC I2Cメッセージ用ポインタ(tx_buffer/rx_bufferにかぶせる)
 
unsigned char serial_rcvptr;                        // 受信バッファポインタ
unsigned char serial_readptr;                       // 受信読み出しポインタ
unsigned char serial_rcvbuff[SERIAL_RCV_BUFFSIZE];  // 受信リングバッファ(RCREG1)
 
unsigned char serial_buffer[SERIAL_BUFF_SIZE];      // シリアルバッファ(作業用)
//char rcv_data;                                    // 受信データ
 
unsigned char rx_buffer[RX_BUFF_SIZE];              // 受信バッファ
unsigned int  rx_count = 0;                         // 受信バッファ位置
 
unsigned char tx_buffer[TX_BUFF_SIZE];              // 送信バッファ
unsigned int  tx_count = 0;                         // 送信バッファ位置
 
unsigned int  i2c_data_len;                         // I2Cのデータ長(data_len)
 
static char   i2c_status = 0;                       // I2Cステータス 0:待機状態 1:データ受信中 10:データ受信完了
 
// --------------------------------------------------
// Function prototype
// --------------------------------------------------
// --------------------------------------------------
// Sub Routine
// --------------------------------------------------
// ------------------------------
// Recieve serialdata
// ------------------------------
char rcv_serialdata(void)
{
    unsigned char data;
     
    // 返り値用データに受信データコピー
    data = serial_rcvbuff[serial_readptr];
    // 受信読み出しポインタを加算
    serial_readptr ++;
    // 受信読み出しポインタをリングる
    serial_readptr &= SERIAL_RCV_BUFFRING;
     
    // 受信データを返す
    return data;
}
 
// ----------------------------------------
// Setup 18F26K22 for Analog Voltage
// ----------------------------------------
void init_pic_for_analogvoltage(void)
{
    // ------------------------------
    // ポートA設定
    // ------------------------------
    // bit7   : RA7 1 = input, 0 = output
    // bit6   : RA6 1 = input, 0 = output
    // bit5   : RA5 1 = input, 0 = output
    // bit4   : RA4 1 = input, 0 = output
    // bit3   : RA3 1 = input, 0 = output
    // bit2   : RA2 1 = input, 0 = output
    // bit1   : RA1 1 = input, 0 = output
    // bit0   : RA0 1 = input, 0 = output
    TRISA = 0b00001111;     // RA0-RA3をを電圧測定用にinputモード
     
    // ANSELA: PORTA ANALOG SELECT REGISTER ポートのI/Oモードの設定。
    // bit7-6 : none (0)
    // bit5   : ANSA4: Analog Select between Analog or Digital Function on pins RA5, respectively
    //            0 = Digital I/O. Pin is assigned to port or digital special function.
    //            1 = Analog input. Pin is assigned as analog input(1). Digital input buffer disabled.
    // bit4   : none (0)
    // bit3   : ANSA3: Analog Select between Analog or Digital Function on pins RA3, respectively
    // bit2   : ANSA2: Analog Select between Analog or Digital Function on pins RA2, respectively
    // bit1   : ANSA1: Analog Select between Analog or Digital Function on pins RA1, respectively
    // bit0   : ANSA0: Analog Select between Analog or Digital Function on pins RA0, respectively
    ANSELA = 0b00001111;    // AN0(=RA0),AN1(=RA1),AN2(=RA2),AN3(=RA3) Analog input
     
    // ADCON0 は、実際に電圧を読むときに、そのポートを指定しないといけないのでここではいじらない
     
    // bit 7 TRIGSEL: Special Trigger Select bit
    //     1 = Selects the special trigger from CTMU
    //     0 = Selects the special trigger from CCP5
    // bit 6-4 Unimplemented: Read as ‘0’
    // bit 3-2 PVCFG<1:0>: Positive Voltage Reference Configuration bits
    //     00 = A/D VREF+ connected to internal signal, AVDD
    //     01 = A/D VREF+ connected to external pin, VREF+
    //     10 = A/D VREF+ connected to internal signal, FVR BUF2
    //     11 = Reserved (by default, A/D VREF+ connected to internal signal, AVDD)
    // bit 1-0 NVCFG0<1:0>: Negative Voltage Reference Configuration bits
    //     00 = A/D VREF- connected to internal signal, AVSS
    //     01 = A/D VREF- connected to external pin, VREF-
    //     10 = Reserved (by default, A/D VREF+ connected to internal signal, AVSS)
    //     11 = Reserved (by default, A/D VREF+ connected to internal signal, AVSS)
//  ADCON1 = 0b00000000;        // VREF+、VREF-ともに内部供給電圧Vddに対しての値となる
    ADCON1 = 0b00001000;        // VREF+はFVRから、VREF-はGNDに対しての値となる
     
    // AD変換制御レジスタ2設定 A/D CONTROL REGISTER 2
    // bit 7 ADFM: A/D Conversion Result Format Select bit
    //     1 = Right justified
    //     0 = Left justified
    // bit 6 Unimplemented: Read as ‘0’
    // bit 5-3 ACQT<2:0>: A/D Acquisition time select bits. Acquisition time is the duration that the A/D charge holding
    //         capacitor remains connected to A/D channel from the instant the GO/DONE bit is set until conversions
    //         begins.
    //     000 = 0(1)
    //     001 = 2 TAD
    //     010 = 4 TAD
    //     011 = 6 TAD
    //     100 = 8 TAD
    //     101 = 12 TAD
    //     110 = 16 TAD
    //     111 = 20 TAD
    // bit 2-0 ADCS<2:0>: A/D Conversion Clock Select bits
    //     000 = FOSC/2
    //     001 = FOSC/8
    //     010 = FOSC/32
    //     011 = FRC(1) (clock derived from a dedicated internal oscillator = 600 kHz nominal)
    //     100 = FOSC/4
    //     101 = FOSC/16
    //     110 = FOSC/64
    //     111 = FRC(1) (clock derived from a dedicated internal oscillator = 600 kHz nominal)
    ADCON2 = 0b10110101;    // 右寄せ、16TAD、FOSC/16
     
    // 電圧リファレンス制御レジスタ0 FIXED VOLTAGE REFERENCE CONTROL REGISTER
    // bit 7 FVREN: Fixed Voltage Reference Enable bit
    //     0 = Fixed Voltage Reference is disabled
    //     1 = Fixed Voltage Reference is enabled
    // bit 6 FVRST: Fixed Voltage Reference Ready Flag bit
    //     0 = Fixed Voltage Reference output is not ready or not enabled
    //     1 = Fixed Voltage Reference output is ready for use
    // bit 5-4 FVRS<1:0>: Fixed Voltage Reference Selection bits
    //     00 = Fixed Voltage Reference Peripheral output is off
    //     01 = Fixed Voltage Reference Peripheral output is 1x (1.024V)
    //     10 = Fixed Voltage Reference Peripheral output is 2x (2.048V)(1)
    //     11 = Fixed Voltage Reference Peripheral output is 4x (4.096V)(1)
    // bit 3-2 Reserved: Read as ‘0’. Maintain these bits clear.
    // bit 1-0 Unimplemented: Read as ‘0’.
    VREFCON0 = 0b10110000;  // FVR有効、x4の4.096Vとする
}
 
// ----------------------------------------
// Switch ON/OFF
// ----------------------------------------
void switch_onoff(char cmd, char * result_buff)
{
    // スイッチはリレーをON/OFFをするだけ。
    // 弱電・強電ともにRA4をLOにすることで、リレーが短絡してスイッチONとなる。
    // RA4はSTATUS LEDと共用なので、ピカピカさせないこと。
     
    // コマンド別に処理分岐
    switch (cmd)
    {
        case 0x20:  // スイッチOFF
            // スイッチOFF
            PORT_STATUS_LED = LED_OFF;
            // スイッチOFFを設定
            sprintf(result_buff, "SWITCH OFF");
            break;
        case 0x21:  // スイッチON
            // スイッチON
            PORT_STATUS_LED = LED_ON;
            // スイッチOFFを設定
            sprintf(result_buff, "SWITCH ON");
            break;
        default:
            sprintf(result_buff, "Unsupported cmd=0x%02x", cmd);
            break;
    }
    // シリアルにも処理結果を出力
    send_strdata(result_buff);
    send_cr();
}
 
// ------------------------------
// Setup MSSP1 18F26K22
// ------------------------------
void init_mssp1_18F26K22(void)
{
    // ------------------------------
    // MSSP1制御データ設定 スレーブとして設定する場合
    // ------------------------------
    // bit 7   : SMP 1 = Slew rate control disabled for standard speed mode (100 kHz and 1 MHz)
    //         :     0 = Slew rate control enabled for high speed mode (400 kHz)
    // bit 6   : CKE 1 = Enable input logic so that thresholds are compliant with SMbus specification
    //         :     0 = Disable SMbus specific inputs
    // bit 5   : D/A: Data/Address bit (I2C mode only)
    //         :     1 = Indicates that the last byte received or transmitted was data
    //         :     0 = Indicates that the last byte received or transmitted was address
    // bit 4   : P: Stop bit
    //         : (I2C mode only. This bit is cleared when the MSSPx module is disabled, SSPxEN is cleared.)
    //         :     1 = Indicates that a Stop bit has been detected last (this bit is ‘0’ on Reset)
    //         :     0 = Stop bit was not detected last
    // bit 3   : S: Start bit
    //         : (I2C mode only. This bit is cleared when the MSSPx module is disabled, SSPxEN is cleared.)
    //         :     1 = Indicates that a Start bit has been detected last (this bit is ‘0’ on Reset)
    //         :     0 = Start bit was not detected last
    // bit 2   : R/W: Read/Write bit information (I2C mode only)
    //         : In I2 C Master mode:
    //         :     1 = Transmit is in progress
    //         :     0 = Transmit is not in progress
    //         : OR-ing this bit with SEN, RSEN, PEN, RCEN or ACKEN will indicate if the MSSPx is in Idle mode.
    //         : (このビットと、SEN、RSEN、PEN、RCEN、またはACKEN との論理和を取ると、マスタモードがアクティブかどうかを判断できる)
    // bit 1   : UA: Update Address bit (10-bit I2C mode only)
    // bit 0   : BF: Buffer Full Status bit
    //         : Receive (SPI and I2 C modes):
    //         :     1 = Receive complete, SSPxBUF is full
    //         :     0 = Receive not complete, SSPxBUF is empty
    //         : Transmit (I2 C mode only):
    //         :     1 = Data transmit in progress (does not include the ACK and Stop bits), SSPxBUF is full
    //         :     0 = Data transmit complete (does not include the ACK and Stop bits), SSPxBUF is empty
    SSP1STAT= 0b00000000;   // 400kHz Slew rate
     
    // bit7   : WCOL master(1 = Collision, 0 = No Collision), slave(1 = must be cleard, 0 = No Collision)
    // bit6   : SSP1OV SPI(pass), I2C(1 = overflow, 0 = not Overflow)
    // bit5   : SSP1EN SPI(pass), I2C(1 = enable SDA/SCL w/input mode, 0 = disable)
    // bit4   : CKP    SPI(pass), I2C(master(1 = enable clock, 0 = hold clock low), slave (unused))
    // bit3-0 : SSP1M  0110 I2C Slave mode, 7bit address
    //        : SSP1M  0111 I2C Slave mode, 10bit address
    //        : SSP1M  1000 I2C Master mode, clock = Fosc/(4 * (SSP1ADD + 1))
    //        : SSP1M  1011 I2C F/W controled Master mode(Slave Idle)
    //        : SSP1M  1110 I2C Slave mode, 7bit address w/Start/Stop bit INT
    //        : SSP1M  1111 I2C Slave mode, 10bit address w/Start/Stop bit INT
    SSP1CON1 = 0b00110110;      // SSP1EN = 1, CKP = 1, SSP1M = Slave mode 7bit
     
    SSP1CON2bits.SEN = 1;       // Start Condition Enabled bit ... SSP1CON2) ←マスターからデータを受け取るなら設定必要
     
    // このデバイスのI2Cアドレスを設定
    SSP1ADD = I2C_ADDR << 1;
     
    // MSSP1割り込み初期化
    PIR1bits.SSP1IF = 0;
     
    // MSSP1バス衝突割り込みフラグを初期化
    PIR2bits.BCL1IF = 0;
     
    // 100ms待つ
    Delay_10ms(10);
}
 
// ------------------------------
// Interrupt Routine
// ------------------------------
// I2Cのマスターとスレーブとのやり取りは、データシートの説明が言葉足らずなために
// 非常に判りづらい。ただし、判ってしまうと何だそれだけか、となる。
//
// 特にスレーブ側であれこれ設定したり判定や処理に必要なのは次のビット
// ・D/A…1=SSP1BUFの中はデータ、0=SSP1BUFの中はアドレス(空っぽ…空の読み出し要求時)
// ・R/W…1=マスターがスレーブから受信、0=マスターがスレーブへ送信
// ・BF…1=バッファに何か入っている(空の読み出し要求時も)、0=バッファは空っぽ
// ・CKP…マスターにデータ送信を許可するとき、スレーブから送信するときに1にしてSCLをリリースする
// ・SSP1IF…割り込みフラグ、なんかしたらクリアする
// ・SEN…マスターからデータを受信する時に、ソフト側でCKPを制御するために1にする。0だとうまく動かないよ!!
//(・S…スタートビット、特に使わなくてもいい気がする)
//
// で、判定に使うビットが多いけど、基本的にはSSP1STATなので、マスクして一括判定すればOK。
// --------------------------------------------------
// 18F26K22 Interrupt Routine
// --------------------------------------------------
// 割り込みはすべてinterrupt宣言されたこの関数が呼ばれる
static void interrupt interrupt_18F26K22()
{
    // 全割り込みを禁止(=0) (Global Interrupt Enable bit ... INTCON)
    INTCONbits.GIE = 0;
     
    // ----------------------------------------
    // MSSP1割り込み処理 (Rev.1の18F26K22_I2C.cを参照すること
    // ----------------------------------------
    // MSSP割り込み(=1)なら (Synchronous Serial Port (MSSP) Interrupt Flag bit ... PIR1)
    if (PIR1bits.SSP1IF == 1)
    {
        // ステータスLEDを点灯…すると毎回ONになるのでスイッチ系では点灯/消灯しない
///     PORT_STATUS_LED = LED_ON;
         
        // MSSP割り込みクリア(=0) (Synchronous Serial Port (MSSP) Interrupt Flag bit ... PIR1)
        PIR1bits.SSP1IF = 0;
         
        // SSP1ステータスを取得、D/A、R/W、BFビットをマスク
        reg_SSP1STAT = SSP1STAT & 0b00100101;
         
        // SSP1ステータスが、アドレス(D/A=0)で、かつマスターがスレーブへ送信(R/W=0)、かつバッファに何かある(BF=1)なら
        if (reg_SSP1STAT == 0b00000001)
        {
            // リザルトLEDを点灯
            PORT_RESULT_LED = LED_ON;
             
            // SSP1BUFを空読みして
            temp_buffer = SSP1BUF;
            // 受信バッファ位置を初期化
            rx_count = 0;
             
            // I2Cステータス 0:待機状態 1:データ受信中 10:データ受信完了
            i2c_status = 1;
             
            // SCLをリリースしてマスターにデータの送信を許可する
            SSP1CON1bits.CKP1 = 1;
             
            // リザルトLEDを消灯
            PORT_RESULT_LED = LED_OFF;
        }
        // SSP1ステータスが、データ(D/A=1)で、かつマスターがスレーブへ送信(R/W=0)、かつバッファに何かある(BF=1)なら
        else if (reg_SSP1STAT == 0b00100001)
        {
            // リザルトLEDを点灯
            PORT_RESULT_LED = LED_ON;
             
            // SSP1BUFからデータを読み出して、受信バッファの受信バッファ位置に設定
            rx_buffer[rx_count] = SSP1BUF;
             
            // 受信バッファ位置が3まで来てたら
            if (rx_count == 3)
            {
                // このあと受信するデータ長を設定
                i2c_data_len = *(int *)(rx_buffer + 2);
            }
            // 受信バッファ位置がchecksum(つまりメッセージ終了)なら
            if (rx_count == (GVC_I2C_MESSAGE_HEADER_SIZE + i2c_data_len))
            {
                // --------------------------------------------------------------------------------
                // 必要ならメッセージ受信したよフラグでも立ててメインループ内で処理してもらう
                // --------------------------------------------------------------------------------
                // I2Cステータス 0:待機状態 1:データ受信中 10:データ受信完了
                i2c_status = 10;
                 
                //
                // まぁこの時点でtx_bufferに指定されたフォーマットでデータを生成しておいた方がいいと思うんだけどどうだろう?
                //
                // ・メッセージデータのCRCを検査
                // ・OKならフォーマットやコマンドに基づいて処理、NGならシリアルにその旨出力
                //
                // CRCチェックがOKなら
                if (GetCRC8((void *)rx_buffer, rx_count + 1) == 0)
                {
                    // 受信バッファをI2Cメッセージポインタに設定
                    gvc_i2c_message = (GVC_I2C_MESSAGE_t *)rx_buffer;
                     
                    // コマンドを作業用バッファにコピー
                    temp_buffer = gvc_i2c_message->cmd;
                     
                    // 送信バッファをI2Cメッセージポインタに設定
                    gvc_i2c_message = (GVC_I2C_MESSAGE_t *)tx_buffer;
                     
                    // コマンドに基づいて処理
                    switch (temp_buffer)
                    {
                        case 0x20 :     // 0x20:スイッチOFF要求
                        case 0x21 :     // 0x21:スイッチON要求
                            // スイッチON/OFF
                            switch_onoff(temp_buffer, gvc_i2c_message->data);
                        case 0x2f :     // 0x2f:スイッチ状態要求
                            // STATUS LEDの状態により状態文字列を設定
                            // ON状態なら
///                         if (PORT_STATUS_LED == LED_ON)    ←何でこれでコンパイルエラーなんだよ!!
                            if (PORT_STATUS_LED == 0)
                            {
                                sprintf(gvc_i2c_message->data, "ON");
                            }
                            // OFF状態なら
                            else
                            {
                                sprintf(gvc_i2c_message->data, "OFF");
                            }
                            break;
                        default :
                            // コマンドエラーを設定
                            sprintf(gvc_i2c_message->data, "COMMAND ERROR!?, %02x", temp_buffer);
                            break;
                    }
                    // メッセージフォーマットに基づいて設定する
                    gvc_i2c_message->format = rx_buffer[0];      // マスターからの要求フォーマットをそのまま返す
                    gvc_i2c_message->cmd = rx_buffer[1];     // エラーの場合にはここを違うデータにするのがいいと思う…TBD
                    gvc_i2c_message->data_len = strlen(gvc_i2c_message->data);        // データ長
                    // CRCを計算して、メッセージの最後に設定
                    gvc_i2c_message->data[gvc_i2c_message->data_len] = GetCRC8((void *)tx_buffer, GVC_I2C_MESSAGE_HEADER_SIZE + gvc_i2c_message->data_len);
                 
                }
                // CRCチェックがNGなら
                else
                {
                    sprintf(tx_buffer, "MASTER MESSAGE CRC ERROR!?");
                }
            }
            // 受信バッファ位置を+1
            rx_count ++;
            // SCLをリリースしてマスターにデータの送信を許可する
            SSP1CON1bits.CKP1 = 1;
            // 受信データがバッファいっぱいになったりしたらフラグでも立ててエラー処理とかする
            if (rx_count >= RX_BUFF_SIZE)
            {
                rx_count = 0;
            }
             
            // リザルトLEDを消灯
            PORT_RESULT_LED = LED_OFF;
        }
        // アドレス(D/A=0)で、かつマスターがスレーブから受信(R/W=1)、かつバッファに何かある(BF=1)な
        else if (reg_SSP1STAT == 0b00000101)
        {
            // リザルトLEDを点灯
            PORT_RESULT_LED = LED_ON;
             
            // SSP1BUFを空読みして
            temp_buffer = SSP1BUF;
            // 送信バッファ位置を初期化
            tx_count = 0;
            // 送信バッファの最初のデータをSSP1BUFに設定
            SSP1BUF = tx_buffer[tx_count];
            // SCLをリリースしてマスターにデータの送信を許可する
            SSP1CON1bits.CKP1 = 1;
            // 送信バッファ位置を+1;
            tx_count ++;
             
            // リザルトLEDを消灯
            PORT_RESULT_LED = LED_OFF;
        }
        // データ(D/A=1)で、かつマスターがスレーブから受信(R/W=1)、かつバッファが空(BF=0)なら
        else if (reg_SSP1STAT == 0b00100100)
        {
            // リザルトLEDを点灯
            PORT_RESULT_LED = LED_ON;
             
            // 送信バッファの送信バッファ位置のデータをSSP1BUFに設定
            SSP1BUF = tx_buffer[tx_count];
            // SCLをリリースしてマスターにデータの送信を許可する
            SSP1CON1bits.CKP1 = 1;
            // 送信バッファ位置を+1;
            tx_count ++;
            // 送信バッファ位置が送信バッファを越えそうになったりしたらフラグでも立ててエラー処理とかする
            if (tx_count >= TX_BUFF_SIZE)
            {
                tx_count = 0;
            }
             
            // リザルトLEDを消灯
            PORT_RESULT_LED = LED_OFF;
        }
        // これら以外は
        else
        {
            // SSP1BUFを空読みして
            temp_buffer = SSP1BUF;
            // SCLをリリースしてマスターに次の命令を促す
            SSP1CON1bits.CKP1 = 1;
        }
        // ステータスLEDを消灯…すると毎回OFFになるのでスイッチ系では点灯/消灯しない
///     PORT_STATUS_LED = LED_OFF;
    }
     
     
    // ----------------------------------------
    // シリアル1受信割り込み処理
    // ----------------------------------------
    // シリアル1受信割り込み(=1)なら (RC1IF: EUSART1 Receive Interrupt Flag bit ... INTCON)
    // 1 = The EUSART1 receive buffer, RCREG1, is full (cleared when RCREG1 is read)
    // 0 = The EUSART1 receive buffer is empty
    if (PIR1bits.RC1IF == 1)
    {
        // 受信ステータスを取得
        reg_RCSTA1 = RCSTA1;
        // 受信ステータスを確認してフレーミングエラー、オーバーランエラーがなければ
        if ((reg_RCSTA1 & 0b00000110) == 0b00000000)
        {
            // 受信バッファ(RCREG1)から1バイト取得
            serial_rcvbuff[serial_rcvptr] = RCREG1;
            // 受信バッファポインタを加算(+1)
            serial_rcvptr ++;
            // 受信バッファポインタをリングる
            serial_rcvptr &= SERIAL_RCV_BUFFRING;
        }
        // 受信ステータスを確認してオーバーランエラーがあるなら
        else if (reg_RCSTA1 & 0b00000010)
        {
            // CREN レシーバイネーブルビットをクリアして再設定
            RCSTA1bits.CREN = 0;
            RCSTA1bits.CREN = 1;
        }
        // エラーがないなら
        else
        {
            // 受信バッファ(RCREG1)から1バイト取得
            serial_rcvbuff[serial_rcvptr] = RCREG1;
        }
        // シリアル1受信割り込みクリア(=0)…は1バイト受信すれば自動的にクリアされるので必要ない
        //PIR1bits.RC1IF = 0;
         
        // ほんとはここで、受信バッファポインタserial_rcvptrがリングバッファを上書きしないように
        // するとか、あわせてフロー制御するとか、いろいろあるけど、今回はとりあえずほっとく
    }
    // 全割り込みを許可(=1) (Global Interrupt Enable bit ... INTCON)
    INTCONbits.GIE = 1;
}
 
// --------------------------------------------------
// Main loop
// --------------------------------------------------
void main(void)
{
    char rcv_data;                          // 受信データ
     
    // Setup 18F26K22
    init_pic_18F26K22();
     
    // Setup MSSP1 18F26K22
    init_mssp1_18F26K22();
     
    // Setup EUSART 18F26K22
    init_eusart_18F26K22();
     
    // ----------------------------------------
    // これより下に、個別の設定を記述
    // ----------------------------------------
    PORT_STATUS_LED = LED_OFF;
     
    // リザルトLEDを点滅
    led_result_brink(1);
     
    // Setup 18F26K22 for Analog Voltage
    init_pic_for_analogvoltage();
     
    // Get Vdd Voltage
    vdd_volt = get_vdd();
    // もしVddが4.0Vより大きいとか、1.0V未満なら
    if (vdd_volt > 4.0 || vdd_volt < 1.0)
    {
        // たぶんちゃんと測定できていないってことで、5.00に固定
        vdd_volt = 5.00;
    }
     
    // 各種グローバル変数の初期化…グローバル変数は宣言時に初期化していても実際にはしてくれない…orz 2013.07.11 T.Kabu
    rx_count = 0;                           // 受信バッファ位置
    tx_count = 0;                           // 送信バッファ位置
    i2c_status = 0;                         // I2Cステータス 0:待機状態 1:データ受信中 10:データ受信完了
     
    // ----------------------------------------
    // 個別設定終了
    // ----------------------------------------
     
    // リザルトLEDを点滅
    led_result_brink(2);
     
    // 受信バッファポインタを初期化
    serial_rcvptr = 0;
    // 受信読み出しポインタを初期化
    serial_readptr = 0;
     
    // バッファを初期化
    memset((void *)serial_buffer, 0x00, sizeof(serial_buffer));
     
    // EUSART1 RX 割り込み許可(=1) (EUSART1 Receive Interrupt Enable bit ... PIE1)
    PIE1bits.RC1IE = 1;
    // MSSP割り込み許可(=1) (Synchronous Serial Port (MSSP) Interrupt Enable bit ... PIE1)
    PIE1bits.SSP1IE = 1;
    // 周辺割り込み許可(=1) (Peripheral Interrupt Enable bit ... INTCON)
    INTCONbits.PEIE = 1;
    // 全割り込みを許可(=1) (Global Interrupt Enable bit ... INTCON)
    INTCONbits.GIE = 1;
     
    // バージョンを送信
    send_strdata(VERSION);
    send_cr();
     
    // リザルトLEDを点滅
    led_result_brink(3);
     
    // メインループ
    while(1)
    {
        // シリアルバッファに未読データがないならスルー
        if (serial_rcvptr == serial_readptr)
        {
        }
        // あるなら
        else
        {
            // 受信バッファから一文字取得
            rcv_data = rcv_serialdata();
             
            // 1が来たらスイッチをONにする
            if (rcv_data == '1')
            {
                // スイッチON/OFF
                switch_onoff(0x21, serial_buffer);
                // 結果を送信
                send_strdata(serial_buffer);
                send_cr();
            }
            // 0が来たらスイッチをONにする
            else if (rcv_data == '0')
            {
                // スイッチON/OFF
                switch_onoff(0x20, serial_buffer);
                // 結果を送信
                send_strdata(serial_buffer);
                send_cr();
            }
        }
        // 特に何もしないで次のデータを待つ
    }
}