I2C通信                                       



■ 
全般                                                     
  I2CはInter-Integrated circuitの略で正式には”アイ・スクウェアド・シー”と読みます。ただ、日本人には発音しにくい為か”アイ・ツー・シー”と発音する人が多いようです。尚、以下ではI2Cは書きにくいのでI2Cと記載します。
   
 

■ PIC間 1文字送受信
 以下に I2C通信によるPIC間の文字送受信の例を紹介します。


(1)C30コンパイラ、 PIC24F

<試作品仕様>

 ・I2C通信によりPIC間の1文字送受信をおこなう。
 ・I2C通信の主な諸元は以下とする。
  @ 通信速度 …… 100KHz
  A アドレス送信方式 …… 7ビット
  B クロックストレッチ制御 …… 有り
  C マスタからのデータ送信要求終了通知 ……NACK
  D スレーブの受信方式 …… 割込み方式
 ・通信ポート: secondary ポート(ASCL1、ASDA1)を使用
 ・マスター側、スレーブ側各々のPICにはキャラクタ型液晶を接続する。
 ・マスタ側液晶の1行目には送信文字を、2行目には受信文字を表示する
 ・スレーブ側液晶の1行目には受信文字を、2行目には返信文字を表示する。
 ・マスターPICからの送信文字 及びスレーブPICからの返信文字は以下とする。
   <マスタ送信文字>    <スレーブ返信文字>
         A       →       a
         B       →       b
         C       →       c
         D       →       d

 ・ 表示例

    マスタ側液晶  スレーブ側液晶
1行目 send_data= B receive_data=B
2行目 receive_data=b   send_data=b



                

