SSブログ

I2C CPU= pic16f886 EEPROM=24LC64 c

他力本願C言語シリーズ
以前、アセンブラで行ったI2C通信に依るEEPROM  24LC64です
書き込みと読み出しのデータをLCD表示しています

CPU = PIC16F886 マスター
LCD = AQX1602XA   スレーブアドレス=0x7C
EEPROM = 24LC64   スレーブアドレス=0xA0

動作は単純です
EEPROMのメモリーアドレス 0x00~0xFFに対して
データ 0x00~0xFF を書いて読み出す、という動作です
LCDの表示は・・・
W=xx  が書き込みデータ
R=xx が読み出しデータ
・・・と成っています、いつもの様に単純な動作確認です


ちゃんと書かれているかも確認しました

pic16f886_24LC64_v003.X



ソースファイルです、無関係のデバイスの関数も書かれていて
相変わらずど素人のソースです、多方面からコピーしてペタペタ
貼って書いて居ますので無理無駄、煩雑、理解不能、苛々など
在りますが責任も含めて全て放棄します、ご容赦下さい。


/*
 * File:   main.c
 * Author: maru
 * pic16f886_24LC64_v003
 * Created on 2019/01/22(火)
 * 0 -> 1 -> 2...32768 -> -32768 -> -32767...-3 -> -2 -> -1 -> 0 の繰り返し
 */

//******************************************************************************
//コンフィギュレーション
// CONFIG1 MPLAB XIDEの Production -> Set Configration bits で設定してもこのプログラムでの宣言が優先される
//#pragma config FOSC = INTRC_NOCLKOUT //RA6 = I/O          //デフォルトではRA6 = fosc/4 output
// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = ON      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)電源オン時、要リセット、しないとBootしない
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Reset Selection bits (BOR enabled)
#pragma config IESO = ON       // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (RB3/PGM pin has PGM function, low voltage programming enabled)

// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

//******************************************************************************
//コンパイラ
#include 
#include 
#include 
#include 
//******************************************************************************
//外部自作ファイル



//******************************************************************************
//マクロ
#define _XTAL_FREQ 8000000      //PIC16F886はINTOSC時最高8MHzまでしか出ない下のOSCCON = 0x70;と矛盾しては成らない
#define LCD_ADD 0x7C            //LCDスレーブアドレス W
#define S5851A_ADR 0x90         //温度センサースレーブアドレス W
#define PCF8574AN_ADR 0x70      //Extentioned IO スレーブアドレス W
#define PCF8574AN_ADR_R 0x73      //Extentioned IO スレーブアドレス W
#define ToHome 0b00000010
#define shiftLeft 0b00011000
#define shiftRight 0b00011100
#define clear 0b00000001
    //--------------------------

//******************************************************************************
static unsigned char I2C_rcv();
static void I2C_nacksnd() ;
static unsigned char I2C_ackchk();

char moji[] = " ";
char moji2[] = "Celsius ";
char moji3[] = "Thermal S-5851A SII";      //この文字列を長くするとカウントアップがバグる、原因不明
char moji4[] = "      ";    //空白を書く、前の文字が残って邪魔をするから
char moji5[] = ".";         //
char moji6[] = "C";

char moji10[] = "0000";		//温度計少数以下
char moji11[] = "0625";		//温度計少数以下
char moji12[] = "1250";		//温度計少数以下
char moji13[] = "1875";		//温度計少数以下
char moji14[] = "2500";		//温度計少数以下

char moji15[] = "3125";		//温度計少数以下
char moji16[] = "3750";		//温度計少数以下
char moji17[] = "4375";		//温度計少数以下
char moji18[] = "5000";		//温度計少数以下
char moji19[] = "5625";		//温度計少数以下

char moji20[] = "6250";		//温度計少数以下
char moji21[] = "6875";		//温度計少数以下
char moji22[] = "7500";		//温度計少数以下
char moji23[] = "8125";		//温度計少数以下
char moji24[] = "8750";		//温度計少数以下
char moji25[] = "9375";		//温度計少数以下

char moji30[] = "EEPROM 24LC64";		//EEPROM
char moji31[] = "W=";                   //EEPROM
char moji32[] = "R=";                   //EEPROM

unsigned char k;            // k = PCF8574ANから読み込んだデータ、char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k2;           // k2 = MCP23017から読み込んだデータ、char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k3;           // k3 = 温度センサーから読み込んだデータ、MSB  char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k4;           // k4 = 温度センサーから読み込んだデータ、LSB  但し上位4bitのみ、下位4bitはゼロ、char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k5;
unsigned char LED;

//---------------------------------
//for EEPROM
int HADR;                              //EEPROM High address
int LADR;                              //EEPROM Low address
int ROMDATA_W;                         //EEPROM write data
int ROMDATA_R;                         //EEPROM read data
//******************************************************************************
    void TRIGGER(){
        PORTAbits.RA0 = 1;    //for debug オシロスコープ・トリガ用 PORTA-RA0
          __delay_us(10);
        PORTAbits.RA0 = 0;
    }
