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

// --------------------------------------------------
// 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			0x30					// モジュールごとにアドレスを変えること!!

// 受信バッファサイズ
#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();
			}
		}
		// 特に何もしないで次のデータを待つ
	}
}