<試作品回路図> (→回路図のPDFファイル
 PIC24FJ64GA002をつかった場合の回路図を以下に示します。

              
           

 

<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

     

          

   <プログラム例>


///************************************************************/
//*  I2C  PIC間 1文字送受信
//*              マスター    PIC24FJ64GA002   
//************************************************************/
#include "p24FJ64GA002.h"
#include <stdio.h>
#include <i2c.h>


#include        "1lcd_lib_C30.h"
#include        "1lcd_lib_c30.c"

/// コンフィギュレーション ビットの設定
_CONFIG1
(
        JTAGEN_OFF &    //JTAGポート: OFF
        GCP_OFF &               //コードプロテクト: OFF
        GWRP_OFF &              //書き込みプロテクト: OFF
        BKBUG_OFF &             //バックグランドデバック: OFF
        COE_OFF &               //クリップオン エミュレーション: OFF 
        ICS_PGx1&               //ICDピンの選択: EMUC/EMUDをPGC1/PGD1と共用
        FWDTEN_OFF              //ウォッチドックタイマ: OFF 
)

_CONFIG2
( 
        IESO_OFF &              // 2速度スタートアップ機能:OFF
//      IESO_ON &               // 2速度スタートアップ機能:ON
        FNOSC_PRI &     //外付け発振子20MHZ PLLなし  → システムクロック:20MHZ
        FCKSM_CSDCMD &  //クロック切替え制御:OFF クロックモニタ:OFF
        OSCIOFNC_OFF &  //OSCO/RC15 function: OSCO or Fosc/2
        IOL1WAY_ON &    //RP Register Protection: Unlimited Writes To RP Registers
//      I2C1SEL_PRI &   //I2C1 pins Select: Use Primary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンSDA1(ピン番号18),SCL1(ピン番号17)を使用する場合
        I2C1SEL_SEC &   //I2C1 pins Select: Use Secondary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンASDA(ピン番号14),ASCL(ピン番号15)を使用する場合
        POSCMOD_HS              //発振回路モード Oscillator Selection:  HS (外付け発振回路 発振周波数レベル:HS)
//      POSCMOD_NONE    //発振回路モード Oscillator Selection:  Primary disabled(内蔵発振回路使用の場合)
)


char Buf[17];   //文字列のバッファー用レジスタ
char Space = ' ';

unsigned int adr_slave = 0xa8;  //送受信相手スレーブのアドレス
unsigned int adr_write_cmd,adr_read_cmd;


void delay_ms(unsigned int N)   //ウェイト関数
{
        __delay32(Clock/2000*N);
}

void DataTrans(unsigned char sData)     // 1バイト送信サブ関数
{
        I2C1TRN = sData;// data送信////   MasterWriteI2C1(sData);
        while(I2C1STATbits.TBF);        // 送信終了待ち
        while(I2C1STATbits.ACKSTAT);    // ACK受信待ち

        while(I2C1CONbits.SEN);//@スタート条件ではない  //@+A+B+C+D →     IdleI2C1(); アイドル待ち
        while(I2C1CONbits.PEN);//Aストップ条件ではない
        while(I2C1CONbits.RCEN);//B受信シーケンス中ではない
        while(I2C1CONbits.ACKEN);//C アクノリッジシーケンス中でない
        while(I2C1STATbits.TRSTAT);     //D送信終了まち
}


void write_slave(unsigned int adr_cmd, char char1)      //文字列送信関数
{
        I2C1STATbits.I2COV = 0;                         // エラークリア//
        I2C1CONbits.SEN = 1;    //I2Cバスにスタート条件出力: SCL: 1、 SDA: 1→0      //      StartI2C1();
        while(I2C1CONbits.SEN); //出力完了待ち                //      while(SSPCON2bits.SEN);         //出力完了待ち
        DataTrans(adr_cmd);             //スレーブチップアドレスと書き込み命令

        DataTrans(char1);       //1バイト送信

        I2C1CONbits.PEN = 1;    //ストップ条件発行(SCL:1、SDA:0→1))      //      StopI2C1();//通信一時停止
        while(I2C1CONbits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる
}


unsigned char read_slave1(unsigned adr_cmd)     //1文字受信関数
{
        unsigned char temp_data;

        I2C1CONbits.SEN = 1;    //スタート条件発行(SCL:1、SDA:1→0) //    StartI2C1();
        while(I2C1CONbits.SEN); //出力完了待ち //正常に発行されればハードによりクリアされる
        IFS1bits.MI2C1IF = 0;   //マスター動作時の割込みフラグクリア(割り込みを使った場合は必須)
        DataTrans(adr_cmd);     //(スレーブアドレス + 読み込み)コマンドをスレーブへ送信

        I2C1CONbits.RCEN = 1;           //受信許可  while(DataRdyI2C1());
        while(!I2C1STATbits.RBF);       //受信バッファ受信完了
        temp_data = I2C1RCV;    //データ読み込み       temp_data =  MasterReadI2C1();  //      
        

        I2C1CONbits.ACKDT = 1;                  //1文字受信でおしまいなおでNACK=1をセット       //      NotAckI2C1();
                                                                        //vs 更にデータ送信をスレーブに要求する場合は、ACK=0をセットする //AckI2C1();
        I2C1CONbits.ACKEN = 1;                  //ACKDTにセットされている NACKかACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
        while(I2C1CONbits.ACKEN);               //送信完了を待つ //ACKENは送信完了でハードによりクリアされる


        I2C1CONbits.PEN = 1;    //ストップ条件発行(SCL:1、SDA:0→1))      StopI2C1();//通信一時停止
        while(I2C1CONbits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる
 
        return temp_data;
}


void Func1(char data_trans)     //      1文字の送受信 &表示関数
{
                unsigned char temp;

                lcd_clear();
                sprintf(Buf,"send_data=%c",data_trans); 
                lcd_str(Buf);                   //マスター側液晶表示 
                write_slave(adr_write_cmd,data_trans);  //スレーブへ "$Tokyo Olympic\r" を送信

                temp = read_slave1(adr_read_cmd);       //スレーブデータの読み出し
                sprintf(Buf,"receive_data=%c",temp);
                lcd_cmd(0xC0);          //2行目の先頭へ
                lcd_str(Buf);                   //マスター側液晶表示 
        
                delay_ms(2000);

}



/// メイン関数
int     main(void) 
{

    AD1PCFG = 0xFFFF;   // ポートA全ディジタルに指定
        TRISB = 0;              //Bポートを出力モードに設定 ポートB     RB5:SDA、RB6:SCLは出力に設定
    CLKDIV = 0;         //CPU Peripheral Clock Ratio = 1:1


        OpenI2C1
        (
                //I2C1CONレジスタの設定
                I2C_ON &        //I2Cモジュール有効   0xFFFF /*I2C module enabled */
                I2C_IDLE_CON & //アイドル」モード中も動作継続   0xDFFF /*continue I2C module in Idle mode */
                I2C_CLK_HLD &   //SCL開放制御ビット(スレーブ動作の場合) 0xEFFF   /*hold clock  */
                I2C_IPMI_DIS &  //インテリジェント周辺管理インターフェース(IPMI)OFF   0xF7FF /*IPMI mode not enabled */
                I2C_7BIT_ADD &  //7ビットアドレスモード   0xFBFF /*I2CADD is 7-bit address */
                I2C_SLW_DIS &   //スルーレート制御無効化  0xFFFF /*Disable Slew Rate Control for 100KHz */
                I2C_SM_DIS &    //SMバス入力スレッショルド無効  0xFEFF /*Disable SM bus specification */
                I2C_GCALL_DIS & //一斉呼び出しアドレス無効  0xFF7F /*Disable General call address. */
                I2C_STR_EN &    //クロックストレッチ有効  0xFFFF /*Enable clock stretching */
                I2C_NACK &              //アクノリッジとしてNACKを送る  0xFFFF /*Transmit 1 to send NACK as acknowledge*/
                I2C_ACK_DIS & //アクノリッジシーケンス有効ビット: アクノリッジシーケンス中ではない  0xFFEF /*Acknowledge condition Idle */
                I2C_RCV_DIS & //受信有効化ビット: 受信シーケンス中ではない  0xFFF7 /*Receive sequence not in progress */
                I2C_STOP_DIS & //ストップ有効化条件化ビット: ストップ条件ではない  0xFFFB /*Stop condition Idle */
                I2C_RESTART_DIS & //リピートスタート条件有効化ビット: リピートスタート条件中ではない  0xFFFD /*Start condition Idle */
                I2C_START_DIS,  //スタート条件有効化ビット: スタート条件中ではない   0xFFFE /*Start condition Idle */

                99                              //I2C1BRGレジスタの設定
                                        //      (Clock /(2*Bus_Fre))-1  //(20000000/(2*100000))-1 = 99   システムクロック:20MHz、 I2Cバスクロック:100KHz
        );
         

        lcd_init();                             // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_clear();                    // 全消去
        sprintf(Buf,"I2C Master !!%c",Space);//arguementがないと遅い  C30のバグ?
        lcd_str(Buf);                   //液晶表示  

        adr_write_cmd = ((adr_slave << 1) & (0b11111110));      //(アドレス + 書き込みコマンド)作成
        adr_read_cmd =  ((adr_slave << 1) | (0b00000001));      //(アドレス + 読み込みコマンド)作成


        delay_ms(3000);
                                
        while(1)
        {
                Func1('A');
                Func1('B');
                Func1('C');
                Func1('D');
        
        }

        return 0;
}


//*************************************************************************
//インクルードファイル    1lcd_lib_C30.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//*************************************************************************

#include "p24FJ64GA002.h"

#define Clock   20000000        // 単位はHzで指定

// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb                 LATBbits.LATB1  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs                  LATBbits.LATB0  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定


void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);


//**************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        __delay32(2*N_msec);    //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);   //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 2000000);       // 1μsecに要するウェイト回数

        _50usec = (unsigned int)(Clock / 2000000 * 50); //50μescに要するウェイト回数

        N_msec = (unsigned long int)(Clock / 2000);             // 1msecに要するウェイト回数
                                                                                                        // = Clock / 2000000*1000

        __delay32(20*N_msec);   //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);    //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}






///************************************************************/
//*  I2C PIC間 1文字送受信 
//*                   スレーブ側  PIC24FJ64GA002   
//************************************************************/
#include "p24FJ64GA002.h"
#include <stdio.h>
#include <stdlib.h>
#include <timer.h>
#include <i2c.h>

#include        "1lcd_lib_C30.h"
#include        "1lcd_lib_c30.c"

/// コンフィギュレーション ビットの設定
_CONFIG1
(
        JTAGEN_OFF &    //JTAGポート: OFF
        GCP_OFF &               //コードプロテクト: OFF
        GWRP_OFF &              //書き込みプロテクト: OFF
        BKBUG_OFF &             //バックグランドデバック: OFF
        COE_OFF &               //クリップオン エミュレーション: OFF 
        ICS_PGx1&               //ICDピンの選択: EMUC/EMUDをPGC1/PGD1と共用
        FWDTEN_OFF              //ウォッチドックタイマ: OFF 
)

_CONFIG2
( 
        IESO_OFF &              // 2速度スタートアップ機能:OFF
//      IESO_ON &               // 2速度スタートアップ機能:ON
        FNOSC_PRI &     //外付け発振子20MHZ PLLなし  → システムクロック:20MHZ
        FCKSM_CSDCMD &  //クロック切替え制御:OFF クロックモニタ:OFF
        OSCIOFNC_OFF &  //OSCO/RC15 function: OSCO or Fosc/2
        IOL1WAY_ON &    //RP Register Protection: Unlimited Writes To RP Registers
//      I2C1SEL_PRI &   //I2C1 pins Select: Use Primary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンSDA1(ピン番号18),SCL1(ピン番号17)を使用する場合
        I2C1SEL_SEC &   //I2C1 pins Select: Use Secondary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンASDA(ピン番号14),ASCL(ピン番号15)を使用する場合
        POSCMOD_HS              //発振回路モード Oscillator Selection:  HS (外付け発振回路 発振周波数レベル:HS)
//      POSCMOD_NONE    //発振回路モード Oscillator Selection:  Primary disabled(内蔵発振回路使用の場合)
)


char Buf[17];   //文字列のバッファー用レジスタ

unsigned int adr_slave = 0xa8;  //送受信相手スレーブのアドレス

char Space = ' ';
        
unsigned char receive_data,send_data;


void delay_ms(unsigned int N)   //ウェイト関数
{
        __delay32(Clock/2000*N);
}

void send_char1(unsigned char send_data)
{
        I2C1TRN = send_data;//マスターへのデータをバッファへ書き込み、書き込み完了後自動的に送信開
                                                //送信完了後もクロックストレッチ制御がある場合はスレーブはSCLをLowにする
                                                // → I2C1CONbits.SCLREL = 0 となっている
        IFS1bits.SI2C1IF = 0;   //スレーブ用割込み制御レジスタIFS1の SI2C1IF割り込みフラグをクリア
        I2C1CONbits.SCLREL = 1; //SCL開放

        IdleI2C1();
}

void _ISR _SI2C1Interrupt(void) //I2C スレーブ割込み関数(マクロ)
{
        if(I2C1STATbits.R_W == 0)       //マスターからの送信モードの場合
        {
                if(I2C1STATbits.D_A == 0)       //受信データがアドレスの場合
                {
                        receive_data = SlaveReadI2C1();         //データを読み出して、データを受信できる状態にする 
                        IdleI2C1();
                }
                else    ////データを受信した場合  
                {
                        receive_data = SlaveReadI2C1(); //

                        switch(receive_data)
                        {
                                case 'A':
                                        send_data = 'a';
                                        break;
                                case 'B':
                                        send_data = 'b';
                                        break;
                                case 'C':
                                        send_data = 'c';
                                        break;
                                case 'D':
                                        send_data = 'd';
                                        break;
                                default:
                                        send_data = '?';
                                        break;
                        }
                        lcd_cmd(0x80);  //1行目先頭へ
                        sprintf(Buf,"receive_data=%c",receive_data);//返信文字を液晶に表示
                        lcd_str(Buf);   //液晶表示 

                        

                }
                I2C1CONbits.SCLREL = 1; 
                IFS1bits.SI2C1IF = 0;   //スレーブ用割込み制御レジスタIFS1の SI2C1IF割り込みフラグをクリア
                                        
        }

        else     //マスターへのデータ送信要求の場合
        {
                lcd_cmd(0xc0);  //2行目へ
                sprintf(Buf,"send_data=%c",send_data);  //返信文字を液晶に表示
                lcd_str(Buf);   //液晶表示 


                I2C1TRN = send_data;//マスターへのデータをバッファへ書き込み、書き込み完了後自動的に送信開
                                                        //送信完了後もクロックストレッチ制御がある場合はスレーブはSCLをLowにする
                                                        // → I2C1CONbits.SCLREL = 0 となっている

                IFS1bits.SI2C1IF = 0;   //スレーブ用割込み制御レジスタIFS1の SI2C1IF割り込みフラグをクリア
                I2C1CONbits.SCLREL = 1; //SCL開放

                while(!I2C1STATbits.P); //      StopI2C1();
        } 

}


/// メイン関数
int     main(void) 
{
        unsigned temp_data;

        AD1PCFG = 0xFFFF;       // ポートA全ディジタルに指定
//      TRISB = 0;              //Bポートを出力モードに設定 ポートB     RB5:SDA、RB6:SCLは出力に設定
        TRISB = 0b0000000001100000;             // この設定はNG //ポートB   RB3:RX 、RB5:SDA、RB6:SCLは入力に、その他は出力に設定
 

        CLKDIV = 0;             //CPU Peripheral Clock Ratio = 1:1

OpenI2C1
(
        //I2C1CONレジスタの設定
        I2C_ON &        //I2Cモジュール有効   0xFFFF /*I2C module enabled */
        I2C_IDLE_CON & //アイドル」モード中も動作継続   0xDFFF /*continue I2C module in Idle mode */
        I2C_CLK_HLD &   //★クロックストレッチ時SCLをLOwに保持する(スレーブモードの場合): SCL開放制御ビット(スレーブ動作の場合) 0xEFFF   /*hold clock  */
        I2C_IPMI_DIS &  //インテリジェント周辺管理 OFF :(IPMI)OFF   0xF7FF /*IPMI mode not enabled */
        I2C_7BIT_ADD &  //7ビットアドレスモード   0xFBFF /*I2CADD is 7-bit address */
        I2C_SLW_DIS &   //スルーレート制御無効化  0xFFFF /*Disable Slew Rate Control for 100KHz */
        I2C_SM_DIS &    //SMバス入力スレッショルド無効  0xFEFF /*Disable SM bus specification */
        I2C_GCALL_DIS & //一斉呼び出しアドレス無効  0xFF7F /*Disable General call address. */
        I2C_STR_EN &    //★クロックストレッチ有効(スレーブモードの場合)  0xFFFF /*Enable clock stretching */
//      I2C_STR_DIS &   //クロックストレッチ無効
        I2C_NACK &              //★受信アクノリッジとしてNACKを送る  0xFFFF /*Transmit 1 to send NACK as acknowledge*/
        I2C_ACK_DIS &   //アクノリッジシーケンス有効ビット: アクノリッジシーケンス中ではない  0xFFEF /*Acknowledge condition Idle */
                                        //アクノリッジシーケンス中はフラグがたつ(?)。アクノリッジシーケンス終了でハードでフラグはクリアされる。
        
        I2C_RCV_EN &    // 受信モード有効                      0x0008 /*Enable receive mode */
//      I2C_RCV_DIS & //受信有効化ビット(I2Cマスタモードの場合): 受信シーケンス中ではない  0xFFF7 /*Receive sequence not in progress */
        I2C_STOP_DIS & //ストップ有効化条件化ビット(I2Cマスタモードの場合): ストップ条件ではない  0xFFFB /*Stop condition Idle */
        I2C_RESTART_DIS & //リピートスタート条件有効化ビット(I2Cマスターモードの場合): リピートスタート条件中ではない  0xFFFD /*Start condition Idle */
        I2C_START_DIS,  //スタート条件有効化ビット: スタート条件中ではない(I2Cマスタモードの場合) 0xFFFE /*Start condition Idle */
        99                              //I2C1BRGレジスタの設定
                                        //      (Clock /(2*Bus_Fre))-1  //(20000000/(2*100000))-1 = 99   システムクロック:20MHz、 I2Cバスクロック:100KHz
);


        I2C1ADD = adr_slave;    //スレーブ(自分)のアドレス

        LATBbits.LATB15 = 1;//消灯


        lcd_init();                             // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_clear();                    // 全消去
        sprintf(Buf,"I2C Slave !!%c",Space);//arguementがないと遅い  C30のバグ?
        lcd_str(Buf);                   //液晶表示  

        delay_ms(1000);


        ConfigIntI2C1(MI2C_INT_OFF  & SI2C_INT_ON & SI2C_INT_PRI_5); 
                //I2Cスレーブ割り込みON(割り込みレベル5)、   //汎用割り込み: レベル0〜レベル7
        EnableIntSI2C1; //割込み許可


        IdleI2C1();                                             // アイドル待ち//

        while(1)        //I2C割込みを待つ
        {
        }
        CloseI2C1();

        return 0;
}


//*************************************************************************
//インクルードファイル    1lcd_lib_C30.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//*************************************************************************

#include "p24FJ64GA002.h"

#define Clock   20000000        // 単位はHzで指定

// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb                 LATBbits.LATB1  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs                  LATBbits.LATB0  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定


void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);



//**************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        __delay32(2*N_msec);    //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);   //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 2000000);       // 1μsecに要するウェイト回数

        _50usec = (unsigned int)(Clock / 2000000 * 50); //50μescに要するウェイト回数

        N_msec = (unsigned long int)(Clock / 2000);             // 1msecに要するウェイト回数
                                                                                                        // = Clock / 2000000*1000

        __delay32(20*N_msec);   //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);    //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}

 

  <動作結果>

マスタ送信文字 → スレーブ返信文字  液晶(上段):マスタ側
        1行目 …… 送信文字
        2行目 …… 受信文字
 液晶(下段):スレーブ側
        1行目 …… 受信文字
        2行目 …… 返信文字
A → a
B → b
C → c
D → d


 



■ PIC間 文字列の送受信
 以下に I2C通信によるPIC間の文字列の送受信の例を紹介します。


(1)C30コンパイラ、 PIC24F

<試作品仕様>

 ・I2C通信によりPIC間の文字列の送受信をおこなう。
 ・I2C通信の主な諸元は以下とする。
  @ 通信速度 …… 100KHz
  A アドレス送信方式 …… 7ビット
  B クロックストレッチ制御 …… 有り
  C マスタからのデータ送信要求終了通知 ……NACK
  D スレーブの受信方式 …… 割込み方式
 ・通信ポート: secondary ポート(ASCL1、ASDA1)を使用
 ・マスター側、スレーブ側各々のPICにはキャラクタ型液晶を接続する。
 ・マスタ側液晶の1行目には送信文字を、2行目には受信文字を表示する
 ・スレーブ側液晶の1行目には受信文字を、2行目には返信文字を表示する。
 ・マスターPICからの送信文字 及びスレーブPICからの返信文字は以下とする。
   <マスタ送信文字>       <スレーブ返信文字>
    $Tokyo Olympic \r   →    $Japan 1964  \r
    $Lio Olympic   \r   →    $Brazil 2016  \r
    $Berlin Olympic\r   →     $German 1936\r
    $How are you? \r    →     $Pardon ?    \r

   
 


<試作品回路図> (→回路図のPDFファイル
 PIC24FJ64GA002をつかった場合の回路図を以下に示します。

              
           

<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています

          

   <プログラム例>

///************************************************************/
//*  I2C  PIC間 文字列送受信
//*                マスター    PIC24FJ64GA002   
//************************************************************/
#include "p24FJ64GA002.h"
#include <stdio.h>
#include <i2c.h>


#include        "1lcd_lib_C30.h"
#include        "1lcd_lib_c30.c"

/// コンフィギュレーション ビットの設定
_CONFIG1
(
        JTAGEN_OFF &    //JTAGポート: OFF
        GCP_OFF &               //コードプロテクト: OFF
        GWRP_OFF &              //書き込みプロテクト: OFF
        BKBUG_OFF &             //バックグランドデバック: OFF
        COE_OFF &               //クリップオン エミュレーション: OFF 
        ICS_PGx1&               //ICDピンの選択: EMUC/EMUDをPGC1/PGD1と共用
        FWDTEN_OFF              //ウォッチドックタイマ: OFF 
)

_CONFIG2
( 
        IESO_OFF &              // 2速度スタートアップ機能:OFF
//      IESO_ON &               // 2速度スタートアップ機能:ON
        FNOSC_PRI &     //外付け発振子20MHZ PLLなし  → システムクロック:20MHZ
        FCKSM_CSDCMD &  //クロック切替え制御:OFF クロックモニタ:OFF
        OSCIOFNC_OFF &  //OSCO/RC15 function: OSCO or Fosc/2
        IOL1WAY_ON &    //RP Register Protection: Unlimited Writes To RP Registers
//      I2C1SEL_PRI &   //I2C1 pins Select: Use Primary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンSDA1(ピン番号18),SCL1(ピン番号17)を使用する場合
        I2C1SEL_SEC &   //I2C1 pins Select: Use Secondary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンASDA(ピン番号14),ASCL(ピン番号15)を使用する場合
        POSCMOD_HS              //発振回路モード Oscillator Selection:  HS (外付け発振回路 発振周波数レベル:HS)
//      POSCMOD_NONE    //発振回路モード Oscillator Selection:  Primary disabled(内蔵発振回路使用の場合)
)


char Tokyo[] =          "$Tokyo Olympic \r";
char Lio[] =            "$Lio Olympic   \r";  
char Berlin[] =         "$Berlin Olympic\r";
char How[] =            "$How are you?  \r";


char Buf[17];   //文字列のバッファー用レジスタ
char Space = ' ';
char* str_ans;
unsigned int ix;
unsigned char data_in[20];
unsigned int adr_slave = 0xa8;  //送受信相手スレーブのアドレス
unsigned int adr_write_cmd,adr_read_cmd;


void delay_ms(unsigned int N)   //ウェイト関数
{
        __delay32(Clock/2000*N);
}

void DataTrans(unsigned char sData)     // 1バイト送信サブ関数
{
        I2C1TRN = sData;// data送信////   MasterWriteI2C1(sData);
        while(I2C1STATbits.TBF);        // 送信終了待ち
        while(I2C1STATbits.ACKSTAT);    // ACK受信待ち

        while(I2C1CONbits.SEN);//@スタート条件ではない  //@+A+B+C+D →     IdleI2C1(); アイドル待ち
        while(I2C1CONbits.PEN);//Aストップ条件ではない
        while(I2C1CONbits.RCEN);//B受信シーケンス中ではない
        while(I2C1CONbits.ACKEN);//C アクノリッジシーケンス中でない
        while(I2C1STATbits.TRSTAT);     //D送信終了まち
}


void write_slave(unsigned int adr_cmd, char* str)       //文字列送信関数
{
        I2C1STATbits.I2COV = 0;                         // エラークリア//
        I2C1CONbits.SEN = 1;    //I2Cバスにスタート条件出力: SCL: 1、 SDA: 1→0      //      StartI2C1();
        while(I2C1CONbits.SEN); //出力完了待ち                //      while(SSPCON2bits.SEN);         //出力完了待ち
        DataTrans(adr_cmd);             //スレーブチップアドレスと書き込み命令

        while(*str)
        {
                DataTrans(*str);        //Slaveへ1バイトのデータ書き込み
                str++;
        } 

        I2C1CONbits.PEN = 1;    //ストップ条件発行(SCL:1、SDA:0→1))      //      StopI2C1();//通信一時停止
        while(I2C1CONbits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる
}



char* read_slave(unsigned adr_cmd)      //文字列受信関数
{
        char* temp_data;

        I2C1CONbits.SEN = 1;    //スタート条件発行(SCL:1、SDA:1→0) //    StartI2C1();
        while(I2C1CONbits.SEN); //出力完了待ち //正常に発行されればハードによりクリアされる
        IFS1bits.MI2C1IF = 0;   //マスター動作時の割込みフラグクリア(割り込みを使った場合は必須)
        DataTrans(adr_cmd);     //(スレーブアドレス + 読み込み)コマンドをスレーブへ送信

        ix = 0;
        while(1)        //文字列データの取得
        {
                I2C1CONbits.RCEN = 1;           //受信許可  
                while(!I2C1STATbits.RBF);       //受信バッファ受信完了を待つ while(DataRdyI2C1());
                data_in[ix] = I2C1RCV;  //1バイトのデータ読み込み  data_in[ix] =  MasterReadI2C1();
        
                if(data_in[ix] == '\r')break;   //データの終端検出
                I2C1CONbits.ACKDT = 0;          //更にデータ送信をスレーブに要求するのでACK=0をセットする        //AckIC1();
                I2C1CONbits.ACKEN = 1;          //ACKDTにセットされている ACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
                while(I2C1CONbits.ACKEN);       //送信完了を待つ //ACKENは送信完了でハードによりクリアされる
                ix++;
        }

        I2C1CONbits.ACKDT = 1;          //スレーブからの文字送信要求は終了なのでNACK=1をセット         //      NotAckI2C1();
                                                                        //vs 更にデータ送信をスレーブに要求する場合は、ACK=0をセットする //AckI2C1();
        I2C1CONbits.ACKEN = 1;          //ACKDTにセットされている NACKかACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
        while(I2C1CONbits.ACKEN);       //送信完了を待つ //ACKENは送信完了でハードによりクリアされる

        I2C1CONbits.PEN = 1;    //ストップ条件発行(SCL:1、SDA:0→1))      StopI2C1();//通信一時停止
        while(I2C1CONbits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる

        ix++;
        data_in[ix] = '\0';     //配列を文字列化
        temp_data = &data_in[0];

        return temp_data;
}



void Func(char* data_trans)             //文字列の送受信 &表示関数
{
                char* temp;

                lcd_clear();
                sprintf(Buf,"%s%c",data_trans,Space);   
                lcd_str(Buf);                   //マスター側液晶表示 
                write_slave(adr_write_cmd,data_trans);  //スレーブへ "$Tokyo Olympic\r" を送信

                temp = read_slave(adr_read_cmd);        //スレーブデータの読み出し
                sprintf(Buf,"%s%c",temp,Space);
                lcd_cmd(0xC0);          //2行目の先頭へ
                lcd_str(Buf);                   //マスター側液晶表示 
        
                delay_ms(2000);

}


/// メイン関数
int     main(void) 
{

    AD1PCFG = 0xFFFF;   // ポートA全ディジタルに指定
        TRISB = 0;              //Bポートを出力モードに設定 ポートB     RB5:SDA、RB6:SCLは出力に設定
    CLKDIV = 0;         //CPU Peripheral Clock Ratio = 1:1


        OpenI2C1
        (
                //I2C1CONレジスタの設定
                I2C_ON &        //I2Cモジュール有効   0xFFFF /*I2C module enabled */
                I2C_IDLE_CON & //アイドル」モード中も動作継続   0xDFFF /*continue I2C module in Idle mode */
                I2C_CLK_HLD &   //SCL開放制御ビット(スレーブ動作の場合) 0xEFFF   /*hold clock  */
                I2C_IPMI_DIS &  //インテリジェント周辺管理インターフェース(IPMI)OFF   0xF7FF /*IPMI mode not enabled */
                I2C_7BIT_ADD &  //7ビットアドレスモード   0xFBFF /*I2CADD is 7-bit address */
                I2C_SLW_DIS &   //スルーレート制御無効化  0xFFFF /*Disable Slew Rate Control for 100KHz */
                I2C_SM_DIS &    //SMバス入力スレッショルド無効  0xFEFF /*Disable SM bus specification */
                I2C_GCALL_DIS & //一斉呼び出しアドレス無効  0xFF7F /*Disable General call address. */
                I2C_STR_EN &    //クロックストレッチ有効  0xFFFF /*Enable clock stretching */
                I2C_NACK &              //アクノリッジとしてNACKを送る  0xFFFF /*Transmit 1 to send NACK as acknowledge*/
                I2C_ACK_DIS & //アクノリッジシーケンス有効ビット: アクノリッジシーケンス中ではない  0xFFEF /*Acknowledge condition Idle */
                I2C_RCV_DIS & //受信有効化ビット: 受信シーケンス中ではない  0xFFF7 /*Receive sequence not in progress */
                I2C_STOP_DIS & //ストップ有効化条件化ビット: ストップ条件ではない  0xFFFB /*Stop condition Idle */
                I2C_RESTART_DIS & //リピートスタート条件有効化ビット: リピートスタート条件中ではない  0xFFFD /*Start condition Idle */
                I2C_START_DIS,  //スタート条件有効化ビット: スタート条件中ではない   0xFFFE /*Start condition Idle */

                99                              //I2C1BRGレジスタの設定
                                        //      (Clock /(2*Bus_Fre))-1  //(20000000/(2*100000))-1 = 99   システムクロック:20MHz、 I2Cバスクロック:100KHz
        );
         

        lcd_init();                             // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_clear();                    // 全消去
        sprintf(Buf,"I2C Master !!%c",Space);//arguementがないと遅い  C30のバグ?
        lcd_str(Buf);                   //液晶表示  

        adr_write_cmd = ((adr_slave << 1) & (0b11111110));      //(アドレス + 書き込みコマンド)作成
        adr_read_cmd =  ((adr_slave << 1) | (0b00000001));      //(アドレス + 読み込みコマンド)作成

        delay_ms(3000);
                                
        while(1)
        {
                Func(Tokyo);    //      "$Tokyo Olympic \r";    
                Func(Lio);              //  "$Lio Olympic   \r"; 
                Func(Berlin);   //  "$Berlin Olympic\r";
                Func(How);              //      "$How are you?  \r";
        }

        return 0;
}


//*************************************************************************
//インクルードファイル    1lcd_lib_C30.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等でに変更したものです。
//*************************************************************************

#include "p24FJ64GA002.h"

#define Clock   20000000        // 単位はHzで指定

// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb                 LATBbits.LATB1  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs                  LATBbits.LATB0  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定


void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);


//**************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        __delay32(2*N_msec);    //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);   //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 2000000);       // 1μsecに要するウェイト回数

        _50usec = (unsigned int)(Clock / 2000000 * 50); //50μescに要するウェイト回数

        N_msec = (unsigned long int)(Clock / 2000);             // 1msecに要するウェイト回数
                                                                                                        // = Clock / 2000000*1000

        __delay32(20*N_msec);   //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);    //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}





///************************************************************/
//*  I2C PIC間 文字列送受信 
//*                   スレーブ側  PIC24FJ64GA002   
//************************************************************/
#include "p24FJ64GA002.h"
#include <stdio.h>
#include <stdlib.h>
#include <timer.h>
#include <i2c.h>

#include        "1lcd_lib_C30.h"
#include        "1lcd_lib_c30.c"

/// コンフィギュレーション ビットの設定
_CONFIG1
(
        JTAGEN_OFF &    //JTAGポート: OFF
        GCP_OFF &               //コードプロテクト: OFF
        GWRP_OFF &              //書き込みプロテクト: OFF
        BKBUG_OFF &             //バックグランドデバック: OFF
        COE_OFF &               //クリップオン エミュレーション: OFF 
        ICS_PGx1&               //ICDピンの選択: EMUC/EMUDをPGC1/PGD1と共用
        FWDTEN_OFF              //ウォッチドックタイマ: OFF 
)

_CONFIG2
( 
        IESO_OFF &              // 2速度スタートアップ機能:OFF
//      IESO_ON &               // 2速度スタートアップ機能:ON
        FNOSC_PRI &     //外付け発振子20MHZ PLLなし  → システムクロック:20MHZ
        FCKSM_CSDCMD &  //クロック切替え制御:OFF クロックモニタ:OFF
        OSCIOFNC_OFF &  //OSCO/RC15 function: OSCO or Fosc/2
        IOL1WAY_ON &    //RP Register Protection: Unlimited Writes To RP Registers
//      I2C1SEL_PRI &   //I2C1 pins Select: Use Primary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンSDA1(ピン番号18),SCL1(ピン番号17)を使用する場合
        I2C1SEL_SEC &   //I2C1 pins Select: Use Secondary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンASDA(ピン番号14),ASCL(ピン番号15)を使用する場合
        POSCMOD_HS              //発振回路モード Oscillator Selection:  HS (外付け発振回路 発振周波数レベル:HS)
//      POSCMOD_NONE    //発振回路モード Oscillator Selection:  Primary disabled(内蔵発振回路使用の場合)
)

char Tokyo[] =          "$Tokyo Olympic \r";
char Lio[] =            "$Lio Olympic   \r";  
char Berlin[] =         "$Berlin Olympic\r";
char How[] =            "$How are you?  \r";

char Japan[] =          "$Japan 1964    \r";
char Brazil[] =         "$Brazil 2016   \r";
char German[] =         "$German 1936   \r";
char Pardon[] =         "$Pardon ?      \r"; 

char Buf[17];   //文字列のバッファー用レジスタ

unsigned int adr_slave = 0xa8;  //送受信相手スレーブのアドレス

char data[17];
char* str;
char* strx;
char Space = ' ';
int ix;


void delay_ms(unsigned int N)   //ウェイト関数
{
        __delay32(Clock/2000*N);
}


int my_strcmp(char str1[],char str2[])  //文字列の比較関数 
{                                                                               // <string.h>のstrcmp()と同じく文字列が一致した時だけ0を返す                                                                               
        int     n1,n2,Result,i;                                 //c30のstrcmp()が極めて遅い(バグ?)ので自作
        char Buf1[20];
        char Buf2[20];

        sprintf(Buf1,"%s",str1);
        sprintf(Buf2,"%s",str2);

        n1 = strlen(str1);      //ヌル文字は除いた文字数の取得
        n2 = strlen(str2);
        if((n1 != n2) || (n1 > 19) || (n2 > 19))Result = 1;
        else
        {
                for(i = 0; i < n1; i++)
                {
                        if((unsigned int)Buf1[i] != (unsigned int)Buf2[i])
                        {
                                Result = 1;
                                break;
                        }
                        Result = 0;
                }
        }
        return Result;  
}



void _ISR _SI2C1Interrupt(void) //I2C スレーブ割込み関数(マクロ)
{
        unsigned char temp_data;
        char* temp_char;

        if(I2C1STATbits.R_W == 0)       //マスターからの送信モードの場合
        {
                if(I2C1STATbits.D_A == 0)       //受信データがアドレスの場合
                {
                        temp_data = SlaveReadI2C1();    //データを読み出して、データを受信できる状態にする temp_data = I2C1RCV
                        IdleI2C1();
                }
                else    ////データを受信した場合  
                {
                        temp_data = SlaveReadI2C1();    //temp_data = I2C1RCV;

                        switch(temp_data)
                        {
                                case '$':
                                        ix = 0;
                                        data[ix] = temp_data;   //受信文字を記憶する

                                        break;
                                case '\r':
                                        ix++;
                                        data[ix] = '\r';
                                        data[ix+1] = '\0';              //data[ ]を文字列化
                                        str = &data[0];
        
                                        if(my_strcmp(str,Tokyo) == 0)strx = Japan;
                                        else if(my_strcmp(str,Lio) == 0)strx = Brazil;
                                        else if(my_strcmp(str,Berlin) == 0)strx = German;
                                        else strx = Pardon;

                                        lcd_cmd(0x80);  //1行目先頭へ
                                        sprintf(Buf,"%s%c",str,Space);  //返信文字を液晶に表示
                                        lcd_str(Buf);                   //液晶表示 
                                
        
                                        break;
                                default:
                                        ix++;
                                        data[ix] = temp_data;   //受信文字を記憶する
                                
                                        break;
                        }
                }
        
                I2C1CONbits.SCLREL = 1; 
                IFS1bits.SI2C1IF = 0;   //スレーブ用割込み制御レジスタIFS1の SI2C1IF割り込みフラグをクリア
                                        
        }

        else     //マスターへのデータ送信要求の場合
        {
                lcd_cmd(0xC0);  //1行目先頭へ
                sprintf(Buf,"%s%c",strx,Space); //返信文字を液晶に表示
                lcd_str(Buf);                   //液晶表示 

                while(1)        //送信要求終了(NACK)を受信するまで繰り返す 
                {
                        I2C1TRN = *strx;        //マスターへのデータをバッファへ書き込み、書き込み完了後自動的に送信開
                                                //送信完了後もクロックストレッチ制御がある場合はスレーブはSCLをLowにする
                                                // → I2C1CONbits.SCLREL = 0 となっている

                        I2C1CONbits.SCLREL = 1; //SCL開放
                        IFS1bits.SI2C1IF = 0;   //スレーブ用割込み制御レジスタIFS1の SI2C1IF割り込みフラグをクリア

                        if(I2C1STATbits.P == 1)break;   //Nack受信→ストップ信号受信の場合
                        delay_ms(3);            //2msec程度の遅れは必要
                        strx++;
                };
        } 
}


/// メイン関数
int     main(void) 
{
        unsigned temp_data;

        AD1PCFG = 0xFFFF;       // ポートA全ディジタルに指定
//      TRISB = 0;              //Bポートを出力モードに設定 ポートB     RB5:SDA、RB6:SCLは出力に設定
        TRISB = 0b0000000001100000;             // この設定はNG //ポートB   RB3:RX 、RB5:SDA、RB6:SCLは入力に、その他は出力に設定
 

        CLKDIV = 0;             //CPU Peripheral Clock Ratio = 1:1

OpenI2C1
(
        //I2C1CONレジスタの設定
        I2C_ON &        //I2Cモジュール有効   0xFFFF /*I2C module enabled */
        I2C_IDLE_CON & //アイドル」モード中も動作継続   0xDFFF /*continue I2C module in Idle mode */
        I2C_CLK_HLD &   //★クロックストレッチ時SCLをLOwに保持する(スレーブモードの場合): SCL開放制御ビット(スレーブ動作の場合) 0xEFFF   /*hold clock  */
        I2C_IPMI_DIS &  //インテリジェント周辺管理 OFF :(IPMI)OFF   0xF7FF /*IPMI mode not enabled */
        I2C_7BIT_ADD &  //7ビットアドレスモード   0xFBFF /*I2CADD is 7-bit address */
        I2C_SLW_DIS &   //スルーレート制御無効化  0xFFFF /*Disable Slew Rate Control for 100KHz */
        I2C_SM_DIS &    //SMバス入力スレッショルド無効  0xFEFF /*Disable SM bus specification */
        I2C_GCALL_DIS & //一斉呼び出しアドレス無効  0xFF7F /*Disable General call address. */
        I2C_STR_EN &    //★クロックストレッチ有効(スレーブモードの場合)  0xFFFF /*Enable clock stretching */
//      I2C_STR_DIS &   //クロックストレッチ無効
        I2C_NACK &              //★受信アクノリッジとしてNACKを送る  0xFFFF /*Transmit 1 to send NACK as acknowledge*/
        I2C_ACK_DIS &   //アクノリッジシーケンス有効ビット: アクノリッジシーケンス中ではない  0xFFEF /*Acknowledge condition Idle */
                                        //アクノリッジシーケンス中はフラグがたつ(?)。アクノリッジシーケンス終了でハードでフラグはクリアされる。
        
        I2C_RCV_EN &    // 受信モード有効                      0x0008 /*Enable receive mode */
//      I2C_RCV_DIS & //受信有効化ビット(I2Cマスタモードの場合): 受信シーケンス中ではない  0xFFF7 /*Receive sequence not in progress */
        I2C_STOP_DIS & //ストップ有効化条件化ビット(I2Cマスタモードの場合): ストップ条件ではない  0xFFFB /*Stop condition Idle */
        I2C_RESTART_DIS & //リピートスタート条件有効化ビット(I2Cマスターモードの場合): リピートスタート条件中ではない  0xFFFD /*Start condition Idle */
        I2C_START_DIS,  //スタート条件有効化ビット: スタート条件中ではない(I2Cマスタモードの場合) 0xFFFE /*Start condition Idle */
        99                              //I2C1BRGレジスタの設定
                                        //      (Clock /(2*Bus_Fre))-1  //(20000000/(2*100000))-1 = 99   システムクロック:20MHz、 I2Cバスクロック:100KHz
);


        I2C1ADD = adr_slave;    //スレーブ(自分)のアドレス

        LATBbits.LATB15 = 1;//消灯


        lcd_init();                             // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_clear();                    // 全消去
        sprintf(Buf,"I2C Slave !!%c",Space);//arguementがないと遅い  C30のバグ?
        lcd_str(Buf);                   //液晶表示  


        delay_ms(1000);


        ConfigIntI2C1(MI2C_INT_OFF  & SI2C_INT_ON & SI2C_INT_PRI_5); 
                //I2Cスレーブ割り込みON(割り込みレベル5)、   //汎用割り込み: レベル0〜レベル7
        EnableIntSI2C1; //割込み許可


        IdleI2C1();                                             // アイドル待ち//

        while(1)        //I2C割込みを待つ
        {
        }
        CloseI2C1();

        return 0;
}



//*************************************************************************
//インクルードファイル    1lcd_lib_C30.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等でに変更したものです。
//*************************************************************************

#include "p24FJ64GA002.h"

#define Clock   20000000        // 単位はHzで指定

// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb                 LATBbits.LATB1  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs                  LATBbits.LATB0  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定


void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);


//**************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        __delay32(2*N_msec);    //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);   //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 2000000);       // 1μsecに要するウェイト回数

        _50usec = (unsigned int)(Clock / 2000000 * 50); //50μescに要するウェイト回数

        N_msec = (unsigned long int)(Clock / 2000);             // 1msecに要するウェイト回数
                                                                                                        // = Clock / 2000000*1000

        __delay32(20*N_msec);   //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);    //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}

<動作結果>

マスター側送信文字列 → スレーブ側返信文字列 液晶(上段): マスター側
        1行目 …… 送信文字列
        2行目 …… 受信文字列
液晶(下段): スレーブ側
        1行目 …… 受信文字列
        2行目 …… 返信文字列
$Tokyo Olympic \r   → $Japan 1964 \r
$Lio Olympic   \r  → $Brazil 2016  \r
$Berlin Olympic\r   →  $German 1936\r
$How are you?  \r  →  $Pardon ?    \r

■  I2C通信 外付けEEPROM 書込み
    (電源再投入による書込みデータの読み出し確認)   

 以下に I2C通信によりる外付けEEPROM読み書きの例を紹介します。

(1) PIC24FJ64GA002  コンパイラ C30

<試作品仕様>
 ・I2C通信により EEPROMと読み書きをおこなう
 ・I2C通信の主な諸元は以下とする。
   @ 通信速度 …… 100KHz
   A アドレス送信方式 …… 7ビット
   B マスタからのデータ送信要求終了通知 ……NACK
 ・通信ポート: secondary ポート(ASCL1、ASDA1)を使用
 ・PICにはキャラクタ型液晶を接続する。
 ・書込みデータの選択はモーメンタリーの押しボタンスイッチとする。選択された書込みデータは液晶の1行目に順次表示されること。
 ・別途設ける書込み用モーメンタリーボタンを押すと液晶の1行目に表示されているデータ(文字列)がEEPROMにメモリされること。
  データは同じアドレスに上書きするものとする。
 ・EEPROMに書込むデータは以下とする。
  @ I am a dragon\r
  A I am a cat\r
  B I am a bird\r
  C I am a horse\r
 ・電源を投入した時の液晶初期画面に、EEPROMに書込まれたデータを読み出して液晶の2行目に表示すること
  例  
    EEPROM Initial =     …… 1行目
    I am a cat■        …… 2行目
  


 <試作品回路図>(→回路図のPDFファイル






<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています





   <プログラム例>

///************************************************************/
//*  I2C通信  EEPROM読み書き
//*      (電源 OFF → ON で、EEPROM書き込みデータを読み出して確認)         PIC24FJ64GA002   
//************************************************************/
#include <p24FJ64GA002.h>
#include <stdio.h>
#include <timer.h>
#include <string.h>
#include <i2c.h>

#include "1lcd_lib_C30.h"
#include "1lcd_lib_c30.c"

/// コンフィギュレーション ビットの設定
_CONFIG1
(
        JTAGEN_OFF &    //JTAGポート: OFF
        GCP_OFF &               //コードプロテクト: OFF
        GWRP_OFF &              //書き込みプロテクト: OFF
        BKBUG_OFF &             //バックグランドデバック: OFF
        COE_OFF &               //クリップオン エミュレーション: OFF 
        ICS_PGx1&               //ICDピンの選択: EMUC/EMUDをPGC1/PGD1と共用
        FWDTEN_OFF              //ウォッチドックタイマ: OFF 
)

_CONFIG2
( 
        IESO_OFF &              // 2速度スタートアップ機能:OFF
//      IESO_ON &               // 2速度スタートアップ機能:ON
        FNOSC_PRI &     //外付け発振子20MHZ PLLなし  → システムクロック:20MHZ
        FCKSM_CSDCMD &  //クロック切替え制御:OFF クロックモニタ:OFF
        OSCIOFNC_OFF &  //OSCO/RC15 function: OSCO or Fosc/2
        IOL1WAY_ON &    //RP Register Protection: Unlimited Writes To RP Registers
//      I2C1SEL_PRI &   //I2C1 pins Select: Use Primary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンSDA1(ピン番号18),SCL1(ピン番号17)を使用する場合
        I2C1SEL_SEC &   //I2C1 pins Select: Use Secondary I2C1 pins
                                        //I2C通信のSDA、SCL: ピンASDA(ピン番号14),ASCL(ピン番号15)を使用する場合
        POSCMOD_HS              //発振回路モード Oscillator Selection:  HS (外付け発振回路 発振周波数レベル:HS)
//      POSCMOD_NONE    //発振回路モード Oscillator Selection:  Primary disabled(内蔵発振回路使用の場合)
)

char Buf[17];   //文字列のバッファー用レジスタ
char tempBuf1[17];
char* str;
char Space = ' ';
unsigned int swCount_Memory = 0,swCount_Select = 0;
char* str_read;
unsigned int ix;
unsigned char data_in[20];

char data_eeprom;

unsigned int adr_chip = 0x00;  //EEPROMのchipアドレス
unsigned int adr_write_cmd,adr_read_cmd;
unsigned int adr_eeprom = 0;    //書き込みするEEPROMの先頭番地

char cat[] = "I am a cat\r";            //
char bird[] = "I am a bird\r";  // 
char horse[] = "I am a horse\r";        //
char dragon[] = "I am a dragon\r";      // 

char Hellow[] = "Hellow"; 


void delay_ms(unsigned int N)   //ウェイト関数
{
        __delay32(Clock/2000*N);
}

int my_strcmp(char str1[],char str2[])  //文字列の比較関数 
{                                                                               // <string.h>のstrcmp()と同じく文字列が一致した時だけ0を返す                                                                               
        int     n1,n2,Result,i;                                 //c30のstrcmp()が極めて遅い(バグ?)ので自作
        char Buf1[20];
        char Buf2[20];

        sprintf(Buf1,"%s",str1);
        sprintf(Buf2,"%s",str2);

        n1 = strlen(str1);      //ヌル文字は除いた文字数の取得
        n2 = strlen(str2);
        if((n1 != n2) || (n1 > 19) || (n2 > 19))Result = 1;
        else
        {
                for(i = 0; i < n1; i++)
                {
                        if((unsigned int)Buf1[i] != (unsigned int)Buf2[i])
                        {
                                Result = 1;
                                break;
                        }
                        Result = 0;
                }
        }
        return Result;  
}


void DataTrans(unsigned char sData)     // 1バイト送信サブ関数
{
        I2C1TRN = sData;// data送信////   MasterWriteI2C1(sData);
 
//       while(I2C1STATbits.TBF);        // 送信終了待ち//このコードがあると書き込み時無限待ちとなることがある
                while(I2C1STATbits.ACKSTAT);    // ACK受信待ち 

        while(I2C1CONbits.SEN);//@スタート条件ではない  //@+A+B+C+D →     IdleI2C1(); アイドル待ち
        while(I2C1CONbits.PEN);//Aストップ条件ではない
        while(I2C1CONbits.RCEN);//B受信シーケンス中ではない
        while(I2C1CONbits.ACKEN);//C アクノリッジシーケンス中でない
        while(I2C1STATbits.TRSTAT);     //D送信終了まち

}

        

void write_ext_eeprom(unsigned int cmd, int adr, char* str)       //文字列送信関数
{
        I2C1STATbits.I2COV = 0;                         // エラークリア//
        I2C1CONbits.SEN = 1;    //I2Cバスにスタート条件出力: SCL: 1、 SDA: 1→0      //      StartI2C1();
        while(I2C1CONbits.SEN); //出力完了待ち                //      while(SSPCON2bits.SEN);         //出力完了待ち

        DataTrans(cmd);             //EEPROMのアドレスと書き込み命令

        DataTrans((unsigned char)(adr >> 8));           //書き込み出す先頭アドレスの上位アドレス出力

        DataTrans((unsigned char)(adr & 0xFF));         //書き込み出す先頭アドレスの下位アドレス出力


        while(*str)
        {
                DataTrans(*str);        //EEPROM(Slave)へ1バイトのデータ書き込み
                str++;
        
                delay_ms(8);            //8msec 書き込み完了待ち  6msecはNG

        } 


        I2C1CONbits.PEN = 1;    //ストップ条件発行(SCL:1、SDA:0→1))      //      StopI2C1();//通信一時停止
        while(I2C1CONbits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる

}



char* read_ext_eeprom(unsigned int cmd, int adr)      //文字列受信関数
{
        char* temp_data ;

        I2C1CONbits.SEN = 1;    //スタート条件発行(SCL:1、SDA:1→0) //    StartI2C1();
        while(I2C1CONbits.SEN); //出力完了待ち //正常に発行されればハードによりクリアされる
        IFS1bits.MI2C1IF = 0;   //マスター動作時の割込みフラグクリア(割り込みを使った場合は必須)

        DataTrans(cmd);     //(スレーブアドレス + 読み込み)コマンドをスレーブへ送信
        DataTrans((unsigned char)(adr >> 8));           //上位アドレス出力
        DataTrans((unsigned char)(adr & 0xFF));         //下位アドレス出力

        I2C1CONbits.RSEN = 1;   //      RestartI2C1();  //リスタート条件出力
        while(I2C1CONbits.RSEN);                //出力完了待ち
        DataTrans(cmd | 0x01);                  //チップアドレスと制御データ出力

        ix = 0;
        while(1)        //文字列データの取得
        {
                I2C1CONbits.RCEN = 1;           //受信許可  
                while(!I2C1STATbits.RBF);       //受信バッファ受信完了を待つ while(DataRdyI2C1());
                data_in[ix] = I2C1RCV;  //1バイトのデータ読み込み  data_in[ix] =  MasterReadI2C1();
        if((data_in[ix] == '\r') || (ix >= 16))break;   //データの終端検出
                I2C1CONbits.ACKDT = 0;          //更にデータ送信をスレーブに要求するのでACK=0をセットする        //AckIC1();
                I2C1CONbits.ACKEN = 1;          //ACKDTにセットされている ACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
                while(I2C1CONbits.ACKEN);       //送信完了を待つ //ACKENは送信完了でハードによりクリアされる
                ix++;

        }

        if(ix < 16)
        {
                I2C1CONbits.ACKDT = 1;          //スレーブからの文字送信要求は終了なのでNACK=1をセット         //      NotAckI2C1();
                                                                                        //vs 更にデータ送信をスレーブに要求する場合は、ACK=0をセットする //AckI2C1();
                I2C1CONbits.ACKEN = 1;          //ACKDTにセットされている NACKかACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
        while(I2C1CONbits.ACKEN);       //送信完了を待つ //ACKENは送信完了でハードによりクリアされる

        I2C1CONbits.PEN = 1;    //ストップ条件発行(SCL:1、SDA:0→1))      StopI2C1();//通信一時停止
        while(I2C1CONbits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる

                ix++;
                data_in[ix] = '\0';     //配列を文字列化
                temp_data = &data_in[0];
        }
        else temp_data = "No Data";

        return temp_data;
}


void sw_detect()        //スイッチ検出
{
        // 文字列の選択
        if(PORTBbits.RB10 == 0)swCount_Select++;        //文字列選択SWがおされたことを検出
        else swCount_Select = 0;                                        //スイッチが離れたならカウントをリセット

        if(swCount_Select == 4)         //検出4回 → スイッチが押されたと判断
        {
                if(my_strcmp(str,dragon) == 0)str = cat;        //文字列の比較
                else if(my_strcmp(str,cat) == 0)str = bird;
                else if(my_strcmp(str,bird) == 0)str = horse;
                else    str = dragon;

                lcd_clear();    
                lcd_cmd(0x80);          //1行目へ
                sprintf(tempBuf1,"%s%c",str,Space);
                lcd_str(tempBuf1);      //液晶表示
                lcd_cmd(0xc0);
                lcd_str("                ");
        }
        if(swCount_Select >= 5)swCount_Select = 5;      //連続的に押された場合のオーバーフロー対策

        //EEPROMへの書き込み
        if(PORTBbits.RB11 == 0)swCount_Memory++;        //EEPROM記憶SWがおされた場合
        else swCount_Memory = 0;
        if(swCount_Memory == 4)
        {
                lcd_cmd(0xc0);
                lcd_str("Recorded        ");

                write_ext_eeprom(adr_write_cmd,adr_eeprom,str); //EEPROMのadr_EEPROM番地に 文字列str を書き込む
        }
        if(swCount_Memory >= 5)swCount_Memory = 5;
}


/// メイン関数
int     main(void) 
{
        AD1PCFG = 0xFFFF;   // ポートA全ディジタルに指定
        TRISB = 0b0000111100000000;     //Bポート: RB8(SCL)、RB9(SDA)、RB10(文字選択SW)、RB11(書き込みSW)を入力モードに、その他は出力モードに設定 
        CLKDIV = 0;         //CPU Peripheral Clock Ratio = 1:1
        OpenI2C1
        (
                //I2C1CONレジスタの設定
                I2C_ON &        //I2Cモジュール有効   0xFFFF /*I2C module enabled */
                I2C_IDLE_CON & //アイドル」モード中も動作継続   0xDFFF /*continue I2C module in Idle mode */
                I2C_CLK_HLD &   //SCL開放制御ビット(スレーブ動作の場合) 0xEFFF   /*hold clock  */
                I2C_IPMI_DIS &  //インテリジェント周辺管理インターフェース(IPMI)OFF   0xF7FF /*IPMI mode not enabled */
                I2C_7BIT_ADD &  //7ビットアドレスモード   0xFBFF /*I2CADD is 7-bit address */
                I2C_SLW_DIS &   //スルーレート制御無効化  0xFFFF /*Disable Slew Rate Control for 100KHz */
                I2C_SM_DIS &    //SMバス入力スレッショルド無効  0xFEFF /*Disable SM bus specification */
                I2C_GCALL_DIS & //一斉呼び出しアドレス無効  0xFF7F /*Disable General call address. */
                I2C_STR_EN &    //クロックストレッチ有効  0xFFFF /*Enable clock stretching */
                I2C_NACK &              //アクノリッジとしてNACKを送る  0xFFFF /*Transmit 1 to send NACK as acknowledge*/
                I2C_ACK_DIS & //アクノリッジシーケンス有効ビット: アクノリッジシーケンス中ではない  0xFFEF /*Acknowledge condition Idle */
                I2C_RCV_DIS & //受信有効化ビット: 受信シーケンス中ではない  0xFFF7 /*Receive sequence not in progress */
                I2C_STOP_DIS & //ストップ有効化条件化ビット: ストップ条件ではない  0xFFFB /*Stop condition Idle */
                I2C_RESTART_DIS & //リピートスタート条件有効化ビット: リピートスタート条件中ではない  0xFFFD /*Start condition Idle */
                I2C_START_DIS,  //スタート条件有効化ビット: スタート条件中ではない   0xFFFE /*Start condition Idle */
                99                              //I2C1BRGレジスタの設定
                                                //(Clock /(2*Bus_Fre))-1  //(20000000/(2*100000))-1 = 99   システムクロック:20MHz、 I2Cバスクロック:100KHz
        );

                adr_write_cmd = ((0xa0 | (adr_chip << 1)) & (0b11111110));      //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0

                adr_read_cmd =  ((0xa0 | (adr_chip << 1)) | (0b00000001));      //(アドレス + 読み込みコマンド)作成 R/Wビット: 読込み=1

                lcd_init();                             // LCD初期化
                lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

                lcd_clear();                    // 全消去
                sprintf(Buf,"I2C Start !!%c",Space);//arguementがないと遅い  C30のバグ?
                lcd_str(Buf);                   //液晶表示 

                delay_ms(2000);

        lcd_clear();                    // 全消去
        lcd_cmd(0x80);  //1行目へ
        lcd_str("EEPROM Initial =");
        str_read = Hellow;
        str_read = read_ext_eeprom(adr_write_cmd,adr_eeprom);   //EEPROMのadr_EEPROM番地からデータ(1バイト)を読み出す
        sprintf(Buf,"%s%c",str_read,Space);
        lcd_cmd(0xc0);  //2行目へ
        lcd_str(Buf);                   //液晶表示 

        while(1)        //
        {
                sw_detect();    //スイッチの動作検出
                delay_ms(10);   //スイッチのチャタリングによる誤動作防止
        }
        CloseI2C1(); 

        return 0;

}




//*************************************************************************
//インクルードファイル    1lcd_lib_C30.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等でに変更したものです。
//*************************************************************************

#include "p24FJ64GA002.h"

#define Clock   20000000        // 単位はHzで指定

// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //LCDのDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_stb                 LATBbits.LATB1  //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定  
#define lcd_rs                  LATBbits.LATB0  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定


void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);




//**************************************************************************
//インクルードファイル    1lcd_lib_C30.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C30コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C30コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C30.h"
unsigned int _1usec;    // 1μsec待つに必要なウェイト回数
unsigned int _50usec;   //50μsec待つに必要なウェイト回数
unsigned long N_msec;   // 1msec待つに必要なウェイト回数



//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        __delay32(_1usec);              //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
                        
        __delay32(_1usec);              // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        __delay32(_50usec);             //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        __delay32(2*N_msec);    //      2msec待ち
        else
        __delay32(_50usec);             //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
//      __delay32(15*N_msec);   //15msecウェイト
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        _1usec =(unsigned int)( Clock / 2000000);       // 1μsecに要するウェイト回数

        _50usec = (unsigned int)(Clock / 2000000 * 50); //50μescに要するウェイト回数

        N_msec = (unsigned long int)(Clock / 2000);             // 1msecに要するウェイト回数
                                                                                                        // = Clock / 2000000*1000

        __delay32(20*N_msec);   //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(5*N_msec);    //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        __delay32(N_msec);              //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}

<動作結果>

   動作結果を以下に示します。

データ モード 液晶画面
     なし       EEPROMにデータがない場合に
 電源を投入した時の液晶初期画面
   I am a dragon\r      液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面 
   I am a cat\r    液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面
   I am a bird\r    液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面
   I am a horse\r    液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面




I2C通信 外付けEEPROM 読み書き

(2) PIC18F452  コンパイラ C18

<試作品仕様>
 ・I2C通信により EEPROMと読み書きをおこなう
 ・I2C通信の主な諸元は以下とする。
   @ 通信速度 …… 400KHz
   A アドレス送信方式 …… 7ビット
   B マスタからのデータ送信要求終了通知 ……NACK
  ・PICにはキャラクタ型液晶を接続する。
 ・書込みデータの選択はモーメンタリーの押しボタンスイッチとする。選択された書込みデータは液晶の1行目に順次表示されること。
 ・別途設ける書込み用モーメンタリーボタンを押すと液晶の1行目に表示されているデータ(文字列)がEEPROMにメモリされること。
  データは同じアドレスに上書きするものとする。
 ・EEPROMに書込むデータは以下とする。
  @ I am a dragon\r
  A I am a cat\r
  B I am a bird\r
  C I am a horse\r
 ・電源を投入した時の液晶初期画面に、EEPROMに書込まれたデータを読み出して液晶の2行目に表示すること
  例  
    EEPROM Initial =     …… 1行目
    I am a cat■        …… 2行目



 <試作品回路図>(→回路図のPDFファイル


<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています



   <プログラム例>
///************************************************************/
//*  I2C通信  EEPROM読み書き
//*      (電源 OFF → ON で、EEPROM書き込みデータを読み出して確認)         PI18F452   // C18コンパイラ   
//************************************************************/
#include <p18F452.h>
#include <stdio.h>

#include <string.h>
#include <i2c.h>

#include "1lcd_lib_C18.h"
#include "1lcd_lib_c18.c"

/* コンフィギュレーションの設定 */

#pragma config OSC = HS      // fosc = 20MHz 
#pragma config WDT = OFF
#pragma config LVP = OFF

char Buf[17];   //文字列のバッファー用レジスタ
char tempBuf1[17];
char* str;

unsigned int swCount_Memory = 0,swCount_Select = 0;
char* str_read;
unsigned int ix;
char data_in[20];

unsigned int adr_chip = 0x00;  //EEPROMのchipアドレス
unsigned int adr_write_cmd,adr_read_cmd;
unsigned int adr_eeprom = 0;    //書き込みするEEPROMの先頭番地

char cat[] = "I am a cat\r";            //
char bird[] = "I am a bird\r";  // 
char horse[] = "I am a horse\r";        //
char dragon[] = "I am a dragon\r";      // 

char Hellow[] = "Hellow"; 
char NoData[] = "No Data_";


void delay_ms (long int cycle)  // CCSコンパイラと同じ delay_ms(long int) 関数を設計
{
        long int i = 0;
        for (i = 0; i < cycle*5; i++)Delay1KTCYx(1);     // 0.05μsec × 4 × 1000 × 5 = 1msec
}


void lcd_printf(char* strx)      //液晶表示補助関数
{
   while(*strx) //終端の '\0'を検出するまで
        {
                lcd_data(*strx);         // 1文字表示
                strx++;
        } 
}


void DataTrans(unsigned char data)      
{
        WriteI2C(data);                                 //データ出力実行
        IdleI2C();                                              //バスアイドル待ち
}


void write_ext_eeprom(unsigned int cmd, int adr, char* str)       //文字列送信関数
{
        SSPCON2bits.SEN = 1;   //I2Cバスにスタート条件出力: SCL: 1、 SDA: 1→0  
        while(SSPCON2bits.SEN); //出力完了待ち 

        DataTrans(cmd);             //EEPROMのアドレスと書き込み命令
        DataTrans((unsigned char)(adr >> 8));   //書き込み出す先頭アドレスの上位アドレス出力
        DataTrans((unsigned char)(adr & 0xFF));         //書き込み出す先頭アドレスの下位アドレス出力

        while(*str)
        {
                DataTrans(*str);        //EEPROM(Slave)へ1バイトのデータ書き込み
                str++;
        
                delay_ms(8);            //8msec 書き込み完了待ち  6msecはNG
        } 

        SSPCON2bits.PEN = 1;   //ストップ条件発行(SCL:1、SDA:0→1))      //      StopI2C1();//通信一時停止
        while(SSPCON2bits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる
}


char* read_ext_eeprom(unsigned int cmd, int adr)      //文字列受信関数
{
        char* temp_data ;

        SSPCON2bits.SEN = 1;    //スタート条件発行(SCL:1、SDA:1→0) //    StartI2C1();
        while(SSPCON2bits.SEN); //出力完了待ち //正常に発行されればハードによりクリアされる
        PIR1bits.SSPIF = 0;   //マスター動作時の割込みフラグクリア(割り込みを使った場合は必須)

        DataTrans(cmd);     //(スレーブアドレス + 読み込み)コマンドをスレーブへ送信

        DataTrans((unsigned char)(adr >> 8));           //上位アドレス出力
        DataTrans((unsigned char)(adr & 0xFF));         //下位アドレス出力

        SSPCON2bits.RSEN = 1;           //リスタート条件出力
        while(SSPCON2bits.RSEN);                //出力完了待ち
        DataTrans(cmd | 0x01);                  //チップアドレスと制御データ出力

        ix = 0;
        while(1)        //文字列データの取得
        {
                SSPCON2bits.RCEN = 1;           //受信許可 
                while(DataRdyI2C());                    //データ入力待ち
                data_in[ix] = ReadI2C();                                //データ読み込み
        if((data_in[ix] == '\r') || (ix >= 16))break;   //データの終端検出
                SSPCON2bits.ACKDT = 0;          //更にデータ送信をスレーブに要求するのでACK=0をセットする        //AckIC1();
                SSPCON2bits.ACKEN = 1;          //ACKDTにセットされている ACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
                while(SSPCON2bits.ACKEN);       //送信完了を待つ //ACKENは送信完了でハードによりクリアされる
                ix++;
        }

        if(ix < 16)
        {
                SSPCON2bits.ACKDT = 1;          //スレーブからの文字送信要求は終了なのでNACK=1をセット         //      NotAckI2C1();
                                                                                //vs 更にデータ送信をスレーブに要求する場合は、ACK=0をセットする //AckI2C1();
                SSPCON2bits.ACKEN = 1;          //ACKDTにセットされている NACKかACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
        while(SSPCON2bits.ACKEN);       //送信完了を待つ //ACKENは送信完了でハードによりクリアされる

        SSPCON2bits.PEN = 1;    //ストップ条件発行(SCL:1、SDA:0→1))      StopI2C1();//通信一時停止
        while(SSPCON2bits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる

                ix++;
                data_in[ix] = '\0';     //配列を文字列化
                temp_data = &data_in[0];
        }
        else    temp_data = NoData;

        return temp_data;
}


void sw_detect()        //スイッチ検出
{
        // 文字列の選択
        if(PORTAbits.RA0 == 0)swCount_Select++; //文字列選択SWがおされたことを検出
        else swCount_Select = 0;                                        //スイッチが離れたならカウントをリセット

        if(swCount_Select == 4)         //検出4回 → スイッチが押されたと判断
        {
                if(strcmp(str,dragon) == 0)str = cat;   //文字列の比較
                else if(strcmp(str,cat) == 0)str = bird;
                else if(strcmp(str,bird) == 0)str = horse;
                else    str = dragon;

                lcd_clear();    
                lcd_cmd(0x80);          //1行目へ  
                sprintf(Buf,"%s",str);  
                lcd_printf(Buf);        //液晶表示
                lcd_cmd(0xc0);
                lcd_printf("                ");
        }
        if(swCount_Select >= 5)swCount_Select = 5;      //連続的に押された場合のオーバーフロー対策

        //EEPROMへの書き込み
        if(PORTAbits.RA1 == 0)swCount_Memory++; //EEPROM記憶SWがおされた場合
        else swCount_Memory = 0;
        if(swCount_Memory == 4)
        {

                lcd_clear();            //C18の場合        必要              
                lcd_cmd(0x80);          //1行目へ //C18の場合 必要      
                lcd_printf(Buf);        //液晶表示 //C18の場合 必要      
                lcd_cmd(0xc0);  //C18の場合        必要      
                sprintf(tempBuf1,"Recorded       ");
                lcd_printf(tempBuf1);

                write_ext_eeprom(adr_write_cmd,adr_eeprom,str); //EEPROMのadr_EEPROM番地に 文字列str を書き込む
        }
        if(swCount_Memory >= 5)swCount_Memory = 5;
}


/// メイン関数
int     main(void) 
{
        ADCON1 = 0b00000110;    //RA0-RA7 : デジタルポート
        TRISA = 0b00000011;     //RA0,RA1 を入力モードに設定
        TRISB = 0;      //Bポート:出力モードに設定 
        TRISC = 0b00011000;

        /* SSPの初期設定I2Cモード */
        OpenI2C
        (
                MASTER,         //マスターモードに設定
                SLEW_ON         //400kbpsに設定
        );                                      
        SSPADD = 11;    //i2c Slew rate : 20000000/(4*(11 + 1)) = 416666Hz = 417KHz 

                adr_write_cmd = ((0xa0 | (adr_chip << 1)) & (0b11111110));      //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0

                adr_read_cmd =  ((0xa0 | (adr_chip << 1)) | (0b00000001));      //(アドレス + 読み込みコマンド)作成 R/Wビット: 読込み=1

                lcd_init();                             // LCD初期化
                lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

                lcd_clear();                    // 全消去
                sprintf(Buf,"I2C Start !!");
                lcd_printf(Buf);                        //液晶表示 

                delay_ms(2000);

        lcd_clear();                    // 全消去
        lcd_cmd(0x80);  //1行目へ
        sprintf(Buf,"EEPROM Initial =");
        lcd_printf(Buf);
        str_read = read_ext_eeprom(adr_write_cmd,adr_eeprom);   //EEPROMのadr_EEPROM番地からデータ(1バイト)を読み出す
        lcd_cmd(0xc0);  //2行目へ
        sprintf(Buf,"%s",str_read);
        lcd_printf(Buf);




        while(1)        //タイマ割込みを待つ
        {
                sw_detect();    //スイッチの動作検出
                delay_ms(10);   //スイッチのチャタリングによる誤動作防止
        }
        CloseI2C(); 

        return 0;
}




//************************************************
//インクルードファイル    1lcd_lib_C18.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリを
//C18コンパイラ用に変更したものです。
//************************************************
#define         lcd_port                LATD    //DataOutPort    pin : 上位4bit
#define         lcd_stb                 LATDbits.LATD0  //stb OutPort  
#define         lcd_rs                  LATDbits.LATD2  // rs OutPort
#define         port_Mode               TRISD   // Port Mode set                        


void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_out(char code, char flag);





//***********************************************
//インクルードファイル    1lcd_lib_C18.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリを
//C18コンパイラ用に変更したものです。
//***********************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C18コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//////////////////////////////////////////////

#include        "delays.h"
#include        "1lcd_lib_C18.h"


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        port_Mode = 0;  // PIC側の DataPort、stbPort、 rsPort を出力モードに設定
        lcd_port = code & 0xF0;
        if (flag == 0)
                lcd_rs = 1;                     //表示データの場合
        else
                lcd_rs = 0;                     //コマンドデータの場合
        
        Delay10TCYx(1);                 //10NOP 
        lcd_stb = 1;                    //strobe out
        Delay10TCYx(1);                 //10NOP
        lcd_stb = 0;                    //reset strobe
}


//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);                       //上位4ビット出力
        lcd_out(asci<<4, 0);            //下位4ビット出力
        Delay10TCYx(50);                        //500NOP (50μsec待ち at 40MHz)
}


/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                //上位4ビット出力
        lcd_out(cmd<<4, 1);             //下位4ビット出力
        if((cmd & 0x03) != 0)
                Delay10KTCYx(2);                //2msec待ち at 40MHz
        else
                Delay10TCYx(50);                //50usec待ち at 40MHz
}


/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  //初期化コマンド出力
//  Delay10KTCYx(15);           //15msec待ち at 40MHz
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(5);                //5msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x30, 1);               //8bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_out(0x20, 1);               //4bit mode set
        Delay10KTCYx(1);                //1msec待ち at 40MHz
        lcd_cmd(0x2E);                  //DL=0 4bit mode
        lcd_cmd(0x08);                  //display off C=D=B=0
        lcd_cmd(0x0D);                  //display on C=D=1 B=0
        lcd_cmd(0x06);                  //entry I/D=1 S=0
        lcd_cmd(0x01);                  //all clear
}




<動作結果>

   動作結果を以下に示します。

データ モード 液晶画面
     なし       EEPROMにデータがない場合に
 電源を投入した時の液晶初期画面
   I am a dragon\r      液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面 
   I am a cat\r    液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面
   I am a bird\r    液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面
   I am a horse\r    液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面




I2C通信 外付けEEPROM 読み書き

(3) PIC18F452  コンパイラ CCS

<試作品仕様>
 ・I2C通信により EEPROMと読み書きをおこなう
 ・I2C通信の主な諸元は以下とする。
   @ 通信速度 …… 400KHz
   A アドレス送信方式 …… 7ビット
   B マスタからのデータ送信要求終了通知 ……NACK
  ・PICにはキャラクタ型液晶を接続する。
 ・書込みデータの選択はモーメンタリーの押しボタンスイッチとする。選択された書込みデータは液晶の1行目に順次表示されること。
 ・別途設ける書込み用モーメンタリーボタンを押すと液晶の1行目に表示されているデータ(文字列)がEEPROMにメモリされること。
  データは同じアドレスに上書きするものとする。
 ・EEPROMに書込むデータは以下とする。
  @ I am a dragon\r
  A I am a cat\r
  B I am a bird\r
  C I am a horse\r
 ・電源を投入した時の液晶初期画面に、EEPROMに書込まれたデータを読み出して液晶の2行目に表示すること
  例  
    EEPROM Initial =     …… 1行目
    I am a cat■        …… 2行目



 <試作品回路図>(→回路図のPDFファイル


<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています




   <プログラム例>

/********************************************************
*  I2C通信  外付けEEPROM読み書き
*                                  PIC18F452    CCSコンパイラ
********************************************************/

#include <18F452.h>
#include <string.h>

#fuses  HS,BORV45,PUT
#fuses  NOWDT,CCP2C1
#fuses  NODEBUG,NOLVP,NOSTVREN
#fuses  NOPROTECT,NOCPD,NOCPB
#fuses  NOWRT,NOWRTD,NOWRTB,NOWRTC,NOEBTR,NOEBTRB

#use delay(CLOCK=20000000)
#use fast_io(B)
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3,FORCE_HW,FAST=400000)
        //マスターモード、内蔵SSPモジュール使用、通信速度=400KHz
        
//////// Port define and link LCD library 
#define mode     0
#define input_x         input_D
#define output_x        output_D
#define set_tris_x      set_tris_D
#define rs PIN_D2       //chip select
#define stb PIN_D0      //strobe
#include "1lcd_lib.c"



#byte   SSPCON2=0x0FC5  //SSPCON2レジスタ定義
#byte   SSPCON1=0x0FC6  //SSPCON1レジスタ定義
#byte   SSPSTAT=0x0FC7  //SSPSTATレジスタ定義
#byte   SSPADD=0x0FC8   //SSPADDレジスタ定義
#byte   SSPBUF=0x0FC9   //SSPBUFレジスタ定義



char* str;
char* str_read;

unsigned int swCount_Memory = 0,swCount_Select = 0;
unsigned int ix;
char data_in[20];

unsigned int adr_chip = 0x00;  //EEPROMのchipアドレス
unsigned int adr_write_cmd,adr_read_cmd;
unsigned int adr_eeprom = 0;    //書き込みするEEPROMの先頭番地

char cat[] = "I am a cat\r";            //
char bird[] = "I am a bird\r";  // 
char horse[] = "I am a horse\r";        //
char dragon[] = "I am a dragon\r";      // 

//char Hellow[] = "Hellow"; 
char NoData[] = "No Data_";


void write_ext_eeprom(unsigned int cmd, int adr, char* str)       //文字列送信関数
{
        i2c_start();    //I2C開始   //   SSPCON2bits.SEN = 1;   //I2Cバスにスタート条件出力: SCL: 1、 SDA: 1→0  
                                        //   while(SSPCON2bits.SEN); //出力完了待ち 
        i2c_write(cmd);                 //送信要求
        i2c_write((unsigned char)(adr >> 8));   //上位アドレス
        i2c_write((unsigned char)(adr & 0xFF)); //下位アドレス

        while(*str)
        {
                i2c_write(*str);        //EEPROM(Slave)へ1バイトのデータ書き込み 
                str++;
                delay_ms(8);    //8msec 書き込み完了待ち  6msecはNG
        } 
        i2c_stop();     //I2C終了 //SSPCON2bits.PEN = 1;   //ストップ条件発行(SCL:1、SDA:0→1)) 
                                //while(SSPCON2bits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる
}


char* read_ext_eeprom(unsigned int cmd, int adr)      //文字列受信関数
{
        char* temp_data ;
        
        i2c_start();    //I2C開始 //SSPCON2bits.SEN = 1;    //スタート条件発行(SCL:1、SDA:1→0) 
                                        //while(SSPCON2bits.SEN); //出力完了待ち //正常に発行されればハードによりクリアされる
                                //   PIR1bits.SSPIF = 0;   //マスター動作時の割込みフラグクリア(割り込みを使った場合は必須)

        i2c_write(cmd);         //(スレーブアドレス + 読み込み)コマンドをスレーブへ送信
        i2c_write((unsigned char)(adr >> 8));                   //上位アドレス送信
        i2c_write(adr & 0xFF);                                          //下位アドレス送信

        i2c_start();    //リスタート条件出力 すでに i2c_start();が実行されて、まだi2c_stop();は実行されていないのでリスタートとなる
                                        //SSPCON2bits.RSEN = 1; //リスタート条件出力
                                        //while(SSPCON2bits.RSEN);      //出力完了待ち
        i2c_write(cmd | 0x01);                                  //チップアドレスと制御データ出力

        ix = 0;
        while(1)        //文字列データの取得
        {
                SSPCON2 = (SSPCON2 | 0b00001000);       //受信許可  b3: 0 → 1  //SSPCON2bits.RCEN = 1;                
                while((SSPSTAT & 0b00000001) == 0); //受信バッファー完了(b0 = 1 )を待つ //while(!SSPSTA.BF); 
           
                data_in[ix] = SSPBUF;   //1バイト受信、受信後ACKを送信しない   data_in[ix] = i2c_read(0); は NG NACKが出力されてしまう

                if((data_in[ix] == '\r') || (ix >= 16))break;   //データの終端検出
                SSPCON2 = SSPCON2 & 0b11011111;         // SSPCON2bits.ACKDT = 0;       //更にデータ送信をスレーブに要求するのでACK=0をセットする        //AckIC1();
                SSPCON2 = SSPCON2 | 0b00010000;         //SSPCON2bits.ACKEN = 1;        //ACDTにセットされている ACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
                while((SSPCON2 & 0b00010000) != 0); // 送信完了(b4 = 1)を待つ //ACKENは送信完了でハードによりクリアされる //while(SSPCON2bits.ACKEN);   
                ix++;
        }

        if(ix < 16)
        {
                        SSPCON2 = SSPCON2 | 0b00100000; //b5 = 1   //SSPCON2bits.ACKDT = 1;     //スレーブからの文字送信要求は終了なのでNACK=1をセット 
                                                                                        //ACKDTにセットされている NACKかACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
                        while((SSPCON2 & 0b00010000) != 0);     //送信完了を待つ //ACKENは送信完了でハードによりクリアされる //while(SSPCON2bits.ACKEN);   
                        i2c_stop();             //SSPCON2bits.PEN = 1;    //ストップ条件発行(SCL:1、SDA:0→1))      StopI2C1();//通信一時停止
                                                        // while(SSPCON2bits.PEN); //ストップ条件発行完了を待つ//正常に発行されればハードによりクリアされる
                        ix++;
                data_in[ix] = '\0';     //配列を文字列化
                temp_data = &data_in[0];
        }
        else    temp_data = NoData;

        return temp_data;
}

void sw_detect()        //スイッチ検出
{
        // 文字列の選択

        if(input(PIN_A0) == 0)swCount_Select++; //文字列選択SWがおされたことを検出
        else swCount_Select = 0;                                        //スイッチが離れたならカウントをリセット

        if(swCount_Select == 4)         //検出4回 → スイッチが押されたと判断
        {
                if(strcmp(str,dragon) == 0)str = cat;   //文字列の比較
                else if(strcmp(str,cat) == 0)str = bird;
                else if(strcmp(str,bird) == 0)str = horse;
                else    str = dragon;

                lcd_clear();    
                lcd_cmd(0x80);          //1行目へ
                printf(lcd_data,"%s",str);      
                lcd_cmd(0xc0);
                printf(lcd_data,"                ");
        }
        if(swCount_Select >= 5)swCount_Select = 5;      //連続的に押された場合のオーバーフロー対策

        //EEPROMへの書き込み
        if(input(PIN_A1) == 0)swCount_Memory++; //EEPROM記憶SWがおされた場合
        else swCount_Memory = 0;
        if(swCount_Memory == 4)
        {

                lcd_clear();            //C18の場合        必要              
                lcd_cmd(0x80);          //1行目へ //C18の場合 必要      
                printf(lcd_data,str);
                
                lcd_cmd(0xc0);  //C18の場合        必要      
                printf(lcd_data,"Recorded       ");
        

                write_ext_eeprom(adr_write_cmd,adr_eeprom,str); //EEPROMのadr_EEPROM番地に 文字列str を書き込む
        }
        if(swCount_Memory >= 5)swCount_Memory = 5;
}


void main()
{
        setup_adc_ports(NO_ANALOGS);    //ADCON1 = 0b00000110;    //RA0-RA7 : デジタルポート

        output_float(PIN_C3);                                           //SCLピン定義
        output_float(PIN_C4);                                           //SDAピン定義

        adr_write_cmd = ((0xa0 | (adr_chip << 1)) & (0b11111110));      //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0
        adr_read_cmd =  ((0xa0 | (adr_chip << 1)) | (0b00000001));      //(アドレス + 読み込みコマンド)作成 R/Wビット: 読込み=1
        lcd_init();     // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF

        lcd_clear();    // 全消去
        printf(lcd_data,"I2C Start !!");
        delay_ms(2000);

        lcd_clear();    // 全消去
        lcd_cmd(0x80);  //1行目へ
        printf(lcd_data,"EEPROM Initial =");
        str_read = read_ext_eeprom(adr_write_cmd,adr_eeprom);   //EEPROMのadr_EEPROM番地からデータ(1バイト)を読み出す
        lcd_cmd(0xc0);  //2行目へ
        printf(lcd_data,"%s",str_read);

        while(1)                                                                        //永久ループ
        {
                sw_detect();    //スイッチの動作検出
                delay_ms(10);   //スイッチのチャタリングによる誤動作防止
        }
}



//---------------------------------------------------------------------------

//**************************************
//インクルードファイル    1lcd_lib.c
//このファイルは後閑哲也さんが設計されたものです
//**************************************
///////////////////////////////////////////////
//  液晶表示器制御ライブラリ
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去


//////////////////////////////////////////////

//////// データ出力サブ関数
void lcd_out(int code, int flag)
{
        output_x((code & 0xF0) | (input_x() & 0x0F));
        if (flag == 0)
                output_high(rs);                //表示データの場合
        else
        output_low(rs);                 //コマンドデータの場合
        delay_cycles(4);                        //NOP 1         
        output_high(stb);                       //strobe out
        delay_cycles(8);                        //NOP 2
        output_low(stb);                        //reset strobe
}
//////// 1文字表示関数
void lcd_data(int asci)
{
        lcd_out(asci, 0);                       //上位4ビット出力
        lcd_out(asci<<4, 0);            //下位4ビット出力
        delay_us(50);                           //50μsec待ち
}
/////// コマンド出力関数
void lcd_cmd(int cmd)
{
        lcd_out(cmd, 1);                        //上位4ビット出力
        lcd_out(cmd<<4, 1);                     //下位4ビット出力
        delay_ms(2);                            //2msec待ち
}
/////// 全消去関数
void lcd_clear()
{
        lcd_cmd(0x01);                          //初期化コマンド出力
        delay_ms(15);                           //15msec待ち
}
/////// 初期化関数
void lcd_init()
{
        set_tris_x(mode);                       //モードセット
        delay_ms(15);
        lcd_out(0x30, 1);                       //8bit mode set
        delay_ms(5);
        lcd_out(0x30, 1);                       //8bit mode set
        delay_ms(1);
        lcd_out(0x30, 1);                       //8bit mode set
        delay_ms(1);
        lcd_out(0x20, 1);                       //4bit mode set
        delay_ms(1);
        lcd_cmd(0x2E);                          //DL=0 4bit mode
        lcd_cmd(0x08);                          //display off C=D=B=0
        lcd_cmd(0x0D);                          //display on C=D=1 B=0
        lcd_cmd(0x06);                          //entry I/D=1 S=0
        lcd_cmd(0x02);                          //cursor home
}



<動作結果>

   動作結果を以下に示します。

データ モード 液晶画面
     なし       EEPROMにデータがない場合に
 電源を投入した時の液晶初期画面
   I am a dragon\r      液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源再投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面 
   I am a cat\r    液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源再投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面
   I am a bird\r    液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源再投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面
   I am a horse\r    液晶1行目のデータ を
  EEPROMに書込んだ時の液晶画面
 (EEPROM書込みスイッチを押した時の液晶画面)
 電源再投入時にEEPROMのデータを
  読出して液晶2行目に表示した初期画面


(4) XC32  Haramony    PIC32MZ2048ECH100編   (EEPROM読み書き) 

   PIC32MZ2048ECH100 revison 5の I2Cを動かすには 下記等のエラッタ対策が必要となります。

       Setting the PEN bit to send a Stop does not release the SDA

<試作品仕様>
   ・I2C通信により EEPROMと読み書きをおこなう
   ・EEPROMは マイクロチップのEEPROM 24LC64とする。
   ・PICが立ち上がったら 以下を EEPROMの適当なアドレスに書き込む
     1.  I am a cat\r
     2.  I am a bird\r
     3.  I am a horse\r
     4.  I am a dragon\r
   ・その後 上記4つの文字列を 読みだして液晶に以下の要領で表示する。
     モード1: 液晶上段:  I am a cat\r
           液晶下段:  I am a bird\r

     モード2: 液晶上段:  I am a horse\r
           液晶下段:  I am a dragon\r

     尚、モード 1と モード2の表示は 2sec間隔で交互に繰り返すこと。 
 

    ・ MHCのライブラは ダイナミックモードを使用すること。
    ・ 開発環境  Harmony  ver. 1.02     XC32  ver.1.34    MPLABX  ver.2.26   PIC32MZ2048ECH100 revison 5

<試作品回路図>(→回路図のPDFファイル



<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています




     

          

   <プログラム例>

//以下、main.c
//--------------------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Project Main Source File

  Company:
    Microchip Technology Inc.
  
  File Name:
    main.c

  Summary:
    This file contains the "main" function for an MPLAB Harmony project.

  Description:
    This file contains the "main" function for an MPLAB Harmony project.  The
    "main" function calls the "SYS_Initialize" function to initialize the state 
    machines of all MPLAB Harmony modules in the system and it calls the 
    "SYS_Tasks" function from within a system-wide "super" loop to maintain 
    their correct operation. These two functions are implemented in 
    configuration-specific files (usually "system_init.c" and "system_tasks.c")
    in a configuration-specific folder under the "src/system_config" folder 
    within this project's top-level folder.  An MPLAB Harmony project may have
    more than one configuration, each contained within it's own folder under
    the "system_config" folder.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

//Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "system/common/sys_module.h"   // SYS function prototypes


// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    /* Initialize all MPLAB Harmony modules, including application(s). */
    SYS_Initialize ( NULL );

    while ( true )
    {
        /* Maintain state machines of all polled MPLAB Harmony modules. */
        SYS_Tasks ( );

    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}


/*******************************************************************************
 End of File
*/




//以下、system_init.c
//--------------------------------------------------------------------------------
/*******************************************************************************
  System Initialization File

  File Name:
    system_init.c

  Summary:
    This file contains source code necessary to initialize the system.

  Description:
    This file contains source code necessary to initialize the system.  It
    implements the "SYS_Initialize" function, configuration bits, and allocates
    any necessary global system resources, such as the systemObjects structure
    that contains the object handles to all the MPLAB Harmony module objects in
    the system.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "system_config.h"
#include "system_definitions.h"
#include "app.h"


// ****************************************************************************
// ****************************************************************************
// Section: Configuration Bits
// ****************************************************************************
// ****************************************************************************

//コンフィグ
//-----------------------------------------------------------------------
//DEVCFG0レジスタ
#pragma config EJTAGBEN = NORMAL
#pragma config DBGPER = ALLOW_PG2
#pragma config FSLEEP = OFF
#pragma config FECCCON = OFF_UNLOCKED
#pragma config BOOTISA = MIPS32
#pragma config TRCEN = OFF
#pragma config ICESEL = ICS_PGx2
#pragma config JTAGEN = OFF //JTAG ポート Disable
#pragma config DEBUG = OFF



//----------------------------------------------------------------------
//DEVCFG1レジスタ
#pragma config FNOSC = SPLL //PLL回路(システムPLL)選択   //システム発振回路 //内蔵FRC(8MHz)選択の場合:FNOSC = FRCDIV   //Oscillator Selection Bits (Fast RC Osc w/Div-by-N (FRCDIV))
#pragma config FDMTEN = OFF //デッドマンタイマ OFF (Deadman Timer is disabled)
//#pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value)

#pragma config FSOSCEN = OFF // 副発振器OFF   //Secondary Oscillator Enable (Disable SOSC)
#pragma config IESO = OFF //ウェイクアップ時の2段速度スタートアップ // Internal/External Switch Over (Disabled)

#pragma config POSCMOD = HS //HS: ハイスピードレゾネータモード // HS(High Speed Resonator Operation) Oscillator mode selected
                            //EC: 外部発振器    //EC(External Clock Input Operation) mode selected // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF //OSCCOピン出力無効
#pragma config FCKSM = CSECME   //クロック発振:切替及びモニタ有効  //主発振器失陥でFRC(内蔵高速発振器)に切替   //FSCM(Fail Safe Clock Monitor)制御

#pragma config FWDTEN = OFF // ウォッチドックタイマ OFF    //Watchdog Timer Disable
//#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
//#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
//#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
//#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%)



//--------------------------------------------------------------------------------------------------------------------
// DEVCFG2レジスタ
//システムクロック:200MHz
//ペリフェラル周波数://default: 100MHz    //PBxDIVで8系統毎に設定変更可
//PBxDIV: PERIPHERAL BUS CLOCK DIVISOR CONTROL レジスタのPBDIV<6:0>: Peripheral Bus Clock Divisor Control ビットで設定

#pragma config FPLLRNG = RANGE_5_10_MHZ        //PLL Input周波数入力範囲設定// System PLL Input Range (5-10 MHz Input)  //PLLin = 8(= 24/3)MHz故
#pragma config FPLLIDIV = DIV_3 //PLL入力側での分周: 1/3  // PLL Input周波数 = 24MHz ÷ 3 = 8MHz     // System PLL Input Divider (1x Divider)

//#pragma config FPLLICLK = PLL_POSC //主発振回路選択 //内蔵FRC(8MHz)の場合はFPLLICLK = PLL_FRC//  System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLICLK = PLL_FRC   //内蔵高速発振器選択    //★★★ バグ有 主発振回路選択の時、FPLLICLK = PLL_POSCではなくFPLLICLK = PLL_FRCを選択する。(at ver.1.33 XC32)

#pragma config FPLLMULT = MUL_50 //PLL倍率:50倍 //8MHz x 50 = 400MHz  //System PLL Multiplier (PLL Multiply by 50)
#pragma config FPLLODIV = DIV_2 //PLL出力側での分周: 1/2  //システムクロック = 400MHz ÷ 2 = 200MHz


#pragma config UPLLFSEL = FREQ_24MHZ //USBのPLL入力を 24MHz→12MHzに変換 // USB PLL Input Frequency Selection (USB PLL input is 12 MHz)
#pragma config UPLLEN = ON //USBのPLL変換:イネーブル // USB PLL Enable (USB PLL is enabled)




//--------------------------------------------------------------------------------------------------------------------------
//DEVCFG3レジスタ
#pragma config USERID =     0xffff
#pragma config FMIIEN =     ON
#pragma config FETHIO =     ON
#pragma config PGL1WAY =    ON
#pragma config PMDL1WAY =   ON
#pragma config IOL1WAY =    ON
#pragma config FUSBIDIO =   ON


/*** BF1SEQ0 ***/

#pragma config TSEQ =       0xffff
#pragma config CSEQ =       0xffff

// *****************************************************************************
// *****************************************************************************
// Section: Library/Stack Initialization Data
// *****************************************************************************
// *****************************************************************************/



// *****************************************************************************
// *****************************************************************************
// Section: Driver Initialization Data
// *****************************************************************************
// *****************************************************************************

//<editor-fold defaultstate="collapsed" desc="DRV_I2C Configuration">

// *****************************************************************************
/* I2C Driver Initialization Data
*/

const DRV_I2C_INIT drvI2C0InitData =
{
    .i2cId = DRV_I2C_PERIPHERAL_ID_IDX0,
    .i2cMode = DRV_I2C_OPERATION_MODE_IDX0,
    .baudRate = DRV_I2C_BAUD_RATE_IDX0,
    .busspeed = DRV_I2C_SLEW_RATE_CONTROL_IDX0,
    .buslevel = DRV_I2C_SMBus_SPECIFICATION_IDX0,
    .mstrInterruptSource = DRV_I2C_MASTER_INT_SRC_IDX0,
    .slaveInterruptSource = DRV_I2C_SLAVE_INT_SRC_IDX0,
    .errInterruptSource = DRV_I2C_ERR_MZ_INT_SRC_IDX0,
};





// </editor-fold>

// *****************************************************************************
// *****************************************************************************
// Section: System Data
// *****************************************************************************
// *****************************************************************************

/* Structure to hold the object handles for the modules in the system. */
SYSTEM_OBJECTS sysObj;

// *****************************************************************************
// *****************************************************************************
// Section: Module Initialization Data
// *****************************************************************************
// *****************************************************************************


//<editor-fold defaultstate="collapsed" desc="SYS_DEVCON Configuration">

/*** System Device Control Initialization Data ***/

const SYS_DEVCON_INIT sysDevconInit =
{
    .moduleInit = {0},
};
// </editor-fold>

// *****************************************************************************
// *****************************************************************************
// Section: Static Initialization Functions
// *****************************************************************************
// *****************************************************************************



// *****************************************************************************
// *****************************************************************************
// Section: System Initialization
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void SYS_Initialize ( SYS_INIT_DATA *data )

  Summary:
    Initializes the board, services, drivers, application and other modules.

  Remarks:
    See prototype in system/common/sys_module.h.
 */

void SYS_Initialize ( void* data )
{
    /* Core Processor Initialization */
    SYS_CLK_Initialize( NULL );
    sysObj.sysDevcon = SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)&sysDevconInit);
    SYS_DEVCON_PerformanceConfig(SYS_CLK_SystemFrequencyGet());
    SYS_DEVCON_JTAGDisable();
    SYS_PORTS_Initialize();

    /* Initialize Drivers */
    sysObj.drvI2C0 = DRV_I2C_Initialize(DRV_I2C_INDEX_0, (SYS_MODULE_INIT *)&drvI2C0InitData);

    // I2Cの初期設定 100kHz 7bit address

    I2C2CONbits.ON = 0;      //IC2モジュール:OFF
    I2C2CONbits.A10M = 0;   //7 bit アドレス
    I2C2BRG = 498;          //Fscl = PBCLK2 / 2 /(BRG + 2)  =  100 MHz / 2 / (498 + 2) = 100 KHz
    I2C2CONbits.ON = 1;      //IC2モジュール:ON




    /* Initialize System Services */

    /* Initialize Middleware */

    /* Initialize the Application */
    APP_Initialize();

}

/*******************************************************************************
 End of File
*/




//以下、app.c
//--------------------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony Application Source File
  
  Company:
    Microchip Technology Inc.
  
  File Name:
    app.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It 
    implements the logic of the application's state machine and it may call 
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files 
// *****************************************************************************
// *****************************************************************************

#include "app.h"

#include "1lcd_lib_C32.h"
#include "mem_24LC_lib_i2c.h"



char Buf[17];   //文字列のバッファー用レジスタ


int delay_Clock = 200000000;   //200MHz


extern char read_data[20];  //I2C受信文字列データ用
char* str_read;

unsigned char Adr_chips = 0b00000100;   //A0 = GND, A1 = GND, A2 = +3.3v


char cat[] = "I am a cat\r";    //I2Cでは 文字列終端の'\0'(0x00)は送受信データとして使えないことから
                                //代用として'\r'(0x0d 復帰)を用いる
char bird[] = "I am a bird\r";  //
char horse[] = "I am a horse\r";        //
char dragon[] = "I am a dragon\r";      //




void delay_us(volatile unsigned int usec)        //1μsec遅延
{
        volatile  int count;

        count = (int)(delay_Clock/20000000)*usec;

        do      //実測 at 200MH (delay_Clock=200000000)
        {       //delay_us(1000):1000.4μsec  delay_us(100):100.6μsec  delay_us(10):10.5μsec  delay_us(1):1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);


}

void delay_ms(volatile unsigned int msec)        //1msec遅延
{
        volatile unsigned int i;         //実測:at200MH (Clock=200000000)//delay_ms(1): 1.0006msec   delay_ms(100):100.04msec

        for(i=0; i<msec; i++)
        delay_us(1000);
}




// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_Initialize function.
    
    Application strings and buffers are be defined outside this structure.
*/

APP_DATA appData;

// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary callback funtions.
*/

// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_Initialize ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;
    
    /* TODO: Initialize your application's state machine and other
     * parameters.
     */



    //初期設定: LED消灯
    LATGbits.LATG15 = 0;    //RG15 = 0 LED --> OFF//LED消灯 赤

    LATDbits.LATD5 = 0;    //RD5 = 0 LED --> OFF//LED消灯 赤
    LATDbits.LATD4 = 0;    //RD4 = 0 LED --> OFF//LED消灯 白
    LATCbits.LATC14 = 0;    //RC14 = 0 LED --> OFF//LED消灯 黄色
    LATCbits.LATC13 = 0;    //RC13 = 0 LED --> OFF//LED消灯 緑





        lcd_init();        // LCD初期化
        lcd_cmd(0b00001100);    // カーソル:OFF  ブリンク:OFF


        lcd_cmd(0x80);          //1目の先頭へ
        sprintf(Buf,"32MZ I2C EEPROM ");//
        lcd_str(Buf);                   //液晶表示

        lcd_cmd(0xC0);          //2行目の先頭へ
        sprintf(Buf,"String RW Start !!");      //
        lcd_str(Buf);           // 開始メッセージ1行目表示


        delay_ms(1000);

    //文字列書込み
    mem24LC_WriteStr(Adr_chips,0x0000,cat);
    mem24LC_WriteStr(Adr_chips,0x0020,bird);
    mem24LC_WriteStr(Adr_chips,0x0040,horse);
    mem24LC_WriteStr(Adr_chips,0x0060,dragon);


}


/******************************************************************************
  Function:
    void APP_Tasks ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Tasks ( void )
{
    /* Check the application's current state. */
    switch ( appData.state )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
                //文字列読込
        mem24LC_ReadStr(Adr_chips, 0x0000);
        str_read = &read_data[0];
        lcd_cmd(0x80);          //1行目の先頭へ
        sprintf(Buf,"%s         ",str_read);    //
        lcd_str(Buf);                   //液晶表示

        mem24LC_ReadStr(Adr_chips, 0x0020);
        str_read = &read_data[0];
        lcd_cmd(0xC0);          //2行目の先頭へ
        sprintf(Buf,"%s         ",str_read);    //
        lcd_str(Buf);                   //液晶表示

        LATGbits.LATG15 = 1;    //RG15 点灯 赤
        LATDbits.LATD5 = 1;    //RD5 点灯 赤
        LATDbits.LATD4 = 1;    //RD4 点灯 白
        LATCbits.LATC14 = 1;    //RC14 点灯 黄色
        LATCbits.LATC13 = 1;    //RC13 点灯 緑


        delay_ms(2000);

        mem24LC_ReadStr(Adr_chips, 0x0040);
        str_read = &read_data[0];
        lcd_cmd(0x80);          //1行目の先頭へ
        sprintf(Buf,"%s         ",str_read);    //
        lcd_str(Buf);                   //液晶表示


        mem24LC_ReadStr(Adr_chips, 0x0060);
        str_read = &read_data[0];
        lcd_cmd(0xC0);          //2行目の先頭へ
        sprintf(Buf,"%s         ",str_read);    //
        lcd_str(Buf);                   //液晶表示

        LATGbits.LATG15 = 0;    //RG15 = 0 LED --> OFF//LED消灯 赤
        LATDbits.LATD5 = 0;    //RD5 = 0 LED --> OFF//LED消灯 赤
        LATDbits.LATD4 = 0;    //RD4 = 0 LED --> OFF//LED消灯 白
        LATCbits.LATC14 = 0;    //RC14 = 0 LED --> OFF//LED消灯 黄色
        LATCbits.LATC13 = 0;    //RC13 = 0 LED --> OFF//LED消灯 緑


        delay_ms(2000);
            break;
        }
   

        /* TODO: implement your application state machine.*/

        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}
 

