TOP > MPLAB XC8編(PIC16F886) > I2CでEEPROMを使う(PIC16F886 XC8) > ソース
I2CでEEPROMを使う(ソース)
(PIC16F886 XC8)
作成日2012.6.24 |
以下のソースを取り込んで、コンパイル→PIC書き込み→実行して下さい。
// ========================== ここから ============================== //ファイル名 I2C_EEPROM.c //作成日 2010.10.9 //更新日 2012.6.23 //作成者 mit.ueno //バージョン 1.1 //コンパイラ MPLAB XC8 //PIC PIC16F886 //クロック 8MHz(INTIO) // //概要 // EEPROMの動作確認 // I2C使用(マスタモード) // //使用ポート // RC3:RTC(SCL) // RC4:RTC(SDA) // // RC6:LCD(RS) // RC7:LCD(E) // RB4:LCD(DB4) // RB5:LCD(DB5) // RB6:LCD(DB6) // RB7:LCD(DB7) // // LCD_V0 : 350ΩでGND // LCD_R/W : GND // LCD_DB0-3: open // #include "pic.h" #define LCD_E RC7 #define LCD_RS RC6 #define I2C_SCL RC3 #define I2C_SDA RC4 #define I2C_SDA_TRIS TRISC4 #define EE_dev_addr 0xA0 #define EE_P0_0 0x00 #define EE_P0_1 0x02 static void pic_init(); static void I2C_start(); static void I2C_restart(); 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_INTRC_NOCLKOUT & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_OFF & IESO_OFF & LVP_OFF); const unsigned char hex_tbl[16] = "0123456789ABCDEF"; // ==================== メイン処理 =========================== main() { unsigned char i; unsigned char c; pic_init(); // PICの初期化 LCD_init(); // LCDの初期化 LCD_ival(); // LCD初期表示 c = 0xAA; LCD_hex(0x82, c); I2C_snd_char(EE_P0_0 ,0xA1 ,0x00 ,c); wait_ms(5); c = 0xBB; LCD_hex(0x86, c); I2C_snd_char(EE_P0_1 ,0xA1 ,0x00 ,c); wait_ms(5); c = I2C_rcv_char(EE_P0_0 ,0xA1 ,0x00); // read LCD_hex(0xC2, c); c = I2C_rcv_char(EE_P0_1 ,0xA1 ,0x00); // read LCD_hex(0xC6, c); while(1) {} } // ==================== PICの初期化 =========================== static void pic_init() { OSCCON = 0x70; // INTOSC 8MHz ANSEL = 0x00; // AN未使用 TRISB = 0x0F; // RB4-7:out TRISC = 0x3F; // RC3,6-7:out SDA/SCL:input PORTB = 0x00; PORTC = 0x00; SSPCON = 0x28; // SSP enable & I2C Master mode, clock = FOSC / (4 * (SSPADD+1)) SSPADD = 0x02; // 0x00だと動作しない return; } // ==================== I2C Start ============================= static void I2C_start() { SEN = 1; while (SEN) {} return; } // ==================== I2C Start Repeat ====================== static void I2C_restart() { SSPIF = 0; RSEN = 1; while (RSEN) {} return; } // ==================== I2C Stop ============================== static void I2C_stop() { SSPIF = 0; PEN = 1; while (PEN) {} SSPIF = 0; return; } // ==================== I2C Send ============================== static void I2C_send(unsigned char send_data) { SSPIF = 0; SSPBUF = send_data; while (!SSPIF) {} return; } // ==================== I2C Recive ============================ static unsigned char I2C_rcv() { SSPIF = 0; RCEN = 1; while (RCEN) {} return(SSPBUF); } // ==================== 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; if (ACKSTAT) { i2c_data = 0xFF; } else { i2c_data = 0x00; } return(i2c_data); } // ==================== I2C ACK send ========================== static void I2C_acksnd() { ACKDT = 0; ACKEN = 1; while (ACKEN) {} return; } // ==================== I2C NACK send ========================= static void I2C_nacksnd() { ACKDT = 1; ACKEN = 1; while (ACKEN) {} 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) { PORTB = (PORTB & 0x0F) | (c << 4); LCD_E = 1; NOP(); LCD_E = 0; return; } // ==================== LCDコマンドWRITE ================= static void LCD_cmd(unsigned char cmd) { LCD_RS = 0; PORTB = (PORTB & 0x0F) | (cmd & 0xF0); LCD_E = 1; // 上位4ビット書き込み NOP(); LCD_E = 0; PORTB = (PORTB & 0x0F) | (cmd <<4); LCD_E = 1; // 下位4ビット書き込み NOP(); LCD_E = 0; wait_50us(); return; } // ==================== LCDデータWRITE ================= static void LCD_data(unsigned char cmd) { LCD_RS = 1; PORTB = (PORTB & 0x0F) | (cmd & 0xF0); LCD_E = 1; // 上位4ビット書き込み NOP(); LCD_E = 0; PORTB = (PORTB & 0x0F) | (cmd <<4); 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]); 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; } // ========================== ここまで ==============================