//-------------------------------
    void I2C_Master_Init(const unsigned long c)
    {
      SSPCON  = 0b00101000;     //RC3/SCK/SCL  RC4/SDI/SDA として使用宣言
      SSPCON2 = 0;
      SSPADD = (_XTAL_FREQ/(4*c))-1;
      SSPSTAT = 0b00000000 ;    // 標準速度モードに設定する(100kHz)
    }
 //-------------------------------   
    void I2C_Init()
    {
      SSPCON  = 0x28;     //RC3/SCK/SCL  RC4/SDI/SDA として使用宣言
      SMP = 1;
      CKE = 0;
      SSPADD = 0x13;      //
     }
//-------------------------------
    void I2C_Master_Wait()
    {
      while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
    }
//-------------------------------
    void I2C_Master_Start()
    {
      I2C_Master_Wait();
      SEN = 1;
    }
//-------------------------------
    void I2C_Master_RepeatedStart()
    {
      I2C_Master_Wait();
      RSEN = 1;
    }
//-------------------------------
//    void I2C_Master_Stop()
//    {
//      I2C_Master_Wait();
//      PEN = 1;
//    }
    
    // ストップコンディション生成 ↑代替 maru
void I2C_Master_Stop() {
 
    // SSP1CON2レジスタのPENビットを1に設定すると
    // ストップコンディションが生成される
    // 発行が完了するとSSP1IFが1になるのでwhile文で待つ
    SSPIF = 0;
    SSPCON2bits.PEN = 1;
    while (SSPIF == 0) {}
    SSPIF = 0;
 
    return;
}
//-------------------------------    

//    void I2C_Master_Write(unsigned d)
//    {
//      I2C_Master_Wait();
//      SSPBUF = d;
//    }
    
    //代替↑

        void I2C_Master_Write(unsigned d)
    // SSP1BUFに送信したいデータをセットすると、そのデータが送信される
    // 発行が完了するとSSP1IFが1になるのでwhile文で待つ
    // ACK 待ちは無い、https://tool-lab.com/make/pic-practice-40/
        {
    I2C_Master_Wait();                  //これが無いと全く出鱈目に成る 
    SSPIF = 0;
    SSPBUF = d;
    while (SSPIF == 0) {}
    SSPIF = 0;
     
 //   return;
}
//-------------------------------
// 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 Recive 
//static unsigned char I2C_rcv() {
//	SSPIF = 0;
//	RCEN = 1;
//	while (RCEN) {}

//	return(SSPBUF);
//}

static unsigned char I2C_rcv() {
    SSPIF = 0;
    SSPCON2bits.RCEN = 1;
    while (SSPIF == 0) {}
    SSPIF = 0;
 
    return SSPBUF;
}
//-------------------------------
// I2C NACK send 
//static void I2C_nacksnd() {
//	ACKDT = 1;
//	ACKEN = 1;
//	while (ACKEN) {}

//	return;
//}
//-------------------------------
static void I2C_nacksnd() {
    // ACKDTにNACKをセット(負論理なので1を設定)
    SSPCON2bits.ACKDT = 1;
    // NACK信号生成
    SSPCON2bits.ACKEN = 1;
    while (SSPCON2bits.ACKEN) {}
    return;
}
//-------------------------------
static void I2C_acksnd() {
    // ACKDTにACKをセット
    SSPCON2bits.ACKDT = 0;
    // NACK信号生成
    SSPCON2bits.ACKEN = 1;
    while (SSPCON2bits.ACKEN) {}
    return;
}
//-------------------------------
    void writeData(char t_data){
        I2C_Master_Start();             //スタート・コンディション
        I2C_Master_Write(LCD_ADD);      //0x7C スレーブアドレス
        I2C_Master_Write(0x40);         //0x40  キャラクタを書くよって宣言
        I2C_Master_Write(t_data);       //キャラクタの送信
        I2C_Master_Stop();              //ストップ・コンディション
        __delay_ms(10);
    }
//-------------------------------
    void writeCommand(char t_command){
        I2C_Master_Start();
        I2C_Master_Write(LCD_ADD);
        I2C_Master_Write(0x00);
        I2C_Master_Write(t_command);
        I2C_Master_Stop();
        __delay_ms(10);
    }
//-------------------------------
    void PICinit(){
      OSCCON = 0x70;          //0x70=8MHz PIC16F886はINTOSC時最高8MHzまでしか出ない上の#define _XTAL_FREQ 8000000;と矛盾しては成らない
      ANSEL  = 0b00000000;
      ANSELH = 0b00000000;
      TRISA  = 0b00000000;
      TRISB  = 0b00000000;
      TRISC  = 0b00011000;
      PORTA  = 0b00000000;    //2進数で書いた場合
      PORTB  = 0x00;          //16進数で書いた場合
    }
