技術コラム(第18回)I2Cについて

はじめに  

 私たちは色々なセンサデバイスを用いて組み込み装置を開発しています。以下で紹介するI2Cはこれらセンシング技術と切っても切れない関係であり、熟知していなければ開発を行えません。今回の組込開発.comの技術コラムではI2Cの技術について触れていきたいと思います。  

I2C(Inter-Integrated Circuit)とは 

 I2Cとは、オランダのフィリップ社が提唱する2線式の同期式シリアル通信インタフェースの事です。2線式なので、SDA (シリアルデータ) 信号とSCL(シリアルクロック)信号を使い、マスタとスレーブと明確に役割を分けて通信します。SCL信号はマスタが生成し、マスタが通信を制御します。そのSCL信号に同期してSDA信号でマスタとスレーブが双方向に通信し合います。 

 一般的に図のように一つのマスタに複数のスレーブが付きます。スレーブには固有のアドレスが割り付けてあり、マスタがそのアドレスを指定して特定のスレーブと通信します。スレーブ側でジェネラル・コール・アドレスという機能がサポートされていれば、マスタがブロードキャスト方式で一斉にデータ送信をする事も可能です。 

I2Cの接続図

通信速度は以下のように三つのモードがあります。

モード 通信速度(最大) 
標準モード 100 kbps
ファーストモード 400 kbps 
ハイスピードモード 3.4 Mbps 

以降でI2C通信について説明していきたいと思います。

I2C通信の動作 

 一般的な7ビットモード通信動作の手順の場合、以下のようになります。 

  1. マスタがスタートコンディションを発行し、コントロールバイト(操作したいスレーブアドレスが入っているバイト + R/Wビット)を全てのスレーブへ送信する。
  2. スレーブはそのアドレスが自分のものと一致するかどうか調べる。
    • アドレスが自分宛でない場合、スレーブは待機状態になる。
    • アドレスが自分宛の場合、コントロールバイトに含まれるR/Wビットの値に応じてデータをマスタから受信するか、マスタへ送信する。
  3. マスタがRビット(スレーブがマスタへ送信)ならば、スレーブが受信応答(ACK)を返したあとに続けてマスタへデータを送信する。マスタはデータ受信後、受信応答(NAK)を返す。 
  4. マスタがWビット(スレーブがマスタから受信)ならば、スレーブが受信応答(ACK)を返したあと、マスタがデータを送信する。スレーブはデータ受信後、受信応答(NAKを返すか、ACKを返すかはスレーブの仕様による)を返す。
  5. マスタがストップコンディションを発行し、スレーブに通信終了を通知する。通知を受信したスレーブは待機状態になる。 

スタート/ストップコンディション 

 マスタは通信を始める際にスレーブに対し、通信開始を示すスタートコンディションを発行します。これはSCL信号が”H”レベル時にSDA信号を”H”→”L”とレベルを変化させる事で成立します。 

 通信終了には、ストップコンディションを発行します。これはSCL信号が”H”レベル時にスタートコンディションの時とは逆にSDA信号を”L”→”H”とレベル変化させる事で成立します。 

 スタート~ストップコンディションの間にはコントールバイトを含めたデータ送受信が行われますが、この時はSCL信号が”L”レベル時にSDAのレベルを変化させるので、データ送受信とスタート/ストップコンディションは区別ができます。 

 なお、スタートコンディション発行し、データ送受信後に、さらにスタートコンディションを発行する事ができます。これをリピート(もしくはコンティニアス)スタートコンディションを言います。これを使う事で、バスを解放せず、連続でスレーブとの通信を行う事ができます。また、以降で説明する10ビットモード通信動作でもこのリピートスタートコンディションが使用されます。 

