15章:I2C仕様EEPROM評価回路

    作成2014.03.29

     PIC18F4553マイコンI2C仕様EEPROMの使用方法を検討してみたいと思います。

  1. I2C仕様EEPROM評価回路
     秋月電子通商 シリアルIスケアC EEPROM 24FC256−I/P 価格:¥90を使用します。

     I2C仕様EEPROM評価回路図を図15-1に示します。
     図15-1において、
    (1)RB0とEEPROMのSDAを接続します。そして10kΩの抵抗をかいして+5Vでプルアップします。(プルアップは必須条件です。)
    (2)RB1とEEPROMのSCLを接続します。そして10kΩの抵抗をかいして+5Vでプルアップします。(プルアップは必須条件です。)
    (3)+5Vとアースの間に0.1μFのコンデンサを設置します。(必須ではないかもしれません)
    (4)結果表示用に8個のLEDを設置します。(結果は2進表示です)

    注意!! +5Vのプルアップをわすれないようにしましょう!!プルアップをわすれて大変苦労しました!!



  2. I2C初期設定
     基本的に以下の設定が不可欠です。
    (1)SSPCON1 = 0x28;
    *SSPBUFへのライト衝突なし
    *受信オーバーフロー無し
    *シリアルポートを動作させ、SDAとSCLピンをシリアルポートピンにする。
    * I2C マスターモード、クロック= FOSC / (4 * (SSPADD+1) ) が設定されます。
    (2)SSPADD = 0x0F;
    *クロック= FOSC / (4 * 16) を設定
    (3)TRISB = 0b00000011;
    *RB0とRB1を入力モードに設定


  3. 送信の基本手順
     送信の基本手順は以下の通りです。

    (1)PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    *通信割込みフラグクリアして通信準備
    (2)SSPCON2bits.SEN = 1;//I2C_startビット
    *startビットを設定
    (3)while (SSPCON2bits.SEN) {}//終了待ち
    *startビットを設定終了待ち

    (4)PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    *通信割込みフラグクリアして通信準備
    (5)while(SSPSTATbits.BF){};//SSPBUFの干渉確認
    *SSPBUFの干渉確認(省略可能です)
    (6)SSPBUF =8bit送信データ;//8bit送信データを設定
    *SSPBUに8bit送信データを設定
    (7)if (SSPCON2bits.ACKSTAT) {PORTD=0b11111110;}//ACKチェック
    *ACKチェック(省略可能です)
    (8)while (!PIR1bits.SSPIF) {}//終了待ち
    *送信終了待ち

    (9)PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    *通信割込みフラグクリアして通信準備
    (10)SSPCON2bits.PEN = 1;//I2C_通信終了
    *ストップビットを設定
    (11)while (SSPCON2bits.PEN) {}//終了待ち
    *ストップビットを設定終了待ち


  4. 受信の基本手順
     受信の基本手順は以下の通りです。

    (1)PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    *通信割込みフラグクリアして通信準備
    (2)SSPCON2bits.SEN = 1;//I2C_startビット
    *startビットを設定
    (3)while (SSPCON2bits.SEN) {}//終了待ち
    *startビットを設定終了待ち

    (4)PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    *通信割込みフラグクリアして通信準備
    (5)while(SSPSTATbits.BF){}; 0b00000011;
    *SSPBUFの干渉確認(省略可能です)
    (6)SSPBUF =8bit受信コマンド;//8bit受信コマンドを設定
    *SSPBUに8bit受信コマンドを設定
    (7)if (SSPCON2bits.ACKSTAT) {PORTD=0b11111110;}//ACKチェック
    *ACKチェック(省略可能です)
    (8)while (!PIR1bits.SSPIF) {}//終了待ち
    *送信終了待ち

    (9)PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    *通信割込みフラグクリアして通信準備
    (10)SSPCON2bits.RCEN = 1;//受信モードを動作
    *受信モードを動作させる
    (11)while (SSPCON2bits.RCEN) {}//終了待ち
    *受信モードを動作終了待ち
    (12)c=SSPBUF;//受信コピー
    *受信コピー

    (13)PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    *通信割込みフラグクリアして通信準備
    (14)SSPCON2bits.ACKDT = 1;//受信の終わりで応答シーケンスを開始1=NO-ACK
    *NO-ACKを設定
    (15)SSPCON2bits.ACKEN = 1;//、ACKDT データビットを送信する。
    *NO-ACKを送信
    (16)while (SSPCON2bits.ACKEN) {}//終了待ち 0x3FEE
    *NO-ACKを送信終了待ち 0x3FED
    0x3FEC

    (17)PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    *通信割込みフラグクリアして通信準備
    (18)SSPCON2bits.PEN = 1;//I2C_通信終了
    *ストップビットを設定
    (19)while (SSPCON2bits.PEN) {}//終了待ち
    *ストップビットを設定終了待ち


  5. I2CによるEEPROM送信・受信ソースプログラム
     具体的な送信・受信ソースプログラムは通信相手の仕様により変化しますが、I2CによるEEPROM 送信・受信ソースプログラムは以下のようになります。
    #include <xc.h>
    #include <p18f4553.h>
    #include <pic18f4553.h>
    
    #pragma config PLLDIV   = 5	// (20MHz crystal)
    #pragma config CPUDIV   = OSC1_PLL2	//「 主 発振 器 そのまま」「システム96MHzPLLソースを2 分 の 一 」
    #pragma config USBDIV   = 2	// Clock source from 96MHz PLL/2
    #pragma config FOSC     = HSPLL_HS	//外付け振動子利用の高速クロック発振で、PLLを 使 う
    #pragma config FCMEN    = OFF	//フェイルセーフクロックモニターを 無効
    #pragma config IESO     = OFF	//発振 器 の 内部 外部 切 り 替 えを 無効
    #pragma config PWRT     = OFF	//電源オン時タイマーを使わない
    #pragma config BOR      = ON	//ハードだけでブラウンアウトリセット 機能 を使う
    #pragma config BORV     = 3	//最小電圧設定
    #pragma config VREGEN   = ON	//USB Voltage Regulator = ON
    #pragma config WDT      = OFF	//ウオッチドッグタイマを 無効
    #pragma config WDTPS    = 32768	//ウォッチドッグタイマーのプリスケーラが1:32,768
    #pragma config MCLRE    = ON	//MCLRを 有効 にしてRE3入力端子は 無効
    #pragma config LPT1OSC  = OFF	//タイマー1 発振 器 を 高電力 モードにする
    #pragma config PBADEN   = OFF	//リセット 時 にPORTB0〜4をデジタル 入出力 に 選択 する
    #pragma config CCP2MX   = OFF	//CCP2の入出力をRB3にマルチプレックスしない
    #pragma config STVREN   = ON	//スタック満杯あるいはアンダーフロー時にリセットする
    #pragma config LVP      = OFF	//ICSPモードでの単一書き込み電源は 使 わない
    #pragma config ICPRT    = OFF	// Dedicated In-Circuit Debug/Programming = OFF
    #pragma config XINST    = OFF	// Extended Instruction Set = OFF
    #pragma config CP0      = OFF	//ブロック0(000800−001FFFh)のコードを保護しない
    #pragma config CP1      = OFF
    #pragma config CP2      = OFF
    #pragma config CP3      = OFF
    #pragma config CPB      = OFF
    #pragma config CPD      = OFF
    #pragma config WRT0     = OFF	//ブロック0 (000800-001FFFh) の書込み保護しない
    #pragma config WRT1     = OFF
    #pragma config WRT2     = OFF
    #pragma config WRT3     = OFF
    #pragma config WRTB     = OFF	// Boot block (000000-0007FFh)の書込み保護しない
    #pragma config WRTC     = OFF	//Configuration registers (300000-3000FFh) の書込み保護しない
    #pragma config WRTD     = OFF	//Data EEPROM の書込み保護しない
    #pragma config EBTR0    = OFF	//Block 0 (000800-001FFFh) を他のブロック実行時のテーブル読み取りから保護しない
    #pragma config EBTR1    = OFF
    #pragma config EBTR2    = OFF
    #pragma config EBTR3    = OFF
    #pragma config EBTRB    = OFF	//Boot block (000000-0007FFh)を他のブロック実行時のテーブル読み取りから保護しない
    
    
    #define Control_W 0xA0 //書込み制御コード
    #define Control_R 0xA1 //読込制御コード
    
    
    #define _XTAL_FREQ  48000000      //__delay_ms
    
    // メイン関数
    void main (void)
    {
    	// 入出力設定
    	ADCON1  =	0b00001111;	//全チャンネルがデジタルに設定され、VDDとVSSが選択
    	TRISA   =	0b00000000;
        	TRISB   =	0b00000011; //B1=SCL(INPUT),BO=SDA(OUTPUT)I2C通信
        	TRISC   =	0b00110000;	//D-,D+(USB用)RC4とRC5を入力に設定
        	TRISD   =	0b00000000;
        	TRISE   =   0b00000011;         //SW1,2=INPUT LED=OUTPUT
        	LATA    =	0b00000000;
        	LATB    =	0b00000000;
        	LATC    =	0b00000000;
        	LATD    =	0b00000000;
        	LATE    =	0b00000000;
            
            SSPCON1 = 0x28;		// SSP enable & I2C Master mode, clock = FOSC / (4 * (SSPADD+1))
    	SSPADD = 0x0F;		// 0x00だと動作しないクロック設定
    
    	unsigned char c;
            unsigned char addr1=0x00;
            unsigned char addr2=0x00;
            unsigned char send_data=0xAA;
    
    	
            //1バイト書込み
            PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    	SSPCON2bits.SEN = 1;//I2C_startビット
    	while (SSPCON2bits.SEN) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
            while(SSPSTATbits.BF){};//SSPBUFの干渉確認
    	SSPBUF =Control_W;//0xA0 //書込み制御コード
            if (SSPCON2bits.ACKSTAT) {PORTD=0b11111110;}//ACKチェック
    	while (!PIR1bits.SSPIF) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
            while(SSPSTATbits.BF){};//SSPBUFの干渉確認
    	SSPBUF = addr1; // 書き込みアドレス1
            if (SSPCON2bits.ACKSTAT) {PORTD=0b11111101;}//ACKチェック
    	while (!PIR1bits.SSPIF) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
            while(SSPSTATbits.BF){};//SSPBUFの干渉確認
    	SSPBUF = addr2;// 書き込みアドレス2
            if (SSPCON2bits.ACKSTAT) {PORTD=0b11111100;}//ACKチェック
    	while (!PIR1bits.SSPIF) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
            while(SSPSTATbits.BF){};//SSPBUFの干渉確認
    	SSPBUF =send_data;// send_data書き込み
            if (SSPCON2bits.ACKSTAT) {PORTD=0b11111011;}//ACKチェック
    	while (!PIR1bits.SSPIF) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    	SSPCON2bits.PEN = 1;//I2C_通信終了
    	while (SSPCON2bits.PEN) {}//終了待ち
           __delay_ms( 5 ); //10mS
    
    	//1バイト読込
            PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    	SSPCON2bits.SEN = 1;//I2C_startビット
    	while (SSPCON2bits.SEN) {}
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
            while(SSPSTATbits.BF){};//SSPBUFの干渉確認
    	SSPBUF =Control_W;//0xA0//書込み制御コード
            if (SSPCON2bits.ACKSTAT) {PORTD=0b11111010;}//ACKチェック
    	while (!PIR1bits.SSPIF) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
            while(SSPSTATbits.BF){};//SSPBUFの干渉確認
    	SSPBUF = addr1;// 書き込みアドレス1
            if (SSPCON2bits.ACKSTAT) {PORTD=0b11111001;}//ACKチェック
    	while (!PIR1bits.SSPIF) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
            while(SSPSTATbits.BF){};//SSPBUFの干渉確認
    	SSPBUF = addr2; // 書き込みアドレス2
            if (SSPCON2bits.ACKSTAT) {PORTD=0b11111000;}//ACKチェック
    	while (!PIR1bits.SSPIF) {}//終了待ち
    
    	SSPCON2bits.SEN = 1;//I2C_startビット
    	while (SSPCON2bits.SEN) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
            while(SSPSTATbits.BF){};//SSPBUFの干渉確認
    	SSPBUF =  Control_R; //0xA1 //読込制御コード
            if (SSPCON2bits.ACKSTAT) {PORTD=0b11110111;}//ACKチェック
    	while (!PIR1bits.SSPIF) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    	SSPCON2bits.RCEN = 1;//受信モードを動作
    	while (SSPCON2bits.RCEN) {}//終了待ち
    
    	c=SSPBUF;//受信コピー
            PORTD=~c;//LED表示
    
            PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
            SSPCON2bits.ACKDT = 1;//受信の終わりで応答シーケンスを開始1=NO-ACK
            SSPCON2bits.ACKEN = 1;//、ACKDT データビットを送信する。
    	while (SSPCON2bits.ACKEN) {}//終了待ち
    
    	PIR1bits.SSPIF = 0;//I2C_通信割込みフラグクリア
    	SSPCON2bits.PEN = 1;//I2C_通信終了
    	while (SSPCON2bits.PEN) {}//終了待ち
    	while(1) {}
    }
    
     I2CによるEEPROM送信・受信ソースプログラムの内容は以下を開いてコピーします。
    「I2CによるEEPROM送信・受信ソースプログラムの内容」にいく。


  6. 動作確認
     動作確認の状況を以下に示します。

    (1)実行すると、0xAAの値をEEPROMの0x0000番地に書込みます。
    (2)次に0x0000番地から値を読み出します。
    (3)読み出した結果をLEDに2進数表示で表示します。


  7. 検討まとめ
    (1)I2C仕様EEPROM評価回路の検討は大変苦労しました。
    (2)トラブルの原因はSDAとSCLの+5Vプルアップをわすれたためです。
    (3)ソフト的に何をやっても正常な応答が得られません。
    (4)SDAとSCLの信号波形を確認できれば良いのですが、高周波の測定が可能なオシロスコープはもっていません。
    (5)トラブル解析のため、ソフトは可能な限りシンプルで原始的な構成にしました。
    (6)いろいろやった後、もう一度冷静にハードの接続を確認して、SDAとSCLの+5Vプルアップをわすれに気づきました。
    (7)シンプルで原始的な構成のソフトは比較的理解しやすい特徴があります。
    (8)+5Vプルアップ後はすんなり動作しました。











16章:LPS331使用 高精度大気圧センサーモジュールに行く。

トップページに戻る。