/*******************************************************************************
 End of File
 */









//以下、sys_ports_static.c
//--------------------------------------------------------------------------------------
/*******************************************************************************
  SYS PORTS Static Functions for PORTS System Service

  Company:
    Microchip Technology Inc.

  File Name:
    sys_ports_static.c

  Summary:
    SYS PORTS static function implementations for the Ports System Service.

  Description:
    The Ports System Service provides a simple interface to manage the ports
    on Microchip microcontrollers. This file defines the static implementation for the 
    Ports System Service.
    
  Remarks:
    Static functions incorporate all system ports configuration settings as
    determined by the user via the Microchip Harmony Configurator GUI.  It provides 
    static version of the routines, eliminating the need for an object ID or 
    object handle.

*******************************************************************************/

//DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/
//DOM-IGNORE-END

#include "system_config.h"
#include "peripheral/ports/plib_ports.h"
#include "peripheral/int/plib_int.h"


void SYS_PORTS_Initialize(void)
{


    //液晶ポート入出力設定-----------------------------
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 15 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 14 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 13 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_B, 12 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_A, 10 );
    PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_A, 9 );
/*
    TRISBbits.TRISB15 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB14 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB13 = 0;       //キャラクタ液晶ポート設定
    TRISBbits.TRISB12 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA10 = 0;       //キャラクタ液晶ポート設定
    TRISAbits.TRISA9 = 0;       //キャラクタ液晶ポート設定
*/



    //LEDポート 出力ポートに設定--------------------
    TRISGbits.TRISG15 = 0;  //RG15 : out//LED 入力ポートに設定 赤
    TRISDbits.TRISD5 = 0;  //RD5 : out//LED 入力ポートに設定    赤
    TRISDbits.TRISD4 = 0;  //RD4 : out//LED 入力ポートに設定    白
    TRISCbits.TRISC14 = 0;  //RC14 : out//LED 入力ポートに設定  黄色
    TRISCbits.TRISC13 = 0;  //RC13 : out//LED 入力ポートに設定  緑


    //I2C  SCL/SDAポート入出力設定