//******************************************************************************
    void LCD_Init(){            //LCDの初期化、秋月のマニュアル通り
      //TRIGGER();                //for debug オシロスコープ・トリガ用 PORTA-RA0  
      I2C_Master_Init(100000);
      __delay_ms(400);
      //TRIGGER();                //for debug オシロスコープ・トリガ用 PORTA-RA0
      writeCommand(0x38);       //このプロトコルは S 0x7C 0x00 0x38 A P と成っているから下のプロトコルも全部一個ずつ送信している
      __delay_ms(20);
      writeCommand(0x39);
      __delay_ms(20);
      writeCommand(0x14);
      __delay_ms(20);
      writeCommand(0x73);
      __delay_ms(20);
      writeCommand(0x52);
      __delay_ms(20);
      writeCommand(0x6C);
      __delay_ms(250);
      writeCommand(0x38);
      __delay_ms(20);
      writeCommand(0x01);
      __delay_ms(20);
      writeCommand(0x0C);
      __delay_ms(20);
    }
//-------------------------------
    void LCD_str(char *c) {     //LCDに配列の文字を表示
      unsigned char i,wk;
      for (i=0 ; ; i++) {
        wk = c[i];
        if  (wk == 0x00) {break;}
        writeData(wk);
      }
    }
//******************************************************************************    
    //S5851A_ADR 温度センサー部分
    void S5851A_W(char t_data){
        I2C_Master_Init(100000);
        I2C_Master_Start();             //スタート・コンディション
        I2C_Master_Write(S5851A_ADR);      //スレーブアドレス
        I2C_Master_Write(0x01);         //
        I2C_Master_Write(t_data);       //キャラクタの送信
        I2C_Master_Stop();              //ストップ・コンディション
        __delay_ms(10);
    }
//******************************************************************************    
    //PCF8574AN Extentioned IO 部分
    void PCF8574AN_W(){                     //PCF8574AN Extentioned IO WRITE
        I2C_Master_Init(100000);
        I2C_Master_Start();                   //スタート・コンディション
        I2C_Master_Write(PCF8574AN_ADR);      //スレーブアドレス
        I2C_Master_Write(0xAA);               //データ送信
        I2C_Master_Stop();                    //ストップ・コンディション
        __delay_ms(10);
    }
    
    void PCF8574AN_W2(char LED){            //PCF8574AN Extentioned IO WRITE
        I2C_Master_Init(100000);
        I2C_Master_Start();                   //スタート・コンディション
        I2C_Master_Write(PCF8574AN_ADR);      //スレーブアドレス
        I2C_Master_Write(LED);                //データ送信
        I2C_Master_Stop();                    //ストップ・コンディション
        __delay_ms(10);
    }
    
     void PCF8574AN_R(){                      //PCF8574AN Extentioned IO READ
    //    I2C_Master_Init(100000);              //これだと遅い
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(PCF8574AN_ADR_R);      //スレーブアドレス read
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        k = I2C_rcv();                          //スレーブアドレス側からのデータを受信する
    //    I2C_rcv(k);                           //この文法では読めない
    //    PORTA = (k);                          //ここに入れるのもOK
        I2C_nacksnd();                          //NACk送信
        I2C_Master_Stop();                      //ストップ・コンディション
        __delay_ms(10);
    }
//******************************************************************************
     // MCP23017 16bit IO 部分
     int GPA_LED;
     int GPB_IN_DATA;
     
     void MCP23017_GPA_INIT(){
        //MCP23017_GPAイニシャライズ
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x40);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x00);                 //レジスタ・ナンバー
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x00);                 //全入力設定 write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void MCP23017_GPB_INIT(){
        //MCP23017_GPイニシャライズ 
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x40);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x01);                 //レジスタ・ナンバー
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0xFF);                 //全出力設定 write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void MCP23017_GPA_OUT(GPA_LED){
        //MCP23017_GPAにデータ出力させる、Lチカ 
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x40);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x14);                 //レジスタ・ナンバー
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(GPA_LED);                 //LED表示 write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void MCP23017_GPB_IN(){
        //MCP23017_GPBのデータを読み込む、ディップスイッチ8bit 
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x40);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x13);                 //レジスタ・ナンバー
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_RepeatedStart();             //SR = RepeatedStart
        I2C_Master_Write(0x41);                 //スレーブアドレス READ
        I2C_Master_Wait();
        I2C_ackchk();
        k2 = I2C_rcv();                          //スレーブアドレス側からのデータを受信する = k2
        I2C_nacksnd();                          //NACk送信
        I2C_Master_Stop();                      //ストップ・コンディション
        __delay_ms(10);
         
     }
  
