I2C 概要
I2C(Inter-Integrated Circuit)通信は主にIC間のシリアルデータ通信を実現するためのプロトコルで、フィリップス社(現Nxp)によって開発されました。I2Cという書き方で、アイスクエアドシーが正式名称ですが、単にアイツーシーと呼ぶことが多いです。SPIよりも複雑なプロトコルで、エラーハンドリングやハンドシェークなどの機能が搭載されています。
I2Cでは、マルチマスター機能が標準搭載されているのが特徴です。SPIの場合、マルチマスター機能の正式なサポートはなく、設計者依存でマスターの調停処理はソフトウェアで実現する必要がありました。I2Cでは、この調停(アービテーション)をハードウェアが自動的に実現します。
また、SPIはMOSI, MISO, SS, SCLKの4つのピンを使用して通信します。一方で、I2Cは2本のピンで通信可能なことが特徴です。したがって、ピンの節約が可能になります。
I2C の位置づけとSPIとの違い
プロトコル | 通信方式 | 最大ライン長 | 最大速度 |
USB 3.0 | 全二重通信 | 3m | 5 Gbps |
USB 2.0 | 半二重通信 | 5m | 480 Mbps |
Ethernet | 全二重通信 | 100m | 10 Gpbs |
I2C | 半二重通信 | 6m | 3.4 Mbps |
RS-232 | 全二重通信 | 15m | 20 kbps |
RS-485 | 半二重通信 | 1200m | 10 Mbps |
SPI | 全二重通信 | 1 | 1~20Mbps (CLK/2マイコン依存) |
I2Cでは、マスターはスレーブアドレスに基づいていスレーブと通信します。I2Cで通信するデバイスには、それぞれアドレスが割り当てられ、それをもとにマスターは通信します。そのため、I2Cはアドレスベースのプロトコルです。
一方で、SPIではアドレスを指定するような機能はありませんでした。SPIでは、スレーブを選択するためのSSピンが専用で使用され、そのピンがLowになっているかどうかでスレーブを判定していました。
I2Cは半二重通信で、SPIは全二重通信(半二重通信も可能)になります。したがって、I2Cでは、送信中に受信、受信中に送信はできないことになります。
I2CとSPIでは、伝送速度が一般的にSPIよりも遅いです。SPIはシリアルクロックの半分まで伝送速度が可能なため、40MHzのクロックを持つマイコンでは、20Mbpsの伝送速度が実現できます。
一方で、I2Cは3.4Mが最大速度であるため、SPIよりも遅いことになります。また、後述しますがこの3.4MはHigh Speed Modeというハイエンドの高性能マイコンにのみ搭載されていることが多い機能になります。したがって、どのマイコンでも3.4Mとなるわけではありません。
I2Cの大きな特徴であるClock Stretchがあります。I2Cにおいて、スレーブはクロックがビジーの場合はクロックをホールドしマスターを待機させることができます。
I2C では、クロック ストレッチングのおかげで、ビジー状態の場合、スレーブはクロックを押し続けることでマスターを待機させることができます。
しかし、SPI では、スレーブはクロックを制御できないため、プログラマは独自のトリックを使用してこの状況を克服できます。
SPIでは、スレーブが生成されたシリアルクロックを制御することはできませんが、I2CではClock Sterethingという機能があります。この機能は多くのマイコンで提供されています。これは、スレーブによってクロックをグランドに引き下げることによって起こります。この機能については後述します。
I2C バス
I2Cのバス構成を以下の図に示します。I2Cを利用する場合には、各マスター、各スレーブに以下の2本のピンが必要です。使用するピンが少ないのはI2Cの一つの特徴です。
- SCL:シリアルクロック(同期するためのクロック信号)
- SDA:シリアルデータ(送受信するデータ信号)
データ線が一つしかないため半二重通信となります。
SCL, SDAはVccにプルアップされています。I2Cを利用する場合は、必ず各ピンをプルアップする必要があります。後述しますが、プルアップはI2Cプロトコルではアイドル状態を定義するために非常に重要な手順です。
I2Cの用語
用語 | 意味 |
Transmitter | バス上にデータを送信しているデバイス |
Receiver | バス上のデータを受信しているデバイス |
Master | 転送を開始し、クロック信号を生成し、転送を終了するデバイス |
Slave | マスタによってアドレスで管理されるデバイス |
Multi-master | マスタはメッセージを破損することなく同時にバスの制御を試みること可能 |
Arbitration | 複数のマスターが同時にバスを制御しようとした場合に、1 つのマスターだけが制御を許可され、勝利メッセージが破損しないことを保証するための手順 |
Synchronization | 2つ以上のデバイスのクロック信号を同期するための手順 |
I2Cモード
モード | 伝送速度 | 特徴 |
Standard Mode | 最大100kbps | 多くのマイコンでサポート |
Fast Mode | 最大400kbps | 多くのマイコンでサポート |
Fast Mode + | 最大1Mbps | 中程度の性能のマイコンでサポート |
High Speed Mode | 最大3.4Mbps | 高性能向けマイコンでサポート |
Standard Modeと Fast Mode以上では、互換性がないため通信ができません。例えば、スレーブデバイスがStandard Modeのみサポートしている場合、マスタがFast Modeで通信する場合は、通信ができません。上方互換はありません。
Fast Modeは、下位互換があり0~100KbpsのStandard Modeのデバイスと通信することはできます。
I2C プロトコルの設定
SDAとSCLは以下の2つに共通する設定項目があります。
- SDA, SCLピンはプルアップする
- SCLとSDAは双方向のバスで接続されていて、正の電源電圧にプルアップ抵抗を用いて固定されている必要があります。これは両方のピンがHighの場合に、バスがアイドル状態(なにもデータが流れていない状態)を表すからです。
- SDA, SCLピンはオープンドレインあるいはオープンコレクタ構成
ピン設定とは異なりますが、バス容量により、接続可能なインタフェースの数が決定します。
I2C ピン設定
I2Cで利用するSDA, SCLピンはどちらともオープンドレイン構成あるいはオープンコレクタ構成である必要があります。これは仕様で決定されています。したがって、必ずプルアップ抵抗を挿入する必要があります。内部のプルアップ抵抗を利用するか、外部のプルアップ抵抗を用意するかは場合によります。I2Cバスが正しく機能するためには、プルアップ抵抗の抵抗値が式に従って計算する必要があります。
I2Cではバスがアイドル状態の場合、SDA, SCL両方のピンがHighになります。したがって、トラブルシューティングとして、まずはGNDとSCL間, GNDとSDA間の電圧を測定してみましょう。
I2C プロトコル
基本
I2Cにおいて、データ転送は常にSDAライン上で行われ、マスタ側で開始されます。I2Cでは以下の図のようなシーケンスで通信が実行されます。下の図は1bitごとにSDAライン上にデータが流れる様子を図示しています。このデータはSCLのクロック信号によって同期しています。
- マスターが通信の開始の合図であるStartコンディションを生成します。
- Startコンディションの後は、スレーブデバイスを特定するアドレスを送信します。
最初の7bitがデバイスアドレスを指し、最後の1bitが読み書きのどちらの操作であるかを確定します。
R/W = 0の場合、マスターがスレーブに書き込み(マスターが送信)
R/W = 1の場合、マスターがスレーブから読み取り(マスターが受信) - アドレスはすべてのデバイスに送信(ブロードキャスト)されるため、アドレスが自身のものと一致しているかを確認します。自身のデバイスアドレスと一致していれば、スレーブがACKをマスターに送信し、マスターがACKを受信します。
- R/Wに応じた操作を実行する。
- R/W = 0:1バイトのデータをマスターがスレーブに送信する(Write)
- R/W = 1:1バイトのデータをスレーブがマスターに送信する(Read)
- 実際の送受信処理が行われます。データはMSBファーストで送信されます。
- R/W = 0:スレーブが1バイトのデータを受信して、ACKをマスターに送信する。
- R/W = 1:スレーブからマスターにデータを送信し、ACKをマスターがスレーブに送信します。
- さらに多くのバイトを送信する場合は、4, 5を繰り返す。
- マスタが通信が修了することの合図として、Stopコンディションを生成します。
StartコンディションとStopコンディションはI2Cバスをあるマスターが占有することを意味して、Stopコンディションは占有しているI2Cバスを開放することを意味しています。バスが開放状態(アイドル状態)の場合、SDA, SCLはHighになっています。バスが開放されると、他のマスタが利用可能になります。
Start, Stop コンディション
I2Cは全ての通信が, Startコンディションで開始され、Stopコンディションで終了します。では、これらはどのように判断されているのかについて見ていきます。
Startコンディションは、SCLがHighの状態で、SDAがHighからLowに遷移することで定義します。
Stopコンディションは、SCLがHighの状態で、SDAがLowからHighに遷移することで定義します。
実際の波形を図示して見ていきます。マスターはこのStartコンディションとStopコンディションを生成するために、SCLとSDAを制御します。Stopコンディションにより、マスターがバスの占有を開放したときには、SCL, SDAどちらもHighになっていることがわかります。
多くのマイコンで搭載されているI2Cペリフェラルは、マスターモード、スレーブモードのどちらもサポートしています。このペリフェラルがStartコンディションを生成すると自動的にマスターモードに設定されます。そして、Stopコンディションを生成すると自動的にスレーブモードに設定されます。したがって、プログラマがモードを指定する必要がありません。
センサなどはセンサデータはマスター側に送信するだけでよいため、スレーブモードのみしかサポートしていないことも多いです。
スレーブアドレス指定
スレーブアドレス指定は8ビットで表されます。以下に図を示します。Startコンディションの後の最初のクロックがSCLで1と書いている部分です。そのクロックに同期して、アドレスが7回送信されます。したがって、7ビットでスレーブアドレスを指定します。そして、8番目のクロックでは、R/W(読み込み/書き込み)のどちらを行うのかを決定します。
SDA=0の場合書き込み、SDA=1の場合、読み込みを表しています。
ACK/NACK
マスターがスレーブアドレスを指定した後、スレーブは自身のアドレス一致しているかどうかを確認し、ACKを返答します。では、このACK/NACKとは実際にはどのようなものかを解説していきます。以下に図を示します。
Startコンディションの後、スレーブのアドレス指定があり、R/Wの指定があり、ここまでは、先ほどのアドレス指定の項目で解説した内容と同じです。Startコンディションが生成されてから9番目のクロックサイクルがACK/NACKを表します。
ACKはPositive Acknowledgementのことを言い、日本語では肯定応答と言われます。NACKはNegative Acknowledgementのことで日本語では、否定応答と言います。実際にはACK/NACKと使われることがほとんどです。
ACK/NACKは、データの送受信が正常に行われたかを確認する仕組みです。受信側はデータの受信後、正常に受信できたことを送信側に伝えます。これがACKです。一方で、正常に行われなかった場合、NACKを返答します。
ACK/NACKは実際には以下のようにI2Cでは定義されています。
ACKが生成されるクロックの間に送信側はバスを開放します。これにより、受信側がSDAをLowにすることが可能になします。この期間中に、SDAがLowにとなればACKとなります。一方で、HighとなっていればNACKになります。
ここでは、9番目のクロックでSDAがHighであればNACK, LowであればACKとなります。これは実際のデータをやり取りするときに生成されるACK/NACKも同様な定義となっています。したがって、9番目のクロックで常にACK/NACKを送信側は受信することになります。
データの遷移区間
SDAライン上のデータは、常にSCLライン上のクロックがHighの期間で安定している必要があります。したがって、この期間ではデータがLowあるいはHighに遷移することなく、常にLow, Highのどちらかに保たれています。クロックがLowの区間のときのみ、データの遷移が可能になっています。
これは、Start, Stopコンディションで、SCLがHighのときのSDAの遷移によって、Start, Stopコンディションを判断しているためです。このStart, Stopと混同してしまうため、I2Cではデータの遷移区間は、クロックがLowとなっている区間のみになります。
Repeated Start
マスターがStopコンディションを生成すると、バスが開放され、他のマスタにもバスを占有すること許可します。Stopコンディションを生成するタイミングで、さらにマスターがStartコンディションを生成することをRepeated Startといいます。この場合は、他のマスタに占有されることなく、現在通信を行っているマスタがさらに占有することができます。
これは、どのような場合に有効な手法かを説明していきます。
まず、I2Cバス上に1つのマスタしか存在しない場合は特に問題にはなりませんが、マスタが複数存在する場合に有効です。
FlashROMがI2Cバスに接続されているとします。マイコンがI2Cバスを経由して、FlashROMのアドレス0x3534に保存されているデータを読み取りたいとします。この場合、以下のような流れで制御されます。
- Startコンディションを生成
- Flash ROMのスレーブアドレスを指定
- 書き込みを設定(読み取りたいアドレスをスレーブに送信するため)
- FlashROMのアドレスを送信
- Stopコンディションを生成
さらに、FlashROMに格納されているデータを受信するために、
- Startコンディションを生成
- Flash ROMのスレーブアドレスを指定
- 読み込みを指定(先ほど指定したアドレスに保存されているデータをスレーブから受信するため)
- Flash ROMに保存されているデータを受信する
- Stopコンディションを生成
このような場合、一旦マスタであるマイコンは読み込みたいアドレスをスレーブに送信した後にStopコンディションを生成するため、他のマスタがバスを占有する機会を与えてしまいます。このようなことは望ましくないため、FlashROMに読み込みたいアドレスを送信した後に、Stopコンディションを生成するのではなく、再度Startコンディションを生成し、バスを開放しないようにします。このようにすれば、マイコンは他のマスタに占有される機会を与えず、すぐさまデータを読み取ることができます。これを追加すると以下の流れになります。
- Startコンディションを生成
- Flash ROMのスレーブアドレスを指定
- 書き込みを設定(読み取りたいアドレスをスレーブに送信するため)
- FlashROMのアドレスを送信
- Startコンディションを生成
- Flash ROMのスレーブアドレスを指定
- 読み込みを指定(先ほど指定したアドレスに保存されているデータをスレーブから受信するため)
- Flash ROMに保存されているデータを受信する
- Stopコンディションを生成
このように、RepeatedStartは書き込みの後にすぐさま読み取り動作を行いたい場合など、一連の動作として一つのまとまりとしたい場合に有効です。
まとめ
本記事では、I2C通信について解説しました。I2CはSDA, SCLの2本のピンで、マルチマスターに対応可能、半二重通信であることが特徴です。I2Cには伝送速度には、モードによって決定することを解説しました。また、実際のI2Cプロトコルの詳細な中身を説明しました。
コメント