//    TRISAbits.TRISA2 = 0;  //RA2: out //SCL2  //不要
//    TRISAbits.TRISA3 = 0;  //RA3: out //SDA2  //不要

    /* PPS Input Remapping */

    /* PPS Output Remapping */

    
}


/*******************************************************************************
 End of File
*/






//以下、system_tasks.c
//--------------------------------------------------------------------------
/*******************************************************************************
 System Tasks File

  File Name:
    system_tasks.c

  Summary:
    This file contains source code necessary to maintain system's polled state
    machines.

  Description:
    This file contains source code necessary to maintain system's polled state
    machines.  It implements the "SYS_Tasks" function that calls the individual
    "Tasks" functions for all the MPLAB Harmony modules in the system.

  Remarks:
    This file requires access to the systemObjects global data structure that
    contains the object handles to all MPLAB Harmony module objects executing
    polled in the system.  These handles are passed into the individual module
    "Tasks" functions to identify the instance of the module to maintain.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "system_config.h"
#include "system_definitions.h"
#include "app.h"


// *****************************************************************************
// *****************************************************************************
// Section: System "Tasks" Routine
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void SYS_Tasks ( void )

  Remarks:
    See prototype in system/common/sys_module.h.
*/

void SYS_Tasks ( void )
{
    /* Maintain the state machines of all library modules executing polled in
    the system. */

    /* Maintain system services */
    SYS_DEVCON_Tasks(sysObj.sysDevcon);

    /* Maintain Device Drivers */
 //   DRV_I2C_Tasks(sysObj.drvI2C0);    //このコマンドをコメントアウト

    /* Maintain the application's state machine. */
    APP_Tasks();
}


/*******************************************************************************
 End of File
 */




//以下、system_config.h
//-------------------------------------------------------------------------------
/*******************************************************************************
  MPLAB Harmony System Configuration Header

  File Name:
    system_config.h

  Summary:
    Build-time configuration header for the system defined by this MPLAB Harmony
    project.

  Description:
    An MPLAB Project may have multiple configurations.  This file defines the
    build-time options for a single configuration.

  Remarks:
    This configuration header must not define any prototypes or data
    definitions (or include any files that do).  It only provides macro
    definitions for build-time configuration options that are not instantiated
    until used by another MPLAB Harmony module or application.
    
    Created with MPLAB Harmony Version 1.02
*******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*******************************************************************************/
// DOM-IGNORE-END

#ifndef _SYSTEM_CONFIG_H
#define _SYSTEM_CONFIG_H

/* This is a temporary workaround for an issue with the peripheral library "Exists"
   functions that causes superfluous warnings.  It "nulls" out the definition of
   The PLIB function attribute that causes the warning.  Once that issue has been
   resolved, this definition should be removed. */
#define _PLIB_UNSUPPORTED


// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************
/*  This section Includes other configuration headers necessary to completely
    define this configuration.
*/


// *****************************************************************************
// *****************************************************************************
// Section: System Service Configuration
// *****************************************************************************
// *****************************************************************************


// *****************************************************************************
/* Clock System Service Configuration Options
*/
#define SYS_CLK_FREQ                        200000000ul
#define SYS_CLK_BUS_PERIPHERAL_1            100000000ul
#define SYS_CLK_BUS_PERIPHERAL_2            100000000ul
#define SYS_CLK_BUS_PERIPHERAL_3            100000000ul
#define SYS_CLK_BUS_PERIPHERAL_4            100000000ul
#define SYS_CLK_BUS_PERIPHERAL_5            100000000ul
#define SYS_CLK_BUS_PERIPHERAL_7            200000000ul
#define SYS_CLK_BUS_PERIPHERAL_8            100000000ul
#define SYS_CLK_CONFIG_PRIMARY_XTAL         24000000ul
#define SYS_CLK_CONFIG_SECONDARY_XTAL       0ul
   
/*** Ports System Service Configuration ***/


#define SYS_PORT_G_ANSEL        0x7003
#define SYS_PORT_G_TRIS         0xf3c3
#define SYS_PORT_G_ODC          0x0
#define SYS_PORT_G_CNPU         0x0
#define SYS_PORT_G_CNPD         0x0
#define SYS_PORT_G_CNEN         0x0


 

/*** Console System Service Configuration DISABLED ***/

#define SYS_CONSOLE_MESSAGE(message)
#define SYS_CONSOLE_PRINT(fmt, ...)

 
/*** Command Processor System Service Configuration DISABLED ***/

#define SYS_CMD_MESSAGE(message)
#define SYS_CMD_PRINT(fmt, ...)
#define SYS_CMD_READY_TO_READ()




// *****************************************************************************
// *****************************************************************************
// Section: Driver Configuration
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* I2C Driver Configuration Options
*/

#define DRV_I2C_INTERRUPT_MODE                                  false
#define DRV_I2C_CLIENTS_NUMBER                                  1
#define DRV_I2C_INSTANCES_NUMBER                                1

#define DRV_I2C_PERIPHERAL_ID_IDX0                              I2C_ID_2    //チャンネル2を選択
#define DRV_I2C_OPERATION_MODE_IDX0                             DRV_I2C_MODE_MASTER //マスターモード
#define DRV_I2C_STOP_IN_IDLE_IDX0                               false
#define DRV_I2C_SMBus_SPECIFICATION_IDX0                        false
#define DRV_I2C_BAUD_RATE_IDX0                                  100000      //I2C ボーレート 100KHz
#define DRV_I2C_BRG_CLOCK_IDX0                                  100000000   //ペリフェラルクロック 100MHz //PBCLK2
#define DRV_I2C_SLEW_RATE_CONTROL_IDX0                          false

#define DRV_I2C_MASTER_INT_SRC_IDX0                             INT_SOURCE_I2C_2_MASTER
#define DRV_I2C_SLAVE_INT_SRC_IDX0                              INT_SOURCE_I2C_2_SLAVE
#define DRV_I2C_ERR_MZ_INT_SRC_IDX0                             INT_SOURCE_I2C_2_BUS
#define DRV_I2C_POWER_STATE_IDX0                                SYS_MODULE_POWER_RUN_FULL

// *****************************************************************************
// *****************************************************************************
// Section: Middleware & Other Library Configuration
// *****************************************************************************
// *****************************************************************************





#endif // _SYSTEM_CONFIG_H
/*******************************************************************************
 End of File
*/



//以下、 1lcd_lib_C32.h
//-------------------------------------------------------------------------------------------
//*************************************************************************
//インクルードファイル    1lcd_lib_C32.h
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//*************************************************************************
#include <p32xxxx.h>
#define lcd_Clock   200000000        // 単位はHzで指定


// LCDポート設定
#define lcd_port_DB7    LATBbits.LATB15 //LCDのDB7(14番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB6    LATBbits.LATB14 //LCDのDB6(13番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB5    LATBbits.LATB13 //のDB5(12番ピン)に接続されるPIC側ポート番号設定
#define lcd_port_DB4    LATBbits.LATB12 //LCDのDB4(11番ピン)に接続されつPIC側ポート番号設定
#define lcd_rs          LATAbits.LATA9  //LCDのrs(4番ピン)に接続されるPIC側ポート番号設定
#define lcd_stb         LATAbits.LATA10 //LCDのstb(6番ピン)に接続されるPIC側ポート番号設定



void lcd_out(char code, char flag);
void lcd_data(char asci);
void lcd_cmd(char cmd);
void lcd_clear(void);
void lcd_init(void);
void lcd_str(char *str);







//以下、 1lcd_lib_C32.c
//-------------------------------------------------------------------------------------------


//**************************************************************************
//インクルードファイル    1lcd_lib_C32.c
//このファイルは後閑哲也さんが設計されたCCSコンパイラ用液晶表示ライブラリ 1lcd_lib.cをもとに、
//C32コンパイラ対応等で変更したものです。
//**************************************************************************

///////////////////////////////////////////////
//  液晶表示器制御ライブラリ for C32コンパイラー
//  内蔵関数は以下
//    lcd_init()    ----- 初期化
//    lcd_cmd(cmd)  ----- コマンド出力
//    lcd_data(chr) ----- 1文字表示出力
//    lcd_clear()   ----- 全消去
//    lcd_str(str*) ----- 文字列表示 
//////////////////////////////////////////////

#include        "1lcd_lib_C32.h"

void lcd_delay_us(unsigned int usec)    //1μsec遅延関数
{
        int count;

        count = (int)(lcd_Clock/20000000)*usec;

        do      //実測: at 200MH (Clock=200000000)
        {       //delay_us(1000)→1000.4μsec、 delay_us(100)→100.6μsec、delay_us(10)→10.5μsec、delay_us(1)→1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);
        

}

void lcd_delay_ms(unsigned int msec)    //1msec遅延関数
{
        unsigned int i;
        
        for(i=0; i<msec; i++)
        lcd_delay_us(1000);
}


//////// データ出力サブ関数
void lcd_out(char code, char flag)
{
        if(code & 0b10000000)lcd_port_DB7 = 1;  //LCDのDB7への出力セット
        else lcd_port_DB7 = 0;
        if(code & 0b01000000)lcd_port_DB6 = 1;  //LCDのDB6への出力セット
        else lcd_port_DB6 = 0;
        if(code & 0b00100000)lcd_port_DB5 = 1;  //LCDのDB5への出力セット
        else lcd_port_DB5 = 0;
        if(code & 0b00010000)lcd_port_DB4 = 1;  //LCDのDB4への出力セット
        else lcd_port_DB4 = 0;

        if (flag == 0)
                lcd_rs = 1;                     // 表示データの場合
        else
                lcd_rs = 0;                     // コマンドデータの場合

        lcd_delay_us(3);                //1μsecウェイト
//      lcd_delay_us(1);                //1μsecウェイト
                
        lcd_stb = 1;                    // strobe(E) ON (Enable)
        lcd_delay_us(3);                //1μsecウェイト
//      lcd_delay_us(1);                // 1μsec : strobe信号の幅

        lcd_stb = 0;                    // reset strobe
}

//////// 1文字表示関数
void lcd_data(char asci)
{
        lcd_out(asci, 0);               // 上位4ビット出力
        lcd_out(asci<<4, 0);    // 下位4ビット出力
        lcd_delay_us(50);               //50μsecウェイト
}

/////// コマンド出力関数
void lcd_cmd(char cmd)
{
        lcd_out(cmd, 1);                // 上位4ビット出力
        lcd_out(cmd<<4, 1);             // 下位4ビット出力
        if((cmd & 0x03) != 0)   // clear Homeの場合
        lcd_delay_ms(2);        //      2msec待ち
        else
        lcd_delay_us(50);       //50μsecウェイト    
}

/////// 全消去関数
void lcd_clear(void)
{
        lcd_cmd(0x01);                  // 初期化コマンド出力
}

/////// 文字列出力関数
void lcd_str(char* str)      
{
        while(*str)                             //文字列終端の '\0'を検出するまで
        {
                lcd_data(*str);         // 1文字表示
                str++;                          //ポインタをインクリメント                          
        }       
}


/////// 初期化関数
void lcd_init(void)
{
        lcd_delay_ms(20);               //20msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(5);                //5msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x30, 1);               // 8bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_out(0x20, 1);               // 4bit mode set
        lcd_delay_ms(1);                //1msecウェイト
        lcd_cmd(0x2E);                  // DL=0 4bit mode
        lcd_cmd(0x08);                  // display off C=D=B=0
        lcd_cmd(0x0D);                  // display on C=D=1 B=0
        lcd_cmd(0x06);                  // entry I/D=1 S=0
        lcd_cmd(0x02);                  // cursor home
}






//以下、mem_24LC_lib_i2c.h
//-----------------------------------------------------------------------------
//mem_24LC_lib_i2c.h



# ifndef _MY_INCLUDE_PERIPHERAL
#define   _MY_INCLUDE_PERIPHERAL
#include <peripheral/peripheral.h>
#include <peripheral/ports/plib_ports.h>
#endif




// I2Cレジスタ設定
#define I2CXCONbits     I2C2CONbits     //I2C制御レジスタ設定
#define I2CXSTATbits    I2C2STATbits    //I2C状態レジスタ設定
#define I2CXTRN         I2C2TRN         //I2C送信バッファレジスタ設定
#define I2CXRCV         I2C2RCV         //I2C受信バッファレジスタ設定
#define I2CXBRG         I2C2BRG         //I2Cボーレートジェネレータレジスタ設定



void mem24LC_Reset_i2C(void);
void mem24LC_Idle_i2c(void);  //アイドル待ち
void mem24LC_start_i2c(void);    //I2Cスタート
void mem24LC_stop_i2c(void); //I2Cストップ
void mem24LC_write_byte_i2c(unsigned char byte);  //1バイト書込み
void mem24LC_restart_i2c(void); //リスタート
unsigned char mem24LC_ReadChr_24LC(unsigned char adr_chips, unsigned int adr_chip_inner);   //1文字読み込み
void mem24LC_WriteChr_24LC(unsigned char adr_chips, unsigned int adr_chip_inner, unsigned char data);   //1文字書込み

void mem24LC_WriteStr(unsigned char adr_chips, unsigned int adr_chip_inner, char* str);  //文字列書込み
void mem24LC_ReadStr(unsigned char adr_chips, unsigned int adr_chip_inner);  //文字列 読み込み







//以下、mem_24LC_lib_i2c.c
//-------------------------------------------------------------------------------

//mem_24LC_lib_i2c.c


#include "mem_24LC_lib_i2c.h"

int mem24LC_Clock = 200000000;  //Hz: システムクロック

char read_data[20]; //I2Cデータ受信用



void mem24LC_delay_us(unsigned int usec)        //1μsec遅延関数
{
         volatile  int count;

        count = (int)(mem24LC_Clock/20000000)*usec;

        do      //実測 at 200MH (mem24LC_Clock=200000000)
        {       //delay_us(1000):1000.4μsec  delay_us(100):100.6μsec  delay_us(10):10.5μsec  delay_us(1):1.5μsec
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
                asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

                count--;
        }while(count != 0);
    

}

void mem24LC_delay_ms(unsigned int msec)        //1msec遅延関数
{
        unsigned int i;

        for(i=0; i<msec; i++)
        delay_us(1000);
}


void mem24LC_Reset_i2C(void)
{
    I2CXCONbits.ON = 0;      //IC2モジュール:OFF
    I2CXCONbits.ON = 1;      //IC2モジュール:ON
}


void mem24LC_Idle_i2c(void)  //アイドル待ち
{
     while(I2CXCONbits.SEN || I2CXCONbits.PEN || I2CXCONbits.RCEN
           || I2CXCONbits.ACKEN || I2CXSTATbits.TRSTAT);
}


void mem24LC_start_i2c(void)    //I2Cスタート
{
    mem24LC_Idle_i2c();
    I2CXCONbits.SEN = 1;    // スタート出力//
    while(I2CXCONbits.SEN); // スタート終了待ち
}


void mem24LC_stop_i2c(void) //I2Cストップ
{
   I2CXCONbits.PEN = 1;     // ストップ出力
   while(I2CXCONbits.PEN); // ストップ終了待ち

}




void mem24LC_write_byte_i2c(unsigned char byte)  //1バイト書込み
{

    I2CXTRN = byte;                 // データセット送信開始
    while(I2CXSTATbits.TBF);        // 送信終了待ち
    while(I2CXSTATbits.ACKSTAT);    // ACK返信待ち
    mem24LC_Idle_i2c();                     // アイドル待ち

}

void mem24LC_restart_i2c(void)
{
    I2CXCONbits.RSEN = 1;           //リスタート条件出力
    while(I2CXCONbits.RSEN);                //出力完了待ち
}

unsigned char mem24LC_ReadChr(unsigned char adr_chips, unsigned int adr_chip_inner)
{
        unsigned char data; //EEPROM読み込みデータ
        char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110));      //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0
        char adr_read_cmd =  ((0xa0 | (adr_chips << 1)) | (0b00000001));      //(アドレス + 読み込みコマンド)作成 R/Wビット: 読込み=1

        mem24LC_Reset_i2C();    //erratta 対策

        mem24LC_start_i2c();    //スタート条件送信
        mem24LC_Idle_i2c();     //アイドル待

        mem24LC_write_byte_i2c(adr_write_cmd);  // (I2Cバスアドレス + 書き込みコマンド)送信
        mem24LC_Idle_i2c();
        
        mem24LC_write_byte_i2c(adr_chip_inner >> 8);        //EEPROM内部アドレスの上位送信
        mem24LC_Idle_i2c();

        mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF);    //EEPROM内部アドレスの下位送信
        mem24LC_Idle_i2c();
        
        mem24LC_restart_i2c();  //再スタート条件送信
        mem24LC_Idle_i2c();

        mem24LC_write_byte_i2c(adr_read_cmd);   //(I2Cバスアドレス + 読み込みコマンド)送信
        mem24LC_Idle_i2c();

        I2CXCONbits.RCEN = 1;           //受信許可

        while(!I2CXSTATbits.RBF);       //受信バッファI2CXRCVが フルになるまで待つ  //Receive complete, I2CxRCV is full

        data = I2CXRCV;                 //受信バッファI2CXRCV読み込み

        mem24LC_stop_i2c();     //ストップ条件送信
        mem24LC_Idle_i2c();

        mem24LC_Reset_i2C();    //erratta 対策

        return data;

}

void mem24LC_ReadStr(unsigned char adr_chips, unsigned int adr_chip_inner)  //文字列 読み込み
{
    int ix = 0;

        char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110));      //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0
        char adr_read_cmd =  ((0xa0 | (adr_chips << 1)) | (0b00000001));      //(アドレス + 読み込みコマンド)作成 R/Wビット: 読込み=1

        mem24LC_Reset_i2C();    //erratta 対策

        mem24LC_start_i2c();    //スタート条件送信
        mem24LC_Idle_i2c();     //アイドル待

        mem24LC_write_byte_i2c(adr_write_cmd);  // (I2Cバスアドレス + 書き込みコマンド)送信
        mem24LC_Idle_i2c();

        mem24LC_write_byte_i2c(adr_chip_inner >> 8);        //EEPROM内部アドレスの上位送信
        mem24LC_Idle_i2c();

        mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF);    //EEPROM内部アドレスの下位送信
        mem24LC_Idle_i2c();

        mem24LC_restart_i2c();  //再スタート条件送信
        mem24LC_Idle_i2c();

        mem24LC_write_byte_i2c(adr_read_cmd);   //(I2Cバスアドレス + 読み込みコマンド)送信
        mem24LC_Idle_i2c();


         while(1)        //文字列データの取得
        {
            I2CXCONbits.RCEN = 1;           //受信許可
            while(!I2CXSTATbits.RBF);       //受信バッファI2CXRCVが フルになるまで待つ  //Receive complete, I2CxRCV is full
            read_data[ix] = I2CXRCV;                 //受信バッファI2CXRCV読み込み

            if(read_data[ix] == '\r' || ix >= 16)break;   //データ終端検出

            I2CXCONbits.ACKDT = 0;          //更にデータ送信をスレーブに要求するのでACK=0をセットする        //AckIC1();
            I2CXCONbits.ACKEN = 1;          //ACKDTにセットされている ACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
            while(I2CXCONbits.ACKEN);       //送信完了を待つ //ACKENは送信完了でハードによりクリアされる

            ix++;

        }

        read_data[ix] = '\0';     //配列を文字列化

        I2CXCONbits.ACKDT = 1;          //スレーブからの文字送信要求は終了なのでNACK=1をセット         //      NotAckI2C1();
                                                                                //vs 更にデータ送信をスレーブに要求する場合は、ACK=0をセットする //AckI2C1();
        I2CXCONbits.ACKEN = 1;          //ACKDTにセットされている NACKかACKをSDAから送信(SCLクロック数:9 = 8 (データ用)+1(ACKEN用))
        while(I2CXCONbits.ACKEN);       //送信完了を待つ //ACKENは送信完了でハードによりクリアされる

        mem24LC_stop_i2c();     //ストップ条件送信
        mem24LC_Idle_i2c();

        mem24LC_Reset_i2C();    //erratta 対策



}


void mem24LC_WriteChr(unsigned char adr_chips, unsigned int adr_chip_inner, unsigned char data)
{
     char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110));      //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0


        mem24LC_Reset_i2C();    //erratta 対策

        mem24LC_start_i2c();    //スタート条件 送信
        mem24LC_Idle_i2c();     //アイドル待ち

        mem24LC_write_byte_i2c(adr_write_cmd);  // (I2Cバスアドレス + 書き込みコマンド)送信
        mem24LC_Idle_i2c();

        mem24LC_write_byte_i2c(adr_chip_inner >> 8);        //EEPROM内部アドレスの上位送信
        mem24LC_Idle_i2c();

        mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF);    //EEPROM内部アドレスの下位送信
        mem24LC_Idle_i2c();


        mem24LC_write_byte_i2c(data);   //データ送信
        mem24LC_Idle_i2c();


        mem24LC_stop_i2c();     //ストップ条件 送信
        mem24LC_Reset_i2C();                                    //errata 対策
        mem24LC_Idle_i2c();

        mem24LC_delay_ms(5);    //EEPROM書き込み待ち

        mem24LC_Reset_i2C();    //erratta 対策


}



void mem24LC_WriteStr(unsigned char adr_chips, unsigned int adr_chip_inner, char* str)  //文字列書込み
{
     char adr_write_cmd = ((0xa0 | (adr_chips << 1)) & (0b11111110));      //(アドレス + 書き込みコマンド)作成 R/Wビット: 書込み=0

        mem24LC_Reset_i2C();    //erratta 対策

        mem24LC_start_i2c();    //スタート条件 送信
        mem24LC_Idle_i2c();     //アイドル待ち

        mem24LC_write_byte_i2c(adr_write_cmd);  // (I2Cバスアドレス + 書き込みコマンド)送信
        mem24LC_Idle_i2c();

        mem24LC_write_byte_i2c(adr_chip_inner >> 8);        //EEPROM内部アドレスの上位送信
        mem24LC_Idle_i2c();

        mem24LC_write_byte_i2c(adr_chip_inner & 0x00FF);    //EEPROM内部アドレスの下位送信
        mem24LC_Idle_i2c();

         while(*str)
        {
                mem24LC_write_byte_i2c(*str);   //データ送信
                mem24LC_Idle_i2c();
                str++;

        }


        mem24LC_stop_i2c();     //ストップ条件 送信
        mem24LC_Reset_i2C();    //errata 対策
        mem24LC_Idle_i2c();


        mem24LC_delay_ms(5);    //EEPROM書き込み待ち

        mem24LC_Reset_i2C();    //erratta 対策


}

















<動作結果>


  液晶表示 
 モード1 
 モード2 

 


■ I2Cインターフェースキャラクタ液晶の表示
 
(1) XC32  Harmony   PIC32MZ2048ECH100編

  PIC32MZ2048ECH100 revison 5の I2Cを動かすには 下記等のエラッタ対策が必要となります。

       Setting the PEN bit to send a Stop does not release the SDA


 <試作品仕様>
   ・ キャラクタ液晶は、I2cインターフェースの秋月電子 ACM1602N1 16文字x 2行 とする
   ・ 
表示する文字は 3秒間隔で交互に変更する。
   ・ 表示する文字は 以下とする
     モード1  上段: Hellow
            下段: World !!
     モード2  上段: PIC32MZ running
            下段: at I2c mode

   ・開発環境: Harmony  ver. 1.02    XC32 ver.1.34   MPLAB X  ver.2.26   PIC32MZ2048ECH100  revision 5
    
 
<試作品回路図>(→回路図のPDFファイル



<試作品外観>下記の写真には上記回路図にはない、また本テーマと関係のない部品が多々写っています


          

   <プログラム例>
//以下main.c
//------------------------------------------------------------------------------------------------------------------------- /******************************************************************************* MPLAB Harmony Project Main Source File Company: Microchip Technology Inc. File Name: main.c Summary: This file contains the "main" function for an MPLAB Harmony project. Description: This file contains the "main" function for an MPLAB Harmony project. The "main" function calls the "SYS_Initialize" function to initialize the state machines of all MPLAB Harmony modules in the system and it calls the "SYS_Tasks" function from within a system-wide "super" loop to maintain their correct operation. These two functions are implemented in configuration-specific files (usually "system_init.c" and "system_tasks.c") in a configuration-specific folder under the "src/system_config" folder within this project's top-level folder. An MPLAB Harmony project may have more than one configuration, each contained within it's own folder under the "system_config" folder. *******************************************************************************/ // DOM-IGNORE-BEGIN /******************************************************************************* Copyright (c) 2013-2014 released Microchip Technology Inc. All rights reserved. //Microchip licenses to you the right to use, modify, copy and distribute Software only when embedded on a Microchip microcontroller or digital signal controller that is integrated into your product or third party product (pursuant to the sublicense terms in the accompanying license agreement). You should refer to the license agreement accompanying this Software for additional information regarding your rights and obligations. SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. *******************************************************************************/ // DOM-IGNORE-END // ***************************************************************************** // ***************************************************************************** // Section: Included Files // ***************************************************************************** // ***************************************************************************** #include <stddef.h> // Defines NULL #include <stdbool.h> // Defines true #include <stdlib.h> // Defines EXIT_FAILURE #include "system/common/sys_module.h" // SYS function prototypes // ***************************************************************************** // ***************************************************************************** // Section: Main Entry Point // ***************************************************************************** // ***************************************************************************** int main ( void ) { /* Initialize all MPLAB Harmony modules, including application(s). */ SYS_Initialize ( NULL ); while ( true ) { /* Maintain state machines of all polled MPLAB Harmony modules. */ SYS_Tasks ( ); } /* Execution should not come here during normal operation */ return ( EXIT_FAILURE ); } /******************************************************************************* End of File */ //以下、 system_init.c //-------------------------------------------------------------------------------------------------- /******************************************************************************* System Initialization File File Name: system_init.c Summary: This file contains source code necessary to initialize the system. Description: This file contains source code necessary to initialize the system. It implements the "SYS_Initialize" function, configuration bits, and allocates any necessary global system resources, such as the systemObjects structure that contains the object handles to all the MPLAB Harmony module objects in the system. *******************************************************************************/ // DOM-IGNORE-BEGIN /******************************************************************************* Copyright (c) 2013-2014 released Microchip Technology Inc. All rights reserved. Microchip licenses to you the right to use, modify, copy and distribute Software only when embedded on a Microchip microcontroller or digital signal controller that is integrated into your product or third party product (pursuant to the sublicense terms in the accompanying license agreement). You should refer to the license agreement accompanying this Software for additional information regarding your rights and obligations. SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. *******************************************************************************/ // DOM-IGNORE-END // ***************************************************************************** // ***************************************************************************** // Section: Included Files // ***************************************************************************** // ***************************************************************************** #include "system_config.h" #include "system_definitions.h" #include "app.h" // **************************************************************************** // **************************************************************************** // Section: Configuration Bits // **************************************************************************** // **************************************************************************** //コンフィグ //----------------------------------------------------------------------- //DEVCFG0レジスタ #pragma config EJTAGBEN = NORMAL #pragma config DBGPER = ALLOW_PG2 #pragma config FSLEEP = OFF #pragma config FECCCON = OFF_UNLOCKED #pragma config BOOTISA = MIPS32 #pragma config TRCEN = OFF #pragma config ICESEL = ICS_PGx2 #pragma config JTAGEN = OFF //JTAG ポート Disable #pragma config DEBUG = OFF //---------------------------------------------------------------------- //DEVCFG1レジスタ #pragma config FNOSC = SPLL //PLL回路(システムPLL)選択 //システム発振回路 //内蔵FRC(8MHz)選択の場合:FNOSC = FRCDIV //Oscillator Selection Bits (Fast RC Osc w/Div-by-N (FRCDIV)) #pragma config FDMTEN = OFF //デッドマンタイマ OFF (Deadman Timer is disabled) //#pragma config DMTINTV = WIN_127_128 // DMT Count Window Interval (Window/Interval value is 127/128 counter value) #pragma config FSOSCEN = OFF // 副発振器OFF //Secondary Oscillator Enable (Disable SOSC) #pragma config IESO = OFF //ウェイクアップ時の2段速度スタートアップ // Internal/External Switch Over (Disabled) #pragma config POSCMOD = HS //HS: ハイスピードレゾネータモード // HS(High Speed Resonator Operation) Oscillator mode selected //EC: 外部発振器 //EC(External Clock Input Operation) mode selected // Primary Oscillator Configuration (Primary osc disabled) #pragma config OSCIOFNC = OFF //OSCCOピン出力無効 #pragma config FCKSM = CSECME //クロック発振:切替及びモニタ有効 //主発振器失陥でFRC(内蔵高速発振器)に切替 //FSCM(Fail Safe Clock Monitor)制御 #pragma config FWDTEN = OFF // ウォッチドックタイマ OFF //Watchdog Timer Disable //#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576) //#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming) //#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode) //#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%) //-------------------------------------------------------------------------------------------------------------------- // DEVCFG2レジスタ //システムクロック:200MHz //ペリフェラル周波数://default: 100MHz //PBxDIVで8系統毎に設定変更可 //PBxDIV: PERIPHERAL BUS CLOCK DIVISOR CONTROL レジスタのPBDIV<6:0>: Peripheral Bus Clock Divisor Control ビットで設定 #pragma config FPLLRNG = RANGE_5_10_MHZ //PLL Input周波数入力範囲設定// System PLL Input Range (5-10 MHz Input)  //8(= 24/3)MHz故 #pragma config FPLLIDIV = DIV_3 //PLL入力側での分周: 1/3 // PLL Input周波数 = 24MHz ÷ 3 = 8MHz // System PLL Input Divider (1x Divider) //#pragma config FPLLICLK = PLL_POSC //主発振回路選択 //内蔵FRC(8MHz)の場合はFPLLICLK = PLL_FRC// System PLL Input Clock Selection (POSC is input to the System PLL) #pragma config FPLLICLK = PLL_FRC //内蔵高速発振器選択 //★★★ バグ有 主発振回路選択の時、FPLLICLK = PLL_POSCではなくFPLLICLK = PLL_FRCを選択する。(at ver.1.33 XC32) #pragma config FPLLMULT = MUL_50 //PLL倍率:50倍 //8MHz x 50 = 400MHz //System PLL Multiplier (PLL Multiply by 50) #pragma config FPLLODIV = DIV_2 //PLL出力側での分周: 1/2 //システムクロック = 400MHz ÷ 2 = 200MHz #pragma config UPLLFSEL = FREQ_24MHZ //USBのPLL入力を 24MHz→12MHzに変換 // USB PLL Input Frequency Selection (USB PLL input is 12 MHz) #pragma config UPLLEN = ON //USBのPLL変換:イネーブル // USB PLL Enable (USB PLL is enabled) //-------------------------------------------------------------------------------------------------------------------------- //DEVCFG3レジスタ #pragma config USERID = 0xffff #pragma config FMIIEN = ON #pragma config FETHIO = ON #pragma config PGL1WAY = ON #pragma config PMDL1WAY = ON #pragma config IOL1WAY = ON #pragma config FUSBIDIO = ON /*** BF1SEQ0 ***/ #pragma config TSEQ = 0xffff #pragma config CSEQ = 0xffff // ***************************************************************************** // ***************************************************************************** // Section: Library/Stack Initialization Data // ***************************************************************************** // *****************************************************************************/ // ***************************************************************************** // ***************************************************************************** // Section: Driver Initialization Data // ***************************************************************************** // ***************************************************************************** //<editor-fold defaultstate="collapsed" desc="DRV_I2C Configuration"> // ***************************************************************************** /* I2C Driver Initialization Data */ const DRV_I2C_INIT drvI2C0InitData = { .i2cId = DRV_I2C_PERIPHERAL_ID_IDX0, .i2cMode = DRV_I2C_OPERATION_MODE_IDX0, .baudRate = DRV_I2C_BAUD_RATE_IDX0, .busspeed = DRV_I2C_SLEW_RATE_CONTROL_IDX0, .buslevel = DRV_I2C_SMBus_SPECIFICATION_IDX0, .mstrInterruptSource = DRV_I2C_MASTER_INT_SRC_IDX0, .slaveInterruptSource = DRV_I2C_SLAVE_INT_SRC_IDX0, .errInterruptSource = DRV_I2C_ERR_MZ_INT_SRC_IDX0, }; // </editor-fold> // ***************************************************************************** // ***************************************************************************** // Section: System Data // ***************************************************************************** // ***************************************************************************** /* Structure to hold the object handles for the modules in the system. */ SYSTEM_OBJECTS sysObj; // ***************************************************************************** // ***************************************************************************** // Section: Module Initialization Data // ***************************************************************************** // ***************************************************************************** //<editor-fold defaultstate="collapsed" desc="SYS_DEVCON Configuration"> /*** System Device Control Initialization Data ***/ const SYS_DEVCON_INIT sysDevconInit = { .moduleInit = {0}, }; // </editor-fold> // ***************************************************************************** // ***************************************************************************** // Section: Static Initialization Functions // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // Section: System Initialization // ***************************************************************************** // ***************************************************************************** /******************************************************************************* Function: void SYS_Initialize ( SYS_INIT_DATA *data ) Summary: Initializes the board, services, drivers, application and other modules. Remarks: See prototype in system/common/sys_module.h. */ void SYS_Initialize ( void* data ) { /* Core Processor Initialization */ SYS_CLK_Initialize( NULL ); sysObj.sysDevcon = SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)&sysDevconInit); SYS_DEVCON_PerformanceConfig(SYS_CLK_SystemFrequencyGet()); SYS_DEVCON_JTAGDisable(); SYS_PORTS_Initialize(); /* Initialize Drivers */ sysObj.drvI2C0 = DRV_I2C_Initialize(DRV_I2C_INDEX_0, (SYS_MODULE_INIT *)&drvI2C0InitData); /* // I2Cの初期設定 100kHz 7bit address I2C2CONbits.ON = 0; //IC2モジュール:OFF I2C2CONbits.A10M = 0; //7 bit アドレス I2C2BRG = 498; //Fscl = PBCLK2 / 2 /(BRG + 2) = 100 MHz / 2 / (498 + 2) = 100 KHz I2C2CONbits.ON = 1; //IC2モジュール:ON */ /* Initialize System Services */ /* Initialize Middleware */ /* Initialize the Application */ APP_Initialize(); } /******************************************************************************* End of File */ //以下、system_app.c //----------------------------------------------------------------------------------------------------------------------- /******************************************************************************* MPLAB Harmony Application Source File Company: Microchip Technology Inc. File Name: app.c Summary: This file contains the source code for the MPLAB Harmony application. Description: This file contains the source code for the MPLAB Harmony application. It implements the logic of the application's state machine and it may call API routines of other MPLAB Harmony modules in the system, such as drivers, system services, and middleware. However, it does not call any of the system interfaces (such as the "Initialize" and "Tasks" functions) of any of the modules in the system or make any assumptions about when those functions are called. That is the responsibility of the configuration-specific system files. *******************************************************************************/ // DOM-IGNORE-BEGIN /******************************************************************************* Copyright (c) 2013-2014 released Microchip Technology Inc. All rights reserved. Microchip licenses to you the right to use, modify, copy and distribute Software only when embedded on a Microchip microcontroller or digital signal controller that is integrated into your product or third party product (pursuant to the sublicense terms in the accompanying license agreement). You should refer to the license agreement accompanying this Software for additional information regarding your rights and obligations. SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. *******************************************************************************/ // DOM-IGNORE-END // ***************************************************************************** // ***************************************************************************** // Section: Included Files // ***************************************************************************** // ***************************************************************************** #include "app.h" #include "lcd_ACM1602_lib_i2c.h" int delay_Clock = 200000000; //200MHz void delay_us(volatile unsigned int usec) //1μsec遅延 { volatile int count; count = (int)(delay_Clock/20000000)*usec; do //実測 at 200MH (delay_Clock=200000000) { //delay_us(1000):1000.4μsec delay_us(100):100.6μsec delay_us(10):10.5μsec  delay_us(1):1.5μsec asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); count--; }while(count != 0); } void delay_ms(volatile unsigned int msec) //1msec遅延 { volatile unsigned int i; //実測:at200MH (Clock=200000000)//delay_ms(1): 1.0006msec delay_ms(100):100.04msec for(i=0; i<msec; i++) delay_us(1000); } // ***************************************************************************** // ***************************************************************************** // Section: Global Data Definitions // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** /* Application Data Summary: Holds application data Description: This structure holds the application's data. Remarks: This structure should be initialized by the APP_Initialize function. Application strings and buffers are be defined outside this structure. */ APP_DATA appData; // ***************************************************************************** // ***************************************************************************** // Section: Application Callback Functions // ***************************************************************************** // ***************************************************************************** /* TODO: Add any necessary callback funtions. */ // ***************************************************************************** // ***************************************************************************** // Section: Application Local Functions // ***************************************************************************** // ***************************************************************************** /* TODO: Add any necessary local functions. */ // ***************************************************************************** // ***************************************************************************** // Section: Application Initialization and State Machine Functions // ***************************************************************************** // ***************************************************************************** /******************************************************************************* Function: void APP_Initialize ( void ) Remarks: See prototype in app.h. */ void APP_Initialize ( void ) { /* Place the App state machine in its initial state. */ appData.state = APP_STATE_INIT; /* TODO: Initialize your application's state machine and other * parameters. */ //初期設定: LED消灯 LATGbits.LATG15 = 0; //RG15 = 0 LED --> OFF//LED消灯 赤 LATDbits.LATD5 = 0; //RD5 = 0 LED --> OFF//LED消灯 赤 LATDbits.LATD4 = 0; //RD4 = 0 LED --> OFF//LED消灯 白 LATCbits.LATC14 = 0; //RC14 = 0 LED --> OFF//LED消灯 黄色 LATCbits.LATC13 = 0; //RC13 = 0 LED --> OFF//LED消灯 緑 lcd_ACM1602_init_i2c(); //I2Cインターフェース式液晶初期化 lcd_ACM1602_cmd_i2c(0x0C); //カーソル:0FF、ブリンク:0FF } /****************************************************************************** Function: void APP_Tasks ( void ) Remarks: See prototype in app.h. */ void APP_Tasks ( void ) { /* Check the application's current state. */ switch ( appData.state ) { /* Application's initial state. */ case APP_STATE_INIT: { lcd_ACM1602_cmd_i2c(0x80); //1行目の先頭へ lcd_ACM1602_str_i2c("Hellow"); lcd_ACM1602_cmd_i2c(0xC0); //2行目の先頭へ lcd_ACM1602_str_i2c(" World !!"); LATGbits.LATG15 = 1; //赤 点灯 LATDbits.LATD5 = 1; //赤 LATDbits.LATD4 = 1; //白 LATCbits.LATC14 = 1; //黄色 LATCbits.LATC13 = 1; //緑 delay_ms(3000); lcd_ACM1602_clear_i2c(); lcd_ACM1602_cmd_i2c(0x80); //1行目の先頭 lcd_ACM1602_str_i2c("PIC32MZ running"); lcd_ACM1602_cmd_i2c(0xC0); lcd_ACM1602_str_i2c(" at I2C mode"); LATGbits.LATG15 = 0; LATDbits.LATD5 = 0; //RD5 = 0 LED --> OFF//LED消灯 赤 LATDbits.LATD4 = 0; //RD4 = 0 LED --> OFF//LED消灯 白 LATCbits.LATC14 = 0; //RC14 = 0 LED --> OFF//LED消灯 黄色 LATCbits.LATC13 = 0; //RC13 = 0 LED --> OFF//LED消灯 緑 delay_ms(3000); lcd_ACM1602_clear_i2c(); break; } /* TODO: implement your application state machine.*/ /* The default state should never be executed. */ default: { /* TODO: Handle error in application's state machine. */ break; } } } /******************************************************************************* End of File */ //以下、system_config.h //----------------------------------------------------------------------------------------------------- /******************************************************************************* MPLAB Harmony System Configuration Header File Name: system_config.h Summary: Build-time configuration header for the system defined by this MPLAB Harmony project. Description: An MPLAB Project may have multiple configurations. This file defines the build-time options for a single configuration. Remarks: This configuration header must not define any prototypes or data definitions (or include any files that do). It only provides macro definitions for build-time configuration options that are not instantiated until used by another MPLAB Harmony module or application. Created with MPLAB Harmony Version 1.02 *******************************************************************************/ // DOM-IGNORE-BEGIN /******************************************************************************* Copyright (c) 2013-2014 released Microchip Technology Inc. All rights reserved. Microchip licenses to you the right to use, modify, copy and distribute Software only when embedded on a Microchip microcontroller or digital signal controller that is integrated into your product or third party product (pursuant to the sublicense terms in the accompanying license agreement). You should refer to the license agreement accompanying this Software for additional information regarding your rights and obligations. SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. *******************************************************************************/ // DOM-IGNORE-END #ifndef _SYSTEM_CONFIG_H #define _SYSTEM_CONFIG_H /* This is a temporary workaround for an issue with the peripheral library "Exists" functions that causes superfluous warnings. It "nulls" out the definition of The PLIB function attribute that causes the warning. Once that issue has been resolved, this definition should be removed. */ #define _PLIB_UNSUPPORTED // ***************************************************************************** // ***************************************************************************** // Section: Included Files // ***************************************************************************** // ***************************************************************************** /* This section Includes other configuration headers necessary to completely define this configuration. */ // ***************************************************************************** // ***************************************************************************** // Section: System Service Configuration // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** /* Clock System Service Configuration Options */ #define SYS_CLK_FREQ 200000000ul #define SYS_CLK_BUS_PERIPHERAL_1 100000000ul #define SYS_CLK_BUS_PERIPHERAL_2 100000000ul #define SYS_CLK_BUS_PERIPHERAL_3 100000000ul #define SYS_CLK_BUS_PERIPHERAL_4 100000000ul #define SYS_CLK_BUS_PERIPHERAL_5 100000000ul #define SYS_CLK_BUS_PERIPHERAL_7 200000000ul #define SYS_CLK_BUS_PERIPHERAL_8 100000000ul #define SYS_CLK_CONFIG_PRIMARY_XTAL 24000000ul #define SYS_CLK_CONFIG_SECONDARY_XTAL 0ul /*** Ports System Service Configuration ***/ #define SYS_PORT_G_ANSEL 0x7003 #define SYS_PORT_G_TRIS 0xf3c3 #define SYS_PORT_G_ODC 0x0 #define SYS_PORT_G_CNPU 0x0 #define SYS_PORT_G_CNPD 0x0 #define SYS_PORT_G_CNEN 0x0 /*** Console System Service Configuration DISABLED ***/ #define SYS_CONSOLE_MESSAGE(message) #define SYS_CONSOLE_PRINT(fmt, ...) /*** Command Processor System Service Configuration DISABLED ***/ #define SYS_CMD_MESSAGE(message) #define SYS_CMD_PRINT(fmt, ...) #define SYS_CMD_READY_TO_READ() // ***************************************************************************** // ***************************************************************************** // Section: Driver Configuration // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** /* I2C Driver Configuration Options */ #define DRV_I2C_INTERRUPT_MODE false #define DRV_I2C_CLIENTS_NUMBER 1 #define DRV_I2C_INSTANCES_NUMBER 1 #define DRV_I2C_PERIPHERAL_ID_IDX0 I2C_ID_2 //チャンネル2 選択 #define DRV_I2C_OPERATION_MODE_IDX0 DRV_I2C_MODE_MASTER //マスターモード #define DRV_I2C_STOP_IN_IDLE_IDX0 false #define DRV_I2C_SMBus_SPECIFICATION_IDX0 false #define DRV_I2C_BAUD_RATE_IDX0 50000 //I2cボーレート //50Kbps #define DRV_I2C_BRG_CLOCK_IDX0 100000000 #define DRV_I2C_SLEW_RATE_CONTROL_IDX0 false #define DRV_I2C_MASTER_INT_SRC_IDX0 INT_SOURCE_I2C_2_MASTER #define DRV_I2C_SLAVE_INT_SRC_IDX0 INT_SOURCE_I2C_2_SLAVE #define DRV_I2C_ERR_MZ_INT_SRC_IDX0 INT_SOURCE_I2C_2_BUS #define DRV_I2C_POWER_STATE_IDX0 SYS_MODULE_POWER_RUN_FULL // ***************************************************************************** // ***************************************************************************** // Section: Middleware & Other Library Configuration // ***************************************************************************** // ***************************************************************************** #endif // _SYSTEM_CONFIG_H /******************************************************************************* End of File */ //以下、sys_ports_static.c //--------------------------------------------------------------------------------------------- /******************************************************************************* SYS PORTS Static Functions for PORTS System Service Company: Microchip Technology Inc. File Name: sys_ports_static.c Summary: SYS PORTS static function implementations for the Ports System Service. Description: The Ports System Service provides a simple interface to manage the ports on Microchip microcontrollers. This file defines the static implementation for the Ports System Service. Remarks: Static functions incorporate all system ports configuration settings as determined by the user via the Microchip Harmony Configurator GUI. It provides static version of the routines, eliminating the need for an object ID or object handle. *******************************************************************************/ //DOM-IGNORE-BEGIN /******************************************************************************* Copyright (c) 2013 released Microchip Technology Inc. All rights reserved. Microchip licenses to you the right to use, modify, copy and distribute Software only when embedded on a Microchip microcontroller or digital signal controller that is integrated into your product or third party product (pursuant to the sublicense terms in the accompanying license agreement). You should refer to the license agreement accompanying this Software for additional information regarding your rights and obligations. SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. *******************************************************************************/ //DOM-IGNORE-END #include "system_config.h" #include "peripheral/ports/plib_ports.h" #include "peripheral/int/plib_int.h" void SYS_PORTS_Initialize(void) { //LEDポート 出力ポートに設定-------------------- //PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_G, 15 );//LED 出力ポートに設定 TRISGbits.TRISG15 = 0; //RG15 : out//LED 出力ポートに設定 //PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_C, 13 );//LED 出力ポートに設定 TRISCbits.TRISC13 = 0; //RC13 : out//LED 出力ポートに設定 //PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_C, 14 );//LED 出力ポートに設定 TRISCbits.TRISC14 = 0; //RC14 : out//LED 出力ポートに設定 //PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_D, 4 );//LED 出力ポートに設定 TRISDbits.TRISD4 = 0; //RD4 : out//LED 出力ポートに設定 //PLIB_PORTS_PinDirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_D, 5 );//LED 出力ポートに設定 TRISDbits.TRISD5 = 0; //RD5 : out//LED 出力ポートに設定 /* PPS Input Remapping */ /* PPS Output Remapping */ } /******************************************************************************* End of File */ //以下、lcd_ACM1602_lib_i2c.h //---------------------------------------------------------------------------------------- //lcd_ACM1602_lib_i2c.h /////////////////////////////////////////////// // 秋月 キャラクタ液晶 ACM1602NI // I2Cインターフェース 16文字 x 2行 for PIC32MX & XC32コンパイラ // Vcc: 2.7v -5.5v // //  lcd_init_i2c() ----- 初期化 // lcd_cmd_i2c(cmd) ----- コマンド出力 // lcd_data_i2c(chr) ----- 1文字表示出力 // lcd_clear_i2c() ----- 全消去 // lcd_str_i2c(str*) ----- 文字列表示 // lcd_cmd_i2c(0x0C); //カーソル:0FF、ブリンク:0FF // lcd_cmd_i2c(0x80); //1行目の先頭へ // lcd_cmd_i2c(0xC0); //2行目の先頭へ ////////////////////////////////////////////// #define lcd_Clock_i2c 200000000 // 単位はHzで指定 // I2Cレジスタ設定 #define I2CXCONbits I2C2CONbits //I2C制御レジスタ設定 #define I2CXSTATbits I2C2STATbits //I2C状態レジスタ設定 #define I2CXTRN I2C2TRN //I2C送信バッファレジスタ設定 //関数プロトタイプ宣言 void lcd_ACM1602_start_i2c(void); void lcd__ACM1602_stop_i2c(void); void lcd_ACM1602_write_byte_i2c(unsigned char byte); //1バイト書込み void lcd_ACM1602_WtiteCommand_i2c(unsigned char command); //コマンド送信 void lcd_ACM1602_WriteData_i2c(unsigned char data); //データ送信 void lcd_ACM1602_Idle_i2c(void); //アイドル待ち void lcd_ACM1602_cmd_i2c(unsigned char cmd); void lcd_ACM1602_data_i2c(unsigned char data); void lcd_ACM1602_clear_i2c(void); //画面クリア void lcd_ACM1602_str_i2c(const unsigned char* str); void lcd_ACM1602_init_i2c(void); //初期化 void lcd_ACM1602_delay_us_i2c(unsigned int usec); //1μsec遅延関数 void lcd_ACM1602_delay_ms_i2c(unsigned int msec); //1msec遅延関数 //以下、lcd_ACM1602_lib_i2c.c //----------------------------------------------------------------------------------------------------- //lcd_ACM1602_lib_i2c.c /////////////////////////////////////////////// // 秋月 キャラクタ液晶 ACM1602NI // I2Cインターフェース 16文字 x 2行 for PIC32MX & XC32コンパイラ // Vcc: 2.7v -5.5v // //  lcd_init_i2c() ----- 初期化 // lcd_cmd_i2c(cmd) ----- コマンド出力 // lcd_data_i2c(chr) ----- 1文字表示出力 // lcd_clear_i2c() ----- 全消去 // lcd_str_i2c(str*) ----- 文字列表示 // lcd_cmd_i2c(0x0C); //カーソル:0FF、ブリンク:0FF // lcd_cmd_i2c(0x80); //1行目の先頭へ // lcd_cmd_i2c(0xC0); //2行目の先頭へ ////////////////////////////////////////////// #include "lcd_ACM1602_lib_i2c.h" #ifndef MY_INCLUDE_XC_H #define MY_INCLUDE_XC_H #include <xc.h> //追加 #endif void lcd_ACM1602_delay_us_i2c(unsigned int usec) //1μsec遅延関数 { int count; count = (int)(lcd_Clock_i2c/20000000)*usec; do //実測: at 200MH (Clock=200000000) { //delay_us(1000)→1000.4μsec、 delay_us(100)→100.6μsec、delay_us(10)→10.5μsec、delay_us(1)→1.5μsec asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); count--; }while(count != 0); } void lcd_ACM1602_delay_ms_i2c(unsigned int msec) //1msec遅延関数 { unsigned int i; for(i=0; i<msec; i++) lcd_ACM1602_delay_us_i2c(1000); } void lcd_ACM1602_Reset_i2C(void) { I2CXCONbits.ON = 0; //IC2モジュール:OFF I2CXCONbits.ON = 1; //IC2モジュール:ON } void lcd_ACM1602_Idle_i2c(void) //アイドル待ち { while(I2CXCONbits.SEN || I2CXCONbits.PEN || I2CXCONbits.RCEN || I2CXCONbits.ACKEN || I2CXSTATbits.TRSTAT); } void lcd_ACM1602_start_i2c(void) //I2Cスタート { lcd_ACM1602_Idle_i2c(); I2CXCONbits.SEN = 1; // スタート出力// while(I2CXCONbits.SEN); // スタート終了待ち } void lcd_ACM1602_stop_i2c(void) //I2Cストップ { I2CXCONbits.PEN = 1; // ストップ出力 while(I2CXCONbits.PEN); // ストップ終了待ち } void lcd_ACM1602_write_byte_i2c(unsigned char byte) //1バイト書込み { I2CXTRN = byte; // データセット送信開始 while(I2CXSTATbits.TBF); // 送信終了待ち while(I2CXSTATbits.ACKSTAT); // ACK返信待ち lcd_ACM1602_Idle_i2c(); // アイドル待ち } void lcd_ACM1602_WtiteCommand_i2c(unsigned char command) //コマンド送信 { lcd_ACM1602_Reset_i2C(); //i2Cモジュール 再スタート lcd_ACM1602_start_i2c(); lcd_ACM1602_write_byte_i2c(0xa0); // アドレス+送信モード送信 lcd_ACM1602_Idle_i2c(); lcd_ACM1602_delay_us_i2c(10); lcd_ACM1602_write_byte_i2c(0x00); // レジスタ指定送信 lcd_ACM1602_Idle_i2c(); lcd_ACM1602_delay_us_i2c(10); lcd_ACM1602_write_byte_i2c(command);// コマンド送信 lcd_ACM1602_Idle_i2c(); lcd_ACM1602_delay_us_i2c(10); lcd_ACM1602_stop_i2c(); } void lcd_ACM1602_WriteData_i2c(unsigned char data) //データ送信 { lcd_ACM1602_Reset_i2C(); //i2Cモジュール 再スタート lcd_ACM1602_start_i2c(); lcd_ACM1602_write_byte_i2c(0xa0); // アドレス+送信モード送信 lcd_ACM1602_Idle_i2c(); lcd_ACM1602_delay_us_i2c(10); lcd_ACM1602_write_byte_i2c(0x80); // レジスタ指定送信 lcd_ACM1602_Idle_i2c(); lcd_ACM1602_delay_us_i2c(10); lcd_ACM1602_write_byte_i2c(data); // データ送信 lcd_ACM1602_Idle_i2c(); lcd_ACM1602_delay_us_i2c(10); lcd_ACM1602_stop_i2c(); } void lcd_ACM1602_cmd_i2c(unsigned char cmd) { lcd_ACM1602_WtiteCommand_i2c(cmd); // lcd_ACM1602_Idle_i2c(); if((cmd == 0x01)||(cmd == 0x02)) // Clear or Homeコマンドの場合 lcd_ACM1602_delay_ms_i2c(3); // 3msec待ち else lcd_ACM1602_delay_us_i2c(60); //60μsec待ち } void lcd_ACM1602_init_i2c(void) //液晶初期化 { lcd_ACM1602_delay_ms_i2c(100); lcd_ACM1602_cmd_i2c(0x01); //WtiteCommand(0x01); lcd_ACM1602_delay_ms_i2c(5); //delay at least 5ms lcd_ACM1602_cmd_i2c(0x38); //WtiteCommand(0x38); lcd_ACM1602_delay_ms_i2c(5); //delay at least 5ms lcd_ACM1602_cmd_i2c(0x0f); //WtiteCommand(0x0f); lcd_ACM1602_delay_ms_i2c(5); //delay at least 5ms lcd_ACM1602_cmd_i2c(0x0f); //WtiteCommand(0x06); lcd_ACM1602_delay_ms_i2c(5); //delay at least 5ms } void lcd_ACM1602_data_i2c(unsigned char data) //1文字表示 { lcd_ACM1602_WriteData_i2c(data); // lcd_ACM1602_delay_us_i2c(30); //delay_us(30); // 遅延 } void lcd_ACM1602_clear_i2c(void) //画面クリア { lcd_ACM1602_cmd_i2c(0x01); //初期化コマンド出力 } void lcd_ACM1602_str_i2c(const unsigned char* str) //文字列表示 { while(*str != 0) ////文字列終端の '\0'を検出するまで lcd_ACM1602_data_i2c(*str++); //1文字表示 }

<実行結果> 

液晶画面
 表示モード1 
 表示モード2