//******************************************************************************
//I2C 温度センサー SII S-5851A 部分
     void s5851a_init()                       //温度センサー初期化
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x90);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Write(0x01);                 //コンフィギュレーション・レジスタ
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x00);                 //常温設定
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void s5851a_me1()                        //温度測定一回目のみ、二回目からはカレントリードと云う簡略化したプロトコルで良い
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x90);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Write(0x00);                 //ダミー
        I2C_Master_Wait();
        I2C_ackchk();
        I2C_Master_RepeatedStart();             //リスタート
        I2C_Master_Write(0x91);                 //スレーブアドレス Read
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        k3 = I2C_rcv();                         //スレーブアドレス側からのデータを受信するMSB
        I2C_acksnd();                           //ACK送信
        k4 = I2C_rcv();                         //スレーブアドレス側からのデータを受信するLSB 但し上位4bitのみ下位4bitはゼロ
        I2C_nacksnd();                          //NACK送信
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void s5851a_me2()                        //温度測定一回目のみ、二回目からはカレントリードと云う簡略化したプロトコルで良い
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x91);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        k3 = I2C_rcv();                         //スレーブアドレス側からのデータを受信するMSB
        I2C_acksnd();                           //ACK送信
        k4 = I2C_rcv();                         //スレーブアドレス側からのデータを受信するLSB 但し上位4bitのみ下位4bitはゼロ
        I2C_nacksnd();                          //NACK送信
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void hairetsu()
     {
            if (k4 == 0) {
            LCD_str(moji10);                
            }else if (k4 == 1){
            LCD_str(moji11);
            }else if (k4 == 2){
            LCD_str(moji12);
            }else if (k4 == 3){
            LCD_str(moji13);
            }else if (k4 == 4){
            LCD_str(moji14);
            
            }else if (k4 == 5){
            LCD_str(moji15);
            }else if (k4 == 6){
            LCD_str(moji16);
            }else if (k4 == 7){
            LCD_str(moji17);
            }else if (k4 == 8){
            LCD_str(moji18);
            }else if (k4 == 9){
            LCD_str(moji19);
            
            }else if (k4 == 0x0A){
            LCD_str(moji20);
            }else if (k4 == 0x0B){
            LCD_str(moji21);
            }else if (k4 == 0x0C){
            LCD_str(moji22);
            }else if (k4 == 0x0D){
            LCD_str(moji23);
            }else if (k4 == 0x0E){
            LCD_str(moji24);
            }else if (k4 == 0x0F){
            LCD_str(moji25);
            }
            return;
     }
//******************************************************************************
//I2C EEPROM 24LC64 部分  
        void EEPROM_W ()                       //EEPROM 1 byte write routin 2019/01/22
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0xA0);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Write(HADR);                 //EEPROM High address
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(LADR);                 //EEPROM Low address
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Write(ROMDATA_W);                 //EEPROM Low address
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
        void EEPROM_R()                        //温度測定一回目のみ、二回目からはカレントリードと云う簡略化したプロトコルで良い
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0xA0);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(HADR);                 //EEPROM High address
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(LADR);                 //EEPROM Low address
        I2C_Master_Wait();
        I2C_ackchk();
        I2C_Master_RepeatedStart();             //リスタート
        I2C_Master_Write(0xA1);                 //スレーブアドレス Read
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        ROMDATA_R = I2C_rcv();                  //スレーブアドレス側からのデータを受信するMSB
        I2C_nacksnd();                          //NACK送信
        I2C_Master_Stop();                      //ストップ・コンディション
     }     
     
     
//******************************************************************************
    int main(void)
    {
        PICinit();                        //PICを初期化
        //-----------
        I2C_Init();                             //これだと速い
        //-----------
        LCD_Init();                       //LCD初期化
        __delay_ms(2);
        //-----------
        writeCommand(0x01);               //画面をクリア
        __delay_ms(10);
        writeCommand(0x02);               //ホームへカーソル移動
        __delay_ms(2);                    // LCD側の処理待ち、LCDは全く読み込めないので見込み時間
      
        writeCommand(0x80);               //1列目へ移動
        LCD_str(moji30);                  //EEPROM
        __delay_ms(10);
        
        writeCommand(0x80+0x40);          //2列目へ移動
        LCD_str(moji31);                  //EEPROM
        __delay_ms(10);
        
        writeCommand(0x88+0x40);          //2列目へ移動
        LCD_str(moji32);                  //EEPROM
        __delay_ms(10);
    //------------------------------- 
        HADR = 0x00;
        LADR = 0x00;
        ROMDATA_W = 0x00;
        
     while(1)
        {
    //-------------------------------
        //write
        //TRIGGER();
        EEPROM_W ();                        //EEPROM DATA WRITE
        writeCommand(0x82+0x40);            //2列目へ移動
        sprintf(moji,"%02X",ROMDATA_W);     //左寄せしない2桁表示
        LCD_str(moji);
        //---------------------------
        //更新
        ROMDATA_W = ROMDATA_W ++;           //DATA inc+1
        
        if(ROMDATA_W == 0x100){             //FF -> 100 と成らない様にする
            ROMDATA_W = 0x00;
        }
        
        LADR = LADR ++;                     //Low address inc+1
        
        if(LADR== 0x100){                   //FF -> 100 と成らない様にする
            LADR = 0x00;
        }
        __delay_ms(100);                     //遅延
        //---------------------------
        //read
        TRIGGER();
        EEPROM_R();                         //EEPROM DATA READ
        writeCommand(0x8A+0x40);            //2列目へ移動
        sprintf(moji,"%02X",ROMDATA_R);     //左寄せしない2桁表示
        LCD_str(moji);
    //-------------------------------
        __delay_ms(100);                     //遅延
        }
    return 0;
    //-------------------------------
    }

**************************************************************************************
2019/01/23(水)

上の記事では 24LC64 の 1/32ページだけの読み書きでしたが
次はC言語の for 文 を使って32ページ全部の読み書き動作です
スレーブアドレス 0xA0(W) / A1(R)
ページ 0x00 = bank=00 と表示し
最後のページは 0x1F = bank=1F と表示しました
結構遅いです、というより絶対遅すぎる、秋月のライターだと
全然速くて比較にならないです


