// -------------------------------------------------- // Global Versatile Controler http://www.gvc-on.net/ // -------------------------------------------------- // -------------------------------------------------- // Revision Memo (Y.M.D Editor/Memo) // -------------------------------------------------- // // 赤外線モジュール用 // // 赤外線モジュールは大きく別けて以下の二つの動作を行う // ・既存赤外線リモコン信号の受信(サンプリング) // ・指定された赤外線リモコン信号の送信 // もともとの赤外線信号をサンプリングしてそれを元にPWMを再生するというおバカ学習リモコンみたいな感じ // // メモリの関係でGVCフォーマットにそった形でメモリ共有する // // ------------------------------ // BASE // ------------------------------ // 2014.01.24 T.Kabu スイッチと赤外線リモコンから流用 //--------------------------------------------------- // 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 (IR SENSOR) ===" // PICのI2Cアドレス、適時変更すること #define I2C_ADDR 0x11 // モジュールごとにアドレスを変えること!! // 受信バッファサイズ #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; // 受信バッファ位置 unsigned char tx_buffer[TX_BUFF_SIZE]; // 送信バッファ unsigned int tx_count; // 送信バッファ位置 unsigned int i2c_data_len; // I2Cのデータ長(data_len) static char i2c_status; // I2Cステータス 0:待機状態 1:データ受信中 10:データ受信完了 unsigned char timer0_h; // タイマー0のHighの値 unsigned char timer0_l; // タイマー0のLowの値 static char pir_sensor_status; // 赤外線センサーステータス 0:未検知 1:検知中 static char pir_sensor_value; // 赤外線センサーのポート値(0=検知、1=未検知) unsigned int pir_sensor_count; // 赤外線センサーカウンタ // -------------------------------------------------- // 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とする } // ------------------------------ // 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); } // ---------------------------------------- // Get PIR data // ---------------------------------------- float get_pirdata(char format, char * result_buff) { // float をスタックにいっぱい用意しようとすると、オーバーフローになるよ!! "fixup overflow referencing psect..." といわれて // リンクできなかったら、変数はstatic宣言でちゃんと固定メモリ領域を使おう 2013.06.10 T.Kabu // PORT_IR_RX の値を取得 pir_sensor_value = PORT_IR_RX; // 赤外線センサーの状態を設定(1->0, 0->1とする) pir_sensor_status = pir_sensor_value ^ 1; // フォーマット別に処理分岐 switch (format) { case 0x01: // 現在の焦電センサーの状態(0x00:未検知、0x01:検知) sprintf(result_buff, "%d", pir_sensor_status); break; case 0x02: // 現在の焦電センサーの経過(サンプリング間隔と検知カウント数を返す) sprintf(result_buff, "PIR INTERVAL = 0.1s, PIR COUNT = %d", pir_sensor_count); break; case 0x11: // 現在の焦電センサーの状態(ポートの値をそのまま) sprintf(result_buff, "%d", pir_sensor_value); break; default: sprintf(result_buff, "Unsupported %02x", format); break; } // 赤外線センサーの状態を返す return pir_sensor_status; } // ------------------------------ // Setup Timer 18F26K22 // ------------------------------ void init_timer_18F26K22(void) { // 割り込み処理内でビットシフトとかあれかな?と思ってここで予め作っておくことにする // 受信タイムアウトタイマー値設定 timer0_h = (TIMER_100ms >> 8); timer0_l = (TIMER_100ms & 0x00ff); } // ------------------------------ // 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。 // // 赤外線リモコンデータの送信では、送信用の割り込みが来たらとりあえずすぐに出力を変更してから、次のデータの // 設定などをする。次の割り込みまでは80usしかない(サンプリング間隔を短くしたらもっと少ない)ので、処理は極力 // 単純にして短時間で済ますようにすること // // -------------------------------------------------- // 18F26K22 Interrupt Routine // -------------------------------------------------- // 割り込みはすべてinterrupt宣言されたこの関数が呼ばれる static void interrupt interrupt_18F26K22() { // 全割り込みを禁止(=0) (Global Interrupt Enable bit ... INTCON) INTCONbits.GIE = 0; // ---------------------------------------- // 赤外線センサー読み取りサンプリングタイマー(デフォルト:100ms) // ---------------------------------------- // タイマー0割り込み(=1)なら (Timer0 Overflow Interrupt Flag bit ... INTCON) if (INTCONbits.TMR0IF == 1) { // タイマー値設定 TMR0H = timer0_h; TMR0L = timer0_l; // タイマー割り込みフラグ初期化 INTCONbits.TMR0IF = 0; // PORT_IR_RX の値を取得して状態により処理分岐 // 赤外線センサーが検知中なら if (PORT_IR_RX == 0) { // 赤外線センサーカウンタに加算 pir_sensor_count += 1; // リザルトLEDを点灯 PORT_RESULT_LED = LED_ON; } // 未検知なら else { // リザルトLEDを消灯 PORT_RESULT_LED = LED_OFF; } } // ---------------------------------------- // MSSP1割り込み処理 (Rev.1の18F26K22_I2C.cを参照すること // ---------------------------------------- // MSSP割り込み(=1)なら (Synchronous Serial Port (MSSP) Interrupt Flag bit ... PIR1) if (PIR1bits.SSP1IF == 1) { // ステータスLEDを点灯 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を点灯…しない、PIR検知で光らせたいため /// PORT_RESULT_LED = LED_ON; // SSP1BUFを空読みして temp_buffer = SSP1BUF; // 受信バッファ位置を初期化 rx_count = 0; // I2Cステータス 0:待機状態 1:データ受信中 10:データ受信完了 i2c_status = 1; // SCLをリリースしてマスターにデータの送信を許可する SSP1CON1bits.CKP1 = 1; // リザルトLEDを消灯…しない、PIR検知で光らせたいため /// PORT_RESULT_LED = LED_OFF; } // SSP1ステータスが、データ(D/A=1)で、かつマスターがスレーブへ送信(R/W=0)、かつバッファに何かある(BF=1)なら else if (reg_SSP1STAT == 0b00100001) { // リザルトLEDを点灯…しない、PIR検知で光らせたいため /// 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 *)tx_buffer; // 要求コマンドがモジュールデータ要求(0x03:テスト時、0x11:正式)なら if ((rx_buffer[1] == 0x03) || (rx_buffer[1] == 0x11)) { // フォーマットの指定に基づいて現在の値から返すデータを生成する get_pirdata(rx_buffer[0], gvc_i2c_message->data); } else { // コマンドエラーを設定 sprintf(gvc_i2c_message->data, "COMMAND ERROR!?, %02x", temp_buffer); } // メッセージフォーマットに基づいて設定する 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を消灯…しない、PIR検知で光らせたいため /// PORT_RESULT_LED = LED_OFF; } // アドレス(D/A=0)で、かつマスターがスレーブから受信(R/W=1)、かつバッファに何かある(BF=1)な else if (reg_SSP1STAT == 0b00000101) { // リザルトLEDを点灯…しない、PIR検知で光らせたいため /// 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を消灯…しない、PIR検知で光らせたいため /// PORT_RESULT_LED = LED_OFF; } // データ(D/A=1)で、かつマスターがスレーブから受信(R/W=1)、かつバッファが空(BF=0)なら else if (reg_SSP1STAT == 0b00100100) { // リザルトLEDを点灯…しない、PIR検知で光らせたいため /// 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を消灯…しない、PIR検知で光らせたいため /// PORT_RESULT_LED = LED_OFF; } // これら以外は else { // SSP1BUFを空読みして temp_buffer = SSP1BUF; // SCLをリリースしてマスターに次の命令を促す SSP1CON1bits.CKP1 = 1; } // ステータスLEDを消灯 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) { // シリアル1受信割り込みクリア(=0)…は1バイト受信すれば自動的にクリアされるので必要ない ← うそ、要るみたい、時々ちゃんと初期化しない 2013.12.03 PIR1bits.RC1IF = 0; // 受信ステータスを取得 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; } // ほんとはここで、受信バッファポインタ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(); // ---------------------------------------- // これより下に、個別の設定を記述 // ---------------------------------------- // LED Brink led_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:データ受信完了 // 赤外線センサーカウンタを初期化 pir_sensor_count = 0; // タイマー値を初期化 init_timer_18F26K22(); // ---------------------------------------- // 個別設定終了 // ---------------------------------------- // LED Brink led_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_crlf(); // LED Brink led_brink(3); // ------------------------------ // リモコン読み取りタイムアウトタイマースタート // ------------------------------ // タイマー値設定 TMR0H = timer0_h; TMR0L = timer0_l; // タイマー割り込みフラグ初期化 INTCONbits.TMR0IF = 0; // タイマー0割り込み許可(=1) (Timer0 Overflow Interrupt Enable bit ... INTCON) INTCONbits.TMR0IE = 1; // タイマー割り込み開始!! T0CON |= 0b10000000; // ------------------------------ // ここまで // ------------------------------ // メインループ while(1) { // シリアルバッファに未読データがないならスルー if (serial_rcvptr == serial_readptr) { } // あるなら else { // 受信バッファから一文字取得 rcv_data = rcv_serialdata(); while(TX1IF == 0); // 送信可能になるまで待つ TXREG1 = rcv_data; // 送信 send_crlf(); send_strdata("pir_sensor_count = "); send_intdata(pir_sensor_count); send_crlf(); } } }