// -------------------------------------------------- // Global Versatile Controler http://www.gvc-on.net/ // -------------------------------------------------- // -------------------------------------------------- // Revision Memo (Y.M.D Editor/Memo) // -------------------------------------------------- // // 2013.05.08 T.Kabu // GVC Rev.2としてのもろもろを定義 // //--------------------------------------------------- // Include Header //--------------------------------------------------- // ---------------------------------------- // Standard Header // ---------------------------------------- #include <xc.h> #include <plib.h> #include <htc.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> // CHAR_BIT // ---------------------------------------- // User Header // ---------------------------------------- // PIC Parameter define and initialize #include "pic_init.h" // GVC Parameter define and initialize #include "gvc_init.h" // -------------------------------------------------- // Variable Param // -------------------------------------------------- // CRC-8-CCITTテーブルの配列 /* static unsigned char CRC8Table[ 256 ] = { 0x00, 0x8D, 0x97, 0x1A, 0xA3, 0x2E, 0x34, 0xB9, 0xCB, 0x46, 0x5C, 0xD1, 0x68, 0xE5, 0xFF, 0x72, 0x1B, 0x96, 0x8C, 0x01, 0xB8, 0x35, 0x2F, 0xA2, 0xD0, 0x5D, 0x47, 0xCA, 0x73, 0xFE, 0xE4, 0x69, 0x36, 0xBB, 0xA1, 0x2C, 0x95, 0x18, 0x02, 0x8F, 0xFD, 0x70, 0x6A, 0xE7, 0x5E, 0xD3, 0xC9, 0x44, 0x2D, 0xA0, 0xBA, 0x37, 0x8E, 0x03, 0x19, 0x94, 0xE6, 0x6B, 0x71, 0xFC, 0x45, 0xC8, 0xD2, 0x5F, 0x6C, 0xE1, 0xFB, 0x76, 0xCF, 0x42, 0x58, 0xD5, 0xA7, 0x2A, 0x30, 0xBD, 0x04, 0x89, 0x93, 0x1E, 0x77, 0xFA, 0xE0, 0x6D, 0xD4, 0x59, 0x43, 0xCE, 0xBC, 0x31, 0x2B, 0xA6, 0x1F, 0x92, 0x88, 0x05, 0x5A, 0xD7, 0xCD, 0x40, 0xF9, 0x74, 0x6E, 0xE3, 0x91, 0x1C, 0x06, 0x8B, 0x32, 0xBF, 0xA5, 0x28, 0x41, 0xCC, 0xD6, 0x5B, 0xE2, 0x6F, 0x75, 0xF8, 0x8A, 0x07, 0x1D, 0x90, 0x29, 0xA4, 0xBE, 0x33, 0xD8, 0x55, 0x4F, 0xC2, 0x7B, 0xF6, 0xEC, 0x61, 0x13, 0x9E, 0x84, 0x09, 0xB0, 0x3D, 0x27, 0xAA, 0xC3, 0x4E, 0x54, 0xD9, 0x60, 0xED, 0xF7, 0x7A, 0x08, 0x85, 0x9F, 0x12, 0xAB, 0x26, 0x3C, 0xB1, 0xEE, 0x63, 0x79, 0xF4, 0x4D, 0xC0, 0xDA, 0x57, 0x25, 0xA8, 0xB2, 0x3F, 0x86, 0x0B, 0x11, 0x9C, 0xF5, 0x78, 0x62, 0xEF, 0x56, 0xDB, 0xC1, 0x4C, 0x3E, 0xB3, 0xA9, 0x24, 0x9D, 0x10, 0x0A, 0x87, 0xB4, 0x39, 0x23, 0xAE, 0x17, 0x9A, 0x80, 0x0D, 0x7F, 0xF2, 0xE8, 0x65, 0xDC, 0x51, 0x4B, 0xC6, 0xAF, 0x22, 0x38, 0xB5, 0x0C, 0x81, 0x9B, 0x16, 0x64, 0xE9, 0xF3, 0x7E, 0xC7, 0x4A, 0x50, 0xDD, 0x82, 0x0F, 0x15, 0x98, 0x21, 0xAC, 0xB6, 0x3B, 0x49, 0xC4, 0xDE, 0x53, 0xEA, 0x67, 0x7D, 0xF0, 0x99, 0x14, 0x0E, 0x83, 0x3A, 0xB7, 0xAD, 0x20, 0x52, 0xDF, 0xC5, 0x48, 0xF1, 0x7C, 0x66, 0xEB, }; */ __EEPROM_DATA( 0x00, 0x8D, 0x97, 0x1A, 0xA3, 0x2E, 0x34, 0xB9); __EEPROM_DATA( 0xCB, 0x46, 0x5C, 0xD1, 0x68, 0xE5, 0xFF, 0x72); __EEPROM_DATA( 0x1B, 0x96, 0x8C, 0x01, 0xB8, 0x35, 0x2F, 0xA2); __EEPROM_DATA( 0xD0, 0x5D, 0x47, 0xCA, 0x73, 0xFE, 0xE4, 0x69); __EEPROM_DATA( 0x36, 0xBB, 0xA1, 0x2C, 0x95, 0x18, 0x02, 0x8F); __EEPROM_DATA( 0xFD, 0x70, 0x6A, 0xE7, 0x5E, 0xD3, 0xC9, 0x44); __EEPROM_DATA( 0x2D, 0xA0, 0xBA, 0x37, 0x8E, 0x03, 0x19, 0x94); __EEPROM_DATA( 0xE6, 0x6B, 0x71, 0xFC, 0x45, 0xC8, 0xD2, 0x5F); __EEPROM_DATA( 0x6C, 0xE1, 0xFB, 0x76, 0xCF, 0x42, 0x58, 0xD5); __EEPROM_DATA( 0xA7, 0x2A, 0x30, 0xBD, 0x04, 0x89, 0x93, 0x1E); __EEPROM_DATA( 0x77, 0xFA, 0xE0, 0x6D, 0xD4, 0x59, 0x43, 0xCE); __EEPROM_DATA( 0xBC, 0x31, 0x2B, 0xA6, 0x1F, 0x92, 0x88, 0x05); __EEPROM_DATA( 0x5A, 0xD7, 0xCD, 0x40, 0xF9, 0x74, 0x6E, 0xE3); __EEPROM_DATA( 0x91, 0x1C, 0x06, 0x8B, 0x32, 0xBF, 0xA5, 0x28); __EEPROM_DATA( 0x41, 0xCC, 0xD6, 0x5B, 0xE2, 0x6F, 0x75, 0xF8); __EEPROM_DATA( 0x8A, 0x07, 0x1D, 0x90, 0x29, 0xA4, 0xBE, 0x33); __EEPROM_DATA( 0xD8, 0x55, 0x4F, 0xC2, 0x7B, 0xF6, 0xEC, 0x61); __EEPROM_DATA( 0x13, 0x9E, 0x84, 0x09, 0xB0, 0x3D, 0x27, 0xAA); __EEPROM_DATA( 0xC3, 0x4E, 0x54, 0xD9, 0x60, 0xED, 0xF7, 0x7A); __EEPROM_DATA( 0x08, 0x85, 0x9F, 0x12, 0xAB, 0x26, 0x3C, 0xB1); __EEPROM_DATA( 0xEE, 0x63, 0x79, 0xF4, 0x4D, 0xC0, 0xDA, 0x57); __EEPROM_DATA( 0x25, 0xA8, 0xB2, 0x3F, 0x86, 0x0B, 0x11, 0x9C); __EEPROM_DATA( 0xF5, 0x78, 0x62, 0xEF, 0x56, 0xDB, 0xC1, 0x4C); __EEPROM_DATA( 0x3E, 0xB3, 0xA9, 0x24, 0x9D, 0x10, 0x0A, 0x87); __EEPROM_DATA( 0xB4, 0x39, 0x23, 0xAE, 0x17, 0x9A, 0x80, 0x0D); __EEPROM_DATA( 0x7F, 0xF2, 0xE8, 0x65, 0xDC, 0x51, 0x4B, 0xC6); __EEPROM_DATA( 0xAF, 0x22, 0x38, 0xB5, 0x0C, 0x81, 0x9B, 0x16); __EEPROM_DATA( 0x64, 0xE9, 0xF3, 0x7E, 0xC7, 0x4A, 0x50, 0xDD); __EEPROM_DATA( 0x82, 0x0F, 0x15, 0x98, 0x21, 0xAC, 0xB6, 0x3B); __EEPROM_DATA( 0x49, 0xC4, 0xDE, 0x53, 0xEA, 0x67, 0x7D, 0xF0); __EEPROM_DATA( 0x99, 0x14, 0x0E, 0x83, 0x3A, 0xB7, 0xAD, 0x20); __EEPROM_DATA( 0x52, 0xDF, 0xC5, 0x48, 0xF1, 0x7C, 0x66, 0xEB); // -------------------------------------------------- // Function prototype // -------------------------------------------------- // -------------------------------------------------- // Sub Routine (gvc_init.c) // -------------------------------------------------- // ------------------------------ // STATUS LED Brink (ON=300ms/OFF=100ms) // ------------------------------ void led_status_brink(char brink) { char count; // ステータスLEDを点灯(300ms)/消灯(100ms)を繰り返す for (count = 0; count < brink; count ++) { PORT_STATUS_LED = LED_ON; Delay_10ms(30); // 300ms待つ PORT_STATUS_LED = LED_OFF; Delay_10ms(10); // 100ms待つ } } // ------------------------------ // RESULT LED Brink (ON=300ms/OFF=100ms) // ------------------------------ void led_result_brink(char brink) { char count; // ステータスLEDを点灯(300ms)/消灯(100ms)を繰り返す for (count = 0; count < brink; count ++) { PORT_RESULT_LED = LED_ON; Delay_10ms(30); // 300ms待つ PORT_RESULT_LED = LED_OFF; Delay_10ms(10); // 100ms待つ } } // ------------------------------ // STATUS/RESULT LED Brink (ON=300ms/OFF=100ms) // ------------------------------ void led_brink(char brink) { char count; // ステータスLED/リザルトLEDを点灯(300ms)/消灯(100ms)を繰り返す for (count = 0; count < brink; count ++) { // ステータスLEDを点滅 led_status_brink(1); // リザルトLEDを点滅 led_result_brink(1); } } // ------------------------------ // LED Brink (Start Up Sign) // ------------------------------ void led_brink3() { // ---------------------------------------- // モニターLEDを点灯(始動の合図) // ---------------------------------------- PORT_STATUS_LED = LED_ON; PORT_RESULT_LED = LED_ON; Delay_10ms(100); // 1000ms待つ PORT_STATUS_LED = LED_OFF; PORT_RESULT_LED = LED_OFF; Delay_10ms(10); // 100ms待つ // ステータスLEDを点滅 led_status_brink(1); // リザルトLEDを点滅 led_result_brink(1); // ステータスLEDを点滅 led_status_brink(1); // リザルトLEDを点滅 led_result_brink(1); PORT_STATUS_LED = LED_ON; PORT_RESULT_LED = LED_ON; Delay_10ms(100); // 1000ms待つ PORT_STATUS_LED = LED_OFF; PORT_RESULT_LED = LED_OFF; Delay_10ms(10); // 100ms待つ } // ------------------------------ // LED light // ------------------------------ void led_light(char long_light, char short_light) { // 長時間点灯ループ while (long_light > 0) { //モニターLEDを点灯 PORT_RESULT_LED = LED_ON; Delay_10ms(50); // モニターLEDを消灯 PORT_RESULT_LED = LED_OFF; Delay_10ms(10); // long_lightを-1 long_light --; } // 短時間点灯ループ while (short_light > 0) { //モニターLEDを点灯 PORT_RESULT_LED = LED_ON; Delay_10ms(20); // モニターLEDを消灯 PORT_RESULT_LED = LED_OFF; Delay_10ms(10); // short_lightを-1 short_light --; } Delay_10ms(20); } // ------------------------------ // CRC8テーブルから計算 // ------------------------------ unsigned char GetCRC8( const void *buff, size_t size ) { unsigned char *data = (unsigned char *)buff; unsigned char crc8 = 0x00; while ( 1 ) { if (size == 0) { break; } else { /// crc8 = CRC8Table[ crc8 ^ *data ]; crc8 = EEPROM_READ( crc8 ^ *data ); data++; size--; } } return crc8; } // ------------------------------ // Send CR // ------------------------------ void send_cr(void) { while(TX1IF == 0); // 送信可能になるまで待つ TXREG1 = 0x0d; // CR送信する } // ------------------------------ // Send LF // ------------------------------ void send_lf(void) { while(TX1IF == 0); // 送信可能になるまで待つ TXREG1 = 0x0a; // LF送信する } // ------------------------------ // Send CR/LF // ------------------------------ void send_crlf(void) { send_cr(); send_lf(); } // ------------------------------ // Send STR DATA // ------------------------------ void send_strdata(const char * strdata) { while ( 1 ) { if (*strdata == 0) { break; } else { while(TX1IF == 0); // 送信可能になるまで待つ TXREG1 = *strdata; strdata++; } } } // ------------------------------ // Send intdata // ------------------------------ void send_intdata(int int_data) { // 1バイトデータをHEXに変換して送信 char str_data[7]; int str_len; int str_pos = 0; str_len = sprintf(str_data, "%d", int_data); while(str_len) { while(TX1IF == 0); // 送信可能になるまで待つ TXREG1 = str_data[str_pos]; // 一文字送信 str_pos ++; // ポインタを一つ進める str_len --; // 文字列長を-1する } } // ------------------------------ // Send DATA // ------------------------------ void send_serial(const char * data, int data_len) { while (data_len) { while(TX1IF == 0); // 送信可能になるまで待つ TXREG1 = *data; data++; data_len--; } } // ------------------------------ // Send hexdata // ------------------------------ void send_hexdata(char char_data) { // 1バイトデータをHEXに変換して送信 char hex_data[3]; // itoa((char *)hex_data, (int)char_data, 16); sprintf((char *)hex_data, "%0.2X", (int)char_data); // Cだとこうだっけか…!? while(TX1IF == 0); // 送信可能になるまで待つ TXREG1 = hex_data[0]; // CR送信する while(TX1IF == 0); // 送信可能になるまで待つ TXREG1 = hex_data[1]; // LF送信する } // ------------------------------ // I2C wait Clear buffer // ------------------------------ void i2c_waitClearbuffer() { // I2Cがアイドル状態でないか、送信状態だったり受信バッファに何かある間は待つ while((SSP1CON2 & 0b00011111) | (SSP1STAT & 0b00000101)); } // ------------------------------ // I2C begin Transmission // ------------------------------ void i2c_beginTransmission() { // I2C wait Clear buffer i2c_waitClearbuffer(); // I2C START CONDITION SSP1CON2bits.SEN = 1 ; } // ------------------------------ // I2C end Transmission // ------------------------------ void i2c_endTransmission() { // I2C wait Clear buffer i2c_waitClearbuffer(); // I2C STOP CONDITION SSP1CON2bits.PEN = 1 ; } // ------------------------------ // I2C write // ------------------------------ int i2c_write(char target_addr, char * data, int data_length) { unsigned int data_pos = -1; // I2C begin Transmission i2c_beginTransmission(); // I2C wait Clear buffer i2c_waitClearbuffer(); // とりあえずありえないダミーデータを設定 reg_SSP1STAT = 0b11111111; // アドレスを送信 R/W=0 SSP1BUF = target_addr << 1; // reg_SSP1STATが変化するまで待つ while(reg_SSP1STAT == 0b11111111); // もしACKSTATUSがACK(=0)なら if (SSP1CON2bits.ACKSTAT == 0) { // dataを1バイトずつ送信する for (data_pos = 0; data_pos < data_length ; data_pos ++) { // I2C wait Clear buffer i2c_waitClearbuffer(); // とりあえずありえないダミーデータを設定 reg_SSP1STAT = 0b11111111; // データを送信 SSP1BUF = (char)data[data_pos]; // reg_SSP1STATが変化するまで待つ while(reg_SSP1STAT == 0b11111111); // もしACKSTATUSがNACKではない(==0:ACK)なら if (SSP1CON2bits.ACKSTAT == 0) { // なにもしない } // そうではなくACKSTATUSがNACKなら else { // スレーブがNACKを返してきた場合の処理 // 呼び出し元にエラーステータスを返した方がいい。それとも再処理します? return data_pos; } } } // I2C end Transmission i2c_endTransmission(); return data_pos; } // ------------------------------ // I2C read // ------------------------------ int i2c_read(char target_addr, char * data, int data_length) { unsigned int data_pos = -1; // I2C begin Transmission i2c_beginTransmission(); // I2C wait Clear buffer i2c_waitClearbuffer(); // とりあえずありえないダミーデータを設定 reg_SSP1STAT = 0b11111111; // アドレスを送信 R/W=1 SSP1BUF = (char)((target_addr << 1) + 1); // reg_SSP1STATが変化するまで待つ while(reg_SSP1STAT == 0b11111111); // もしACKSTATUSがACK(=0)なら if (SSP1CON2bits.ACKSTAT == 0) { // dataを1バイトずつ受信する for (data_pos = 0; data_pos < data_length ; data_pos++) { // I2C wait Clear buffer i2c_waitClearbuffer(); // 受信を許可する SSP1CON2bits.RCEN = 1; // I2Cがアイドル状態でないか、送信状態だったり受信バッファに何かくるまで待つ while((SSP1CON2 & 0b00011111) | (SSP1STAT & 0b00000100)); // データを受信 data[data_pos] = SSP1BUF; // I2C wait Clear buffer i2c_waitClearbuffer(); // 次のデータを要求するのでACKデータはACK(=0)を設定 SSP1CON2bits.ACKDT = 0 ; // ACKデータ(ACKDT)を返す SSP1CON2bits.ACKEN = 1 ; } // I2C wait Clear buffer i2c_waitClearbuffer(); // 受信を許可する SSP1CON2bits.RCEN = 1; // I2Cがアイドル状態でないか、送信状態だったり受信バッファに何かくるまで待つ while((SSP1CON2 & 0b00011111) | (SSP1STAT & 0b00000100)); // データを受信 data[data_pos] = SSP1BUF; // データポインタを加算 data_pos++; // I2C wait Clear buffer i2c_waitClearbuffer(); // 次のデータは要らないのでACKデータはNOACK(=1)を設定 SSP1CON2bits.ACKDT = 1; // ACKデータ(ACKDT)を返す SSP1CON2bits.ACKEN = 1 ; } // I2C end Transmission i2c_endTransmission(); return data_pos; } // ------------------------------ // I2C Scan // ------------------------------ char i2c_slave_check(unsigned char target_addr) { char result; // 結果 // 指定されたターゲットからACKが帰ってくるかどうかを確認 if ((target_addr > 0x7f) | (target_addr == 0)) { return '-'; } // I2C begin Transmission i2c_beginTransmission(); // I2C wait Clear buffer i2c_waitClearbuffer(); // とりあえずありえないダミーデータを設定 reg_SSP1STAT = 0b11111111; // アドレスを送信 R/W=0 SSP1BUF = target_addr << 1; // reg_SSP1STATが変化するまで待つ while(reg_SSP1STAT == 0b11111111); // ターゲットスレーブからACKを受信したら if (SSP1CON2bits.ACKSTAT == 0) { // よかったよかった result = 'o'; } // ACKではなかったら else { // 再処理します? result = 'x'; } // I2C end Transmission i2c_endTransmission(); // 結果を返して終わる return result; }