書けているかは秋月のライターで確認しました、書けています、って当然ですね
pic16f886_24LC64_v005.Xa

pic16f886_24LC64_v005.Xb

pic16f886_24LC64_v005.Xc

ソースファイル、毎回ですが下手でお見苦しいです余計な関数消してないし・・・


/*
 * File:   main.c
 * Author: maru
 * pic16f886_24LC64_v005
 * Created on 2019/01/22(火)
 * 
 */

//******************************************************************************
//コンフィギュレーション
// CONFIG1 MPLAB XIDEの Production -> Set Configration bits で設定してもこのプログラムでの宣言が優先される
//#pragma config FOSC = INTRC_NOCLKOUT //RA6 = I/O          //デフォルトではRA6 = fosc/4 output
// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = ON      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)電源オン時、要リセット、しないとBootしない
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Reset Selection bits (BOR enabled)
#pragma config IESO = ON       // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (RB3/PGM pin has PGM function, low voltage programming enabled)

// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

//******************************************************************************
//コンパイラ
#include 
#include 
#include 
#include 
//******************************************************************************
//外部自作ファイル



//******************************************************************************
//マクロ
#define _XTAL_FREQ 8000000      //PIC16F886はINTOSC時最高8MHzまでしか出ない下のOSCCON = 0x70;と矛盾しては成らない
#define LCD_ADD 0x7C            //LCDスレーブアドレス W
#define S5851A_ADR 0x90         //温度センサースレーブアドレス W
#define PCF8574AN_ADR 0x70      //Extentioned IO スレーブアドレス W
#define PCF8574AN_ADR_R 0x73      //Extentioned IO スレーブアドレス W
#define ToHome 0b00000010
#define shiftLeft 0b00011000
#define shiftRight 0b00011100
#define clear 0b00000001
    //--------------------------

//******************************************************************************
static unsigned char I2C_rcv();
static void I2C_nacksnd() ;
static unsigned char I2C_ackchk();

char moji[] = " ";
char moji2[] = "Celsius ";
char moji3[] = "Thermal S-5851A SII";      //この文字列を長くするとカウントアップがバグる、原因不明
char moji4[] = "      ";    //空白を書く、前の文字が残って邪魔をするから
char moji5[] = ".";         //
char moji6[] = "C";

char moji10[] = "0000";		//温度計少数以下
char moji11[] = "0625";		//温度計少数以下
char moji12[] = "1250";		//温度計少数以下
char moji13[] = "1875";		//温度計少数以下
char moji14[] = "2500";		//温度計少数以下

char moji15[] = "3125";		//温度計少数以下
char moji16[] = "3750";		//温度計少数以下
char moji17[] = "4375";		//温度計少数以下
char moji18[] = "5000";		//温度計少数以下
char moji19[] = "5625";		//温度計少数以下

char moji20[] = "6250";		//温度計少数以下
char moji21[] = "6875";		//温度計少数以下
char moji22[] = "7500";		//温度計少数以下
char moji23[] = "8125";		//温度計少数以下
char moji24[] = "8750";		//温度計少数以下
char moji25[] = "9375";		//温度計少数以下

char moji30[] = "EEPROM bank=";		//EEPROM
char moji31[] = "W=";                   //EEPROM
char moji32[] = "R=";                   //EEPROM

unsigned char k;            // k = PCF8574ANから読み込んだデータ、char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k2;           // k2 = MCP23017から読み込んだデータ、char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k3;           // k3 = 温度センサーから読み込んだデータ、MSB  char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k4;           // k4 = 温度センサーから読み込んだデータ、LSB  但し上位4bitのみ、下位4bitはゼロ、char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k5;
unsigned char LED;

//---------------------------------
//for EEPROM
int HADR;                              //EEPROM High address
int LADR;                              //EEPROM Low address
int ROMDATA_W;                         //EEPROM write data
int ROMDATA_R;                         //EEPROM read data

//******************************************************************************
    void TRIGGER(){
        PORTAbits.RA0 = 1;    //for debug オシロスコープ・トリガ用 PORTA-RA0
          __delay_us(10);
        PORTAbits.RA0 = 0;
    }
//-------------------------------
    void I2C_Master_Init(const unsigned long c)
    {
      SSPCON  = 0b00101000;     //RC3/SCK/SCL  RC4/SDI/SDA として使用宣言
      SSPCON2 = 0;
      SSPADD = (_XTAL_FREQ/(4*c))-1;
      SSPSTAT = 0b00000000 ;    // 標準速度モードに設定する(100kHz)
    }
 //-------------------------------   
    void I2C_Init()
    {
      SSPCON  = 0x28;     //RC3/SCK/SCL  RC4/SDI/SDA として使用宣言
      SMP = 1;
      CKE = 0;
      SSPADD = 0x13;      //
     }
//-------------------------------
    void I2C_Master_Wait()
    {
      while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
    }
//-------------------------------
    void I2C_Master_Start()
    {
      I2C_Master_Wait();
      SEN = 1;
    }
