TOP > MPLAB XC8編(PIC16F88) > I2CでEEPROMを使う(PIC16F88 XC8) > ソース
I2CでEEPROMを使う(ソース)
(PIC16F88 XC8)
作成日2012.6.10 |
以下のソースを取り込んで、コンパイル→PIC書き込み→実行して下さい。
// ========================== ここから ============================== //ファイル名 I2C_EEPROM1.c //作成日 2010.9.12 //更新日 2012.6.9 //作成者 mit.ueno //バージョン 1.1 //コンパイラ MPLAB XC8 //PIC PIC16F88 //クロック 8MHz(INTIO) // //概要 // EEPROM(AT24C1024B)の動作確認 // I2C使用(マスタモード)ファームウェア制御 // SCL/SDAの無通信時の状態 // SCL output,1 // SDA input,1 // // NOP() の数は20MHz動作前提 // //使用ポート // RB1:EEPROM(SDA) // RB4:EEPROM(SCL) // // RB2:LCD(RS) // RB3:LCD(E) // RA0:LCD(DB4) // RA1:LCD(DB5) // RA2:LCD(DB6) // RA3:LCD(DB7) // // LCD_V0 : 10KΩVRでGND // LCD_R/W : GND // LCD_DB0-3: open // // LCD表示形式 // 0123456789abcdef // W xxxxxxxxxxxxxx // R xxxxxxxxxxxxxx // // EEPROM_A1 : GND // EEPROM_A2 : GND // EEPROM_WP : GND // #include "pic.h" #define LCD_E RB3 #define LCD_RS RB2 #define I2C_SCL RB4 #define I2C_SDA RB1 #define I2C_SDA_TRIS TRISB1 // EEPROMアドレス(I2Cフォーマット) #define EE_dev_addr 0xA0 // EEPROMアドレス #define EE_P0_0 0x00 // EEPROMメモリアドレス最上位ビット:0 #define EE_P0_1 0x02 // EEPROMメモリアドレス最上位ビット:1 static void pic_init(); static void I2C_start(); static void I2C_send(unsigned char); static unsigned char I2C_ackchk(); static void I2C_acksnd(); static void I2C_nacksnd(); static unsigned char I2C_rcv(); static void I2C_snd_char(unsigned char EE_P0 ,unsigned char addr1 ,unsigned char addr2 ,unsigned char send_data); static unsigned char I2C_rcv_char(unsigned char EE_P0 ,unsigned char addr1 ,unsigned char addr2); static void I2C_stop(); static void LCD_init(); static void LCD_ival(); static void LCD_cmd(unsigned char); static void LCD_data(unsigned char); static void LCD_hex(unsigned char, unsigned char); static void LCD_send4(unsigned char); static void wait_50us(); static void wait_1ms(); static void wait_ms(unsigned char); __CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_OFF & IESO_OFF & LVP_OFF); const unsigned char hex_tbl[16] = "0123456789ABCDEF"; // ==================== メイン処理 =========================== main() { unsigned char c; pic_init(); // PICの初期化 LCD_init(); // LCDの初期化 LCD_ival(); // LCD初期表示 // EEPROMに2バイト書き込む。そのデータをLCDに表示。 LCD_hex(0x82, 0xA5); I2C_snd_char(EE_P0_0 ,0x00 ,0x00 ,0xA5); wait_ms(5); LCD_hex(0x84, 0x5B); I2C_snd_char(EE_P0_1 ,0xFF ,0x00 ,0x5B); wait_ms(5); // EEPROMより2バイト読み込み、そのデータをLCDに表示。 c = I2C_rcv_char(EE_P0_0 ,0x00 ,0x00); // read LCD_hex(0xC2, c); c = I2C_rcv_char(EE_P0_1 ,0xFF ,0x00); // read LCD_hex(0xC4, c); while(1) {} } // ==================== PICの初期化 =========================== static void pic_init() { OSCCON = 0x70; // INTOSC 8MHz ANSEL = 0x00; // AN未使用 TRISA = 0xF0; // RA0-3:out TRISB = 0xE3; // RB2-4:out SDAは通常input(開放) PORTA = 0x00; PORTB = 0x12; // SCL=1,SDA=1 // SSPCON = 0x2B; // SSP enable & I2C Firmware Controlled Master mode // この設定をするとうまく動作しない return; } // ==================== I2C Start ============================= static void I2C_start() { I2C_SDA = 1; I2C_SDA_TRIS = 0; // output I2C_SCL = 1; // SCL high NOP(); NOP(); NOP(); NOP(); I2C_SDA = 0; // SDA low : start NOP(); NOP(); NOP(); NOP(); I2C_SCL = 0; // SCL low return; } // ==================== I2C Stop ============================== static void I2C_stop() { I2C_SDA = 0; // SDA low I2C_SDA_TRIS = 0; // output I2C_SCL = 1; // SCL high NOP(); NOP(); NOP(); NOP(); I2C_SDA_TRIS = 1; // input(SDA high) : stop return; } // ==================== I2C Send ============================== static void I2C_send(unsigned char send_data) { unsigned char i2c_data,i; I2C_SDA_TRIS = 0; // SDA output i2c_data = send_data; for (i=8 ; i>0 ; i--) { if (i2c_data & 0x80) { // ビットセット I2C_SDA = 1; } else { I2C_SDA = 0; } i2c_data = i2c_data << 1; // next bit set I2C_SCL = 1; // 1ビット送信 NOP(); NOP(); NOP(); NOP(); I2C_SCL = 0; } I2C_SDA_TRIS = 1; // SDA input return; } // ==================== I2C Recive ============================ static unsigned char I2C_rcv() { unsigned char i2c_data,i; I2C_SDA_TRIS = 1; // SDA input for (i=8 ; i>0 ; i--) { NOP(); I2C_SCL = 1; // 1ビット受信 i2c_data = i2c_data <<1; if (PORTB & 0x02) { i2c_data = i2c_data | 0x01; } else { i2c_data = i2c_data & 0xFE; } I2C_SCL = 0; } return(i2c_data); } // ==================== I2C Send char ========================== static void I2C_snd_char(unsigned char ee_p0 ,unsigned char addr1 ,unsigned char addr2 ,unsigned char send_data) { I2C_start(); I2C_send(EE_dev_addr | ee_p0); // スレーブアドレス & Write if (I2C_ackchk()) { LCD_data('4'); } I2C_send(addr1); // 書き込みアドレス1 if (I2C_ackchk()) { LCD_data('5'); } I2C_send(addr2); // 書き込みアドレス2 if (I2C_ackchk()) { LCD_data('6'); } I2C_send(send_data); // 書き込み if (I2C_ackchk()) { LCD_data('7'); } I2C_stop(); return; } // ==================== I2C Recive char ======================== static unsigned char I2C_rcv_char(unsigned char ee_p0 ,unsigned char addr1 ,unsigned char addr2) { unsigned char c; I2C_start(); I2C_send(EE_dev_addr | ee_p0); // スレーブアドレス & Write if (I2C_ackchk()) { LCD_data('8'); } I2C_send(addr1); // 書き込みアドレス1 if (I2C_ackchk()) { LCD_data('9'); } I2C_send(addr2); // 書き込みアドレス2 if (I2C_ackchk()) { LCD_data('A'); } I2C_start(); I2C_send(EE_dev_addr | ee_p0 | 0x01); // スレーブアドレス & Read if (I2C_ackchk()) { LCD_data('B'); } c = I2C_rcv(); I2C_nacksnd(); I2C_stop(); return(c); } // ==================== I2C ACK check ========================= static unsigned char I2C_ackchk() { unsigned char i2c_data; I2C_SCL = 1; // ACKビット受信 NOP(); i2c_data = PORTB & 0x02; I2C_SCL = 0; return(i2c_data); } // ==================== I2C ACK send ========================== static void I2C_acksnd() { I2C_SDA = 0; // ACK I2C_SDA_TRIS = 0; // SDA output NOP(); I2C_SCL = 1; // ACK送信 NOP(); NOP(); NOP(); NOP(); I2C_SCL = 0; I2C_SDA_TRIS = 1; // SDA input return; } // ==================== I2C NACK send ========================= static void I2C_nacksnd() { I2C_SDA = 1; // NACK I2C_SDA_TRIS = 0; // SDA output I2C_SCL = 1; // NACK送信 NOP(); I2C_SCL = 0; NOP(); I2C_SDA_TRIS = 1; // SDA input return; } // ==================== LCD 初期表示 ========================== static void LCD_ival() { // 0123456789abcdef // W // R LCD_cmd(0x80); LCD_data('W'); LCD_cmd(0xC0); LCD_data('R'); return; } // ==================== LCD 4bit 送信 ========================= static void LCD_send4(unsigned char c) { PORTA = (PORTA & 0xF0) | c; LCD_E = 1; NOP(); LCD_E = 0; return; } // ==================== LCDコマンドWRITE ================= static void LCD_cmd(unsigned char cmd) { LCD_RS = 0; PORTA = (PORTA & 0xF0) | ((cmd >>4) & 0x0F); LCD_E = 1; // 上位4ビット書き込み NOP(); LCD_E = 0; PORTA = (PORTA & 0xF0) | (cmd & 0x0F); LCD_E = 1; // 下位4ビット書き込み NOP(); LCD_E = 0; wait_50us(); return; } // ==================== LCDデータWRITE ================= static void LCD_data(unsigned char cmd) { LCD_RS = 1; PORTA = (PORTA & 0xF0) | ((cmd >>4) & 0x0F); LCD_E = 1; // 上位4ビット書き込み NOP(); LCD_E = 0; PORTA = (PORTA & 0xF0) | (cmd & 0x0F); LCD_E = 1; // 下位4ビット書き込み NOP(); LCD_E = 0; wait_50us(); return; } // =============== 1バイトを16進数でLCDに出力 ========== static void LCD_hex(unsigned char addr, unsigned char ad) { LCD_cmd(addr); LCD_data(hex_tbl[ad>>4 & 0x0F]); LCD_data(hex_tbl[ad & 0x0F]); } // ==================== LCDの初期化 =========================== static void LCD_init() { wait_ms(15); LCD_E = 0; LCD_RS = 0; LCD_send4(0x03); // DB4-7に'3'を出力(8bitモードに)@ wait_ms(5); LCD_send4(0x03); // DB4-7に'3'を出力(8bitモードに)A wait_ms(1); LCD_send4(0x03); // DB4-7に'3'を出力(8bitモードに)B wait_ms(1); LCD_send4(0x02); // DB4-7に'2'を出力(4bitモードに) wait_ms(1); // ここからは4bitモードで、Busyフラグが使える LCD_cmd(0x28); // DL=0:4bit ,N=1:2lines ,F=0:5*7dot LCD_cmd(0x08); // Display off LCD_cmd(0x0C); // Display on ,cursor on ,no blink LCD_cmd(0x06); // Entry mode (Inc ,No Shift) LCD_cmd(0x01); // Clear Display wait_ms(2); return; } // ==================== 50μSウェイトルーチン ================= static void wait_50us() { unsigned char i; for (i=32 ; i>0 ; i--) {} return; } // ==================== 1mSウェイトルーチン ================= static void wait_1ms() { unsigned char i; for (i=179 ; i>0 ; i--) { NOP(); NOP(); NOP(); } return; } // ==================== 1mS×ms ウェイトルーチン ============= static void wait_ms(unsigned char ms) { unsigned char c; for (c=ms ; c>0 ; c--) { wait_1ms(); } return; } // ========================== ここまで ==============================