スレーブアドレスについて 

 マスタとスレーブはSDA信号から送信するデータで通信を行います。このデータ単位は8ビット単位で、MSB(最上位ビット)から送信します。 

 通信し合うデータの長さが8ビット単位であれば、コントロールバイトに含まれるスレーブアドレスの最大の長さは7ビットになります(残り1ビットはR/Wビット)。スレーブアドレスの指定方法にはこのような7ビットの他、10ビットモードがあります。データ単位は8ビットなので、10ビットモードの場合は二回に分けてコントロールバイトとアドレスを送信します。 

 10ビットモードでマスタが送信(スレーブがマスタから受信)する場合、第一アドレスが含まれるコントロールバイトは上位5ビットが11110の固定値で、その後にスレーブアドレスの上位2ビットのA9、A8、最下位ビットはWビットというような構成となっています。ここまでが二回分けた一回目の送信です。二回目は第二アドレス(最上位A7~最下位A0)のみの8ビットの送信になります。このあと、マスタがデータを送信し、スレーブが受信します。 

 10ビットモードでマスタが受信(スレーブがマスタへ送信)する場合、マスタが第一アドレス、第二アドレスを送信した後、リピートスタートコンディションを発行し、もう一度第一アドレスを送信します。このときの第一アドレスは、マスタが受信となっているので最下位ビットはRビットになります。以降でスレーブがデータを送信し、マスタが受信します。 

ACKとNOACK(NAK) 

 SDA信号から送受信するデータ単位は8ビットですが、9ビット目にACKビットがあります。これは通信の成否の他、何らかの意味を持たせる場合もあります。ACKビットはマスタ/スレーブに関わらず、必ず受信した方が出力します。 

 このACKビットは、”L”レベルの時はACKとなり、”H”レベルの時はNOACK(NAK)になります。このNAKによりデータ転送の終了を判断します。なお、スレーブによっては最終データをマスタから受信した時でもNAKを返さない場合もあります。例えば、可変長のデータをマスタがスレーブへ書き込む場合はスレーブは最終バイトかどうか知る術がありません。そのため、NAKを返す事ができないのです。もし、マスタがスレーブからのNAKを期待している場合、マスタかスレーブのどちらかのプログラムを改修する必要が出てきます。 

I2C通信フォーマット 

 今までの内容を図でまとめると以下のようになります。信号については以下のようになります。フォーマットは上下でマスタ/スレーブが分かれて記載されています。 

スタートコンディション 
Sr リピートスタートコンディション 
ストップコンディション 
ACK 受信応答 
NAK(NOACK) 受信応答(ラストデータ受信応答) 

7ビット マスタWrite 

7bitモード マスタWrite

7ビット マスタRead

7bitモード マスタRead

10ビット マスタWrite

10bitモード マスタWrite

10ビット マスタRead

10bitモード マスタRead

マルチマスタモード 

 I2Cでは同一のI2Cバス上に複数のマスタを置くことができるマルチマスタモードをサポートしているデバイスがあります。マスタはSCL信号からクロックを供給したり、自らの都合でSDA信号からデータを入出力させりするため、複数のマスタが同時に動作すると、お互いのSCL信号やSDA信号の衝突が発生します。この状態をバスコリジョンと言います。マルチマスタモードをサポートするデバイスにはバスコリジョン検出機能があり、衝突が起こると割込みが発生するような仕組みがあります。 

 実際にはマスタAが通信している最中にマスタBが通信しようとした場合、マスタBが通信失敗するようになっています。このような状態を調停(アービトレーション)負けと言い、マスタBはバスが解放されるのを待ってから通信をやり直さなければいけません。 

 ここで、マスタAがスレーブに対して連続で通信したい場合もあると思います。ストップコンディションを発行してしまうと、マスタBに通信を割り込まれる可能性があります。このような場合は前述したリピートスタートコンディションを発行すれば、マスタAがバスを使用し続けられるため、割り込まれる心配がなくなります。 

 なお、マルチマスタモードを利用してもマスタ同士ではアドレスを持たないため通信はできません。RAM等を共有メモリとして使えば、工夫次第でマスタ同士の通信も可能になります。 

 マルチマスタモードの用途としてはRAMやROM、A-Dコンバータなどのスレーブデバイスを複数のマスタで共有する場合などがあります。

終わりに 

 センサ類を多数扱った開発には、I2Cはつきものです。組込開発.comでも、I2C接続したセンサーを用いた事例がこちらに有ります。また、その他の開発実績は組込開発.comの以下リンクにあります。ぜひご覧ください。 

投稿者プロフィール

PicoPo
PicoPo
組込み開発歴もうすぐ10年?な者。ですがまだまだひよっこな開発者。電子基板を片手に色々とやるぞ!と意気込みだけは十分…でしょうか。Raspberry系のものを触ったり、飽きればまた別のも触ります。この頃自分が飽きっぽい性格な事に気づきました。そんな自分ですが、VR系も好きでUnityとかも趣味で触り勉強中。3Dは難しい。