//-------------------------------
    void I2C_Master_RepeatedStart()
    {
      I2C_Master_Wait();
      RSEN = 1;
    }
//-------------------------------
//    void I2C_Master_Stop()
//    {
//      I2C_Master_Wait();
//      PEN = 1;
//    }
    
    // ストップコンディション生成 ↑代替 maru
void I2C_Master_Stop() {
 
    // SSP1CON2レジスタのPENビットを1に設定すると
    // ストップコンディションが生成される
    // 発行が完了するとSSP1IFが1になるのでwhile文で待つ
    SSPIF = 0;
    SSPCON2bits.PEN = 1;
    while (SSPIF == 0) {}
    SSPIF = 0;
 
    return;
}
//-------------------------------    

//    void I2C_Master_Write(unsigned d)
//    {
//      I2C_Master_Wait();
//      SSPBUF = d;
//    }
    
    //代替↑

        void I2C_Master_Write(unsigned d)
    // SSP1BUFに送信したいデータをセットすると、そのデータが送信される
    // 発行が完了するとSSP1IFが1になるのでwhile文で待つ
    // ACK 待ちは無い、https://tool-lab.com/make/pic-practice-40/
        {
    I2C_Master_Wait();                  //これが無いと全く出鱈目に成る 
    SSPIF = 0;
    SSPBUF = d;
    while (SSPIF == 0) {}
    SSPIF = 0;
     
 //   return;
}
//-------------------------------
// 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 Recive 
//static unsigned char I2C_rcv() {
//	SSPIF = 0;
//	RCEN = 1;
//	while (RCEN) {}

//	return(SSPBUF);
//}

static unsigned char I2C_rcv() {
    SSPIF = 0;
    SSPCON2bits.RCEN = 1;
    while (SSPIF == 0) {}
    SSPIF = 0;
 
    return SSPBUF;
}
//-------------------------------
// I2C NACK send 
//static void I2C_nacksnd() {
//	ACKDT = 1;
//	ACKEN = 1;
//	while (ACKEN) {}

//	return;
//}
//-------------------------------
static void I2C_nacksnd() {
    // ACKDTにNACKをセット(負論理なので1を設定)
    SSPCON2bits.ACKDT = 1;
    // NACK信号生成
    SSPCON2bits.ACKEN = 1;
    while (SSPCON2bits.ACKEN) {}
    return;
}
//-------------------------------
static void I2C_acksnd() {
    // ACKDTにACKをセット
    SSPCON2bits.ACKDT = 0;
    // NACK信号生成
    SSPCON2bits.ACKEN = 1;
    while (SSPCON2bits.ACKEN) {}
    return;
}
//-------------------------------
    void writeData(char t_data){
        I2C_Master_Start();             //スタート・コンディション
        I2C_Master_Write(LCD_ADD);      //0x7C スレーブアドレス
        I2C_Master_Write(0x40);         //0x40  キャラクタを書くよって宣言
        I2C_Master_Write(t_data);       //キャラクタの送信
        I2C_Master_Stop();              //ストップ・コンディション
        __delay_ms(10);
    }
//-------------------------------
    void writeCommand(char t_command){
        I2C_Master_Start();
        I2C_Master_Write(LCD_ADD);
        I2C_Master_Write(0x00);
        I2C_Master_Write(t_command);
        I2C_Master_Stop();
        __delay_ms(10);
    }
//-------------------------------
    void PICinit(){
      OSCCON = 0x70;          //0x70=8MHz PIC16F886はINTOSC時最高8MHzまでしか出ない上の#define _XTAL_FREQ 8000000;と矛盾しては成らない
      ANSEL  = 0b00000000;
      ANSELH = 0b00000000;
      TRISA  = 0b00000000;
      TRISB  = 0b00000000;
      TRISC  = 0b00011000;
      PORTA  = 0b00000000;    //2進数で書いた場合
      PORTB  = 0x00;          //16進数で書いた場合
    }
//******************************************************************************
    void LCD_Init(){            //LCDの初期化、秋月のマニュアル通り
      //TRIGGER();                //for debug オシロスコープ・トリガ用 PORTA-RA0  
      I2C_Master_Init(100000);
      __delay_ms(400);
      //TRIGGER();                //for debug オシロスコープ・トリガ用 PORTA-RA0
      writeCommand(0x38);       //このプロトコルは S 0x7C 0x00 0x38 A P と成っているから下のプロトコルも全部一個ずつ送信している
      __delay_ms(20);
      writeCommand(0x39);
      __delay_ms(20);
      writeCommand(0x14);
      __delay_ms(20);
      writeCommand(0x73);
      __delay_ms(20);
      writeCommand(0x52);
      __delay_ms(20);
      writeCommand(0x6C);
      __delay_ms(250);
      writeCommand(0x38);
      __delay_ms(20);
      writeCommand(0x01);
      __delay_ms(20);
      writeCommand(0x0C);
      __delay_ms(20);
    }
//-------------------------------
    void LCD_str(char *c) {     //LCDに配列の文字を表示
      unsigned char i,wk;
      for (i=0 ; ; i++) {
        wk = c[i];
        if  (wk == 0x00) {break;}
        writeData(wk);
      }
    }
