I2Cの実験(6/6)

1/6 )( 2/6 )( 3/6 )( 4/6 )( 5/6 )  〔マイコンのトップに戻る〕


《PCA9547D-I2Cマルチプレクサー(I2Cバス切換器)》

PCA9547は複数(8チャンネル)のI2Cバスを切り換えてくれる秀逸な一品です。
v(o^_゚o)ってゆうかぁ、一夫多妻ぃ。  (iΘvΘi) 例えが変であります、モアどのぉ。

なので、I2Cアドレスがダブった時等に重宝します。
しかも5Vのトレラント入力であり、2.7V〜5.5Vまでの電圧レベル変換もこなしてくれます。

PCA9547Dは秋月電子のこちらで購入していますが、パッケージが"SOP"(1.27mmピッチ)なので、
2.54mmピッチに変換するこちらの基板と、ピンヘッダが必要です。
1.27mmピッチの半田付け今まで躊躇していたのですがぁ、いやぁ、気合を入れて実際やってみるとぉ
意外とまだなんとかなる物ですね。(但しぃ、アルコールを抜いてからやらないとですがぁね)
(;¬_¬) いや、アルコール入れないと震え止まらないんじゃぁ....  (._.)....

製品の概略ブロック図
これは、製品の概略ブロック図です、データシートのをちょい加工しています。

電源投入時のデフォルトチャンネルは[SD0][SC0]の0チャンネルです。
I2Cの通信速度はMAX400KHzまでです。

PCA9547の操作電源(VDD)は2.3V〜5.5Vですが、使用する電圧に応じて出力される電圧レベルが
変わる事に注意しましょう。 例えば3.3Vなら"1.9V"で、5Vなら"3.6V"が出力されます。
だからぁ5Vにした場合にスレーブデバイスが3.3V電源の場合"3.6V"でもOKか調べてみる必要が
有りそう、まあ、たぶん、PCA9547を3.3Vで操作したら良さげな気がしますね....。

ピンの構成図 左は、PCA9547Dのピン配列構成図です。

[REST]ピンはLOWでリセットが掛かるので通常はHIGH(VDD)に
接続します。

[SD0-7]ピンは"SDA"で、[SC0-7]ピンは"SCL"となります。

[A0][A1][A2]ピンはデバイスのI2Cアドレスを選択する為の物です。

[1][1][1][0][A2][A1][A0]の7ビット構成なので、0x700x77から
選択可能です。

上のブロック図では[A0][A1][A2]ピンは全てGND(LOW)接続なのでアドレスは0x70となります。

I2Cの通信フォーマットについて

PCA9547へのチャンネル切り換え指示フォーマットは下記の2バイトを送る事で可能となります。
尚、現在のチャンネル情報が読めるフォーマットも有るのですが説明を省きます、
必要な人はデータシートを見ましょう。

  (スレーブアドレス)    (コントロールレジスタ)
1 1 1 0 A2 A1 A0 RW   x x x x B3 B2 B1 B0
[RW]ビットは書き込みなので0を指定。
[B0][B1][B2]のビットでチャンネル0〜7を指定。
[B3]ビットはチャンネル切り替えの有効無効指示。(切り換える場合は有効で1を指示)

I2Cバスは8チャンネル接続可能だが、そこにぶら下げるスレーブのアドレスとPCA9547のアドレスは
  ダブらない様に注意しましょう。


PIC側プログラムについて

PCA9547に切り替え指示を出すプログラムは簡単なのですが、下記に関数を付けときます、
キリバリしてお使い下さい、但し、"skI2Clib"のライブラリが必要です。
"skI2Clib"のライブラリについてはこちらを参照下さい。
/*******************************************************************************
*  ans = ChgI2CMultiplexer(adrs,ch)                                            *
*  I2Cマルチプレクサー(PCA9547)のチャンネルを切り換える処理                    *
*  この関数は"マルチマスター"に対応しています。                                *
*  この関数を使う場合は、"skI2Clib"のライブラリが必要です。                    *
*    adrs  : PCA9547のデバイスアドレスを指定する(0x70-0x77)                    *
*    ch    : 切り換えるI2Cバスのチャンネルを指定する(0ch-7ch)                  *
*    ans   :  0= 正常                                                          *
*             1= 異常(相手からACKが返ってこない)                               *
*            -1= バスの衝突が発生して10回リトライしたがダメだった              *
*******************************************************************************/
int ChgI2CMultiplexer(unsigned char adrs,unsigned char ch)
{
     unsigned char c ;
     int  ans , i ;

     for (i=0 ; i < 10 ; i++) {
          ans = I2C_Start(adrs,RW_0);   // スタートコンディションを発行する
          if (ans == 0) {
               c = ch & 0x07 ;          // チャネル(bit0-2)を取り出す
               c = c | 0x08 ;           // enableビットを設定する
               ans = I2C_Send(c) ;      // Control register の送信
               I2C_Stop() ;             // ストップコンディションを発行する
          }
          if (ans != -1) break ;        // バスの衝突が発生していなければ終了
          __delay_ms(100) ;             // 100ms後に再トライ
     }
     return ans ;
}

例) A0/A1/A2が全てGND配線ならデバイスアドレスは”0x70”とし、7チャンネルに切り替える場合
 #include "skI2Clib.h"
 
 void interrupt InterFunction( void ) {
      InterI2C() ;
 }
 main() {
      // I2C通信のマスターモードで初期化を行う、通信速度は400KHz
      InitI2C_Master(1) ;
      // I2Cマルチプレクサー(PCA9547)を7チャンネルに切り換える
      ChgI2CMultiplexer(0x70,7) ;
 
 
 }
Arduino側プログラムについて

こちらは、Arduinoのスケッチとなります、I2C関数はArduino標準のWireライブラリを利用しています。
/*******************************************************************************
*  ans = ChgI2CMultiplexer(adrs,ch)                                            *
*  I2Cマルチプレクサー(PCA9547)のチャンネルを切り換える処理                    *
*  この関数は、Arduino標準のWireライブラリを使っています。                     *
*    adrs  : PCA9547のデバイスアドレスを指定する(0x70-0x77)                    *
*    ch    : 切り換えるI2Cバスのチャンネルを指定する(0ch-7ch)                  *
*    ans   : 0=正常終了、それ以外はI2C通信エラーです                           *
*            1=送ろうとしたデータが送信バッファのサイズを超えた(32バイトMAX)   *
*            2=スレーブ・アドレスを送信し、NACKを受信した                      *
*            3=データ・バイトを送信し、NACKを受信した                          *
*            4=その他のエラー                                                  *
*******************************************************************************/
int ChgI2CMultiplexer(unsigned char adrs,unsigned char ch)
{
     unsigned char c ;
     int  ans ;

     Wire.beginTransmission(adrs) ;     // 通信の開始
     c = ch & 0x07 ;                    // チャネル(bit0-2)を取り出す
     c = c | 0x08 ;                     // enableビットを設定する
     Wire.write(c) ;                    // Control register の送信
     ans = Wire.endTransmission() ;     // データの送信と通信の終了
     return ans ;
}

例) A0/A1/A2が全てVDD配線ならデバイスアドレスは”0x77”とし、1チャンネルに切り替える場合
 #include <Wire.h>
 
 void setup() {
      // I2Cの初期化マスターとする
      Wire.begin() ;
      // I2Cマルチプレクサー(PCA9547)を1チャンネルに切り換える
      ChgI2CMultiplexer(0x77,1) ;
 
 
 }
 void loop() {
 
 
 }

実験の風景

実験時の写真

PCA9547Dはチャンネル1をI2C接続LCDに繋ぎ、PIC16F1829から制御しています。
I2C用プルアップ抵抗は、LCD側は10KΩでプルアップし、PIC側はPIC内蔵プルアップを使っています。


[前ページ"ArduinoでソフトI2C通信"へ]





【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.