//******************************************************************************    
    //S5851A_ADR 温度センサー部分
    void S5851A_W(char t_data){
        I2C_Master_Init(100000);
        I2C_Master_Start();             //スタート・コンディション
        I2C_Master_Write(S5851A_ADR);      //スレーブアドレス
        I2C_Master_Write(0x01);         //
        I2C_Master_Write(t_data);       //キャラクタの送信
        I2C_Master_Stop();              //ストップ・コンディション
        __delay_ms(10);
    }
//******************************************************************************    
    //PCF8574AN Extentioned IO 部分
    void PCF8574AN_W(){                     //PCF8574AN Extentioned IO WRITE
        I2C_Master_Init(100000);
        I2C_Master_Start();                   //スタート・コンディション
        I2C_Master_Write(PCF8574AN_ADR);      //スレーブアドレス
        I2C_Master_Write(0xAA);               //データ送信
        I2C_Master_Stop();                    //ストップ・コンディション
        __delay_ms(10);
    }
    
    void PCF8574AN_W2(char LED){            //PCF8574AN Extentioned IO WRITE
        I2C_Master_Init(100000);
        I2C_Master_Start();                   //スタート・コンディション
        I2C_Master_Write(PCF8574AN_ADR);      //スレーブアドレス
        I2C_Master_Write(LED);                //データ送信
        I2C_Master_Stop();                    //ストップ・コンディション
        __delay_ms(10);
    }
    
     void PCF8574AN_R(){                      //PCF8574AN Extentioned IO READ
    //    I2C_Master_Init(100000);              //これだと遅い
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(PCF8574AN_ADR_R);      //スレーブアドレス read
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        k = I2C_rcv();                          //スレーブアドレス側からのデータを受信する
    //    I2C_rcv(k);                           //この文法では読めない
    //    PORTA = (k);                          //ここに入れるのもOK
        I2C_nacksnd();                          //NACk送信
        I2C_Master_Stop();                      //ストップ・コンディション
        __delay_ms(10);
    }
//******************************************************************************
     // MCP23017 16bit IO 部分
     int GPA_LED;
     int GPB_IN_DATA;
     
     void MCP23017_GPA_INIT(){
        //MCP23017_GPAイニシャライズ
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x40);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x00);                 //レジスタ・ナンバー
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x00);                 //全入力設定 write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void MCP23017_GPB_INIT(){
        //MCP23017_GPイニシャライズ 
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x40);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x01);                 //レジスタ・ナンバー
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0xFF);                 //全出力設定 write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void MCP23017_GPA_OUT(GPA_LED){
        //MCP23017_GPAにデータ出力させる、Lチカ 
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x40);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x14);                 //レジスタ・ナンバー
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(GPA_LED);                 //LED表示 write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void MCP23017_GPB_IN(){
        //MCP23017_GPBのデータを読み込む、ディップスイッチ8bit 
        I2C_Init();                             //これだと速い
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x40);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x13);                 //レジスタ・ナンバー
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_RepeatedStart();             //SR = RepeatedStart
        I2C_Master_Write(0x41);                 //スレーブアドレス READ
        I2C_Master_Wait();
        I2C_ackchk();
        k2 = I2C_rcv();                          //スレーブアドレス側からのデータを受信する = k2
        I2C_nacksnd();                          //NACk送信
        I2C_Master_Stop();                      //ストップ・コンディション
        __delay_ms(10);
         
     }
  
//******************************************************************************
//I2C 温度センサー SII S-5851A 部分
     void s5851a_init()                       //温度センサー初期化
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x90);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Write(0x01);                 //コンフィギュレーション・レジスタ
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(0x00);                 //常温設定
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void s5851a_me1()                        //温度測定一回目のみ、二回目からはカレントリードと云う簡略化したプロトコルで良い
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x90);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Write(0x00);                 //ダミー
        I2C_Master_Wait();
        I2C_ackchk();
        I2C_Master_RepeatedStart();             //リスタート
        I2C_Master_Write(0x91);                 //スレーブアドレス Read
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        k3 = I2C_rcv();                         //スレーブアドレス側からのデータを受信するMSB
        I2C_acksnd();                           //ACK送信
        k4 = I2C_rcv();                         //スレーブアドレス側からのデータを受信するLSB 但し上位4bitのみ下位4bitはゼロ
        I2C_nacksnd();                          //NACK送信
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void s5851a_me2()                        //温度測定一回目のみ、二回目からはカレントリードと云う簡略化したプロトコルで良い
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0x91);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        k3 = I2C_rcv();                         //スレーブアドレス側からのデータを受信するMSB
        I2C_acksnd();                           //ACK送信
        k4 = I2C_rcv();                         //スレーブアドレス側からのデータを受信するLSB 但し上位4bitのみ下位4bitはゼロ
        I2C_nacksnd();                          //NACK送信
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
     void hairetsu()
     {
            if (k4 == 0) {
            LCD_str(moji10);                
            }else if (k4 == 1){
            LCD_str(moji11);
            }else if (k4 == 2){
            LCD_str(moji12);
            }else if (k4 == 3){
            LCD_str(moji13);
            }else if (k4 == 4){
            LCD_str(moji14);
            
            }else if (k4 == 5){
            LCD_str(moji15);
            }else if (k4 == 6){
            LCD_str(moji16);
            }else if (k4 == 7){
            LCD_str(moji17);
            }else if (k4 == 8){
            LCD_str(moji18);
            }else if (k4 == 9){
            LCD_str(moji19);
            
            }else if (k4 == 0x0A){
            LCD_str(moji20);
            }else if (k4 == 0x0B){
            LCD_str(moji21);
            }else if (k4 == 0x0C){
            LCD_str(moji22);
            }else if (k4 == 0x0D){
            LCD_str(moji23);
            }else if (k4 == 0x0E){
            LCD_str(moji24);
            }else if (k4 == 0x0F){
            LCD_str(moji25);
            }
            return;
     }
//******************************************************************************
//I2C EEPROM 24LC64 部分  
        void EEPROM_W ()                       //EEPROM 1 byte write routin 2019/01/22
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0xA0);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Write(HADR);                 //EEPROM High address
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(LADR);                 //EEPROM Low address
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        I2C_Master_Write(ROMDATA_W);                 //EEPROM Low address
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Stop();                      //ストップ・コンディション
     }
     
        void EEPROM_R()                        //温度測定一回目のみ、二回目からはカレントリードと云う簡略化したプロトコルで良い
     {
        I2C_Master_Start();                     //スタート・コンディション
        I2C_Master_Write(0xA0);                 //スレーブアドレス write
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(HADR);                 //EEPROM High address
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
        I2C_Master_Write(LADR);                 //EEPROM Low address
        I2C_Master_Wait();
        I2C_ackchk();
        I2C_Master_RepeatedStart();             //リスタート
        I2C_Master_Write(0xA1);                 //スレーブアドレス Read
        I2C_Master_Wait();
        I2C_ackchk();                           //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする 
        ROMDATA_R = I2C_rcv();                  //スレーブアドレス側からのデータを受信するMSB
        I2C_nacksnd();                          //NACK送信
        I2C_Master_Stop();                      //ストップ・コンディション
     }     
     
     
//******************************************************************************
    int main(void)
    {
        PICinit();                        //PICを初期化
        //-----------
        I2C_Init();                             //これだと速い
        //-----------
        LCD_Init();                       //LCD初期化
        __delay_ms(2);
        //-----------
        writeCommand(0x01);               //画面をクリア
        __delay_ms(10);
        writeCommand(0x02);               //ホームへカーソル移動
        __delay_ms(2);                    // LCD側の処理待ち、LCDは全く読み込めないので見込み時間
      
        writeCommand(0x80);               //1列目へ移動
        LCD_str(moji30);                  //EEPROM
        __delay_ms(10);
        
        writeCommand(0x80+0x40);          //2列目へ移動
        LCD_str(moji31);                  //EEPROM
        __delay_ms(10);
        
        writeCommand(0x88+0x40);          //2列目へ移動
        LCD_str(moji32);                  //EEPROM
        __delay_ms(10);
        
        //-------------------------------
        HADR = 0x00;
        LADR = 0x00;
        ROMDATA_W = 0x00;

        //-------------------------------
        while(1)                            //Loop
        {
        //-------------------------------
            //Bank
            for (HADR = 0; HADR <= 0x1F; HADR ++)
            {
                writeCommand(0x8C);            //2列目へ移動
                sprintf(moji,"%02X",HADR);     //左寄せしない2桁表示、書き込みデータ表示
                LCD_str(moji);
        //------------------------------- 
                for (ROMDATA_W = 0; ROMDATA_W <=0xFF; ROMDATA_W ++)
                {
        //write
        //TRIGGER();
                    EEPROM_W ();                        //EEPROM DATA WRITE
                    writeCommand(0x82+0x40);            //2列目へ移動
                    sprintf(moji,"%02X",ROMDATA_W);     //左寄せしない2桁表示、書き込みデータ表示
                    LCD_str(moji);
        //---------------------------
                    if(ROMDATA_W == 0x100){             //FF -> 100 と成らない様にする
                        ROMDATA_W = 0x00;
                    }
                    //__delay_ms(6);本来ここに5ms以上のタイマーを置くべき所、LCD表示でモタモタして10ms掛かるのでタイマーは削除
        //---------------------------
        //read
                    TRIGGER();
                    EEPROM_R();                         //EEPROM DATA READ
                    writeCommand(0x8A+0x40);            //2列目へ移動
                    sprintf(moji,"%02X",ROMDATA_R);     //左寄せしない2桁表示
                    LCD_str(moji);
    //-------------------------------
                    __delay_ms(1);                     //遅延
                    LADR = LADR ++;                     //Low address inc+1
        
                    if(LADR== 0x100){                   //FF -> 100 と成らない様にする
                        LADR = 0x00;
                    }
                }
            }
        }
    return 0;                                   //Loop
    //-------------------------------
    }
    


nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

I2C & PIC16F886 & LC..I2C Color Sensor S11.. ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。