概要
I2C(I squared C)はフィリップス社で開発されたシリアルバス。正式な呼称はInter-Integrated Circuitの略で表記はI2Cと上付きが本来とのこと。
マスターに対して1つ以上のスレーブを繋ぐことができて、接続はクロック線(SCL)とデータ線(SDA)の2本だけで済む。マスターからスレーブを指定して、Read/Write信号によりデータを書き込んだり読み込んだりすることができる。
原理(マスターからスレーブへの書き込み)
ビットデータの転送
データはクロック信号に同期してビット情報を転送。SCLの立ち上がり開始から立ち下がり開始までの間にデータを転送する。データを変更(H ⇔ L)する場合には、SCLがLの間にSDAを変更する。
スタートコンディション/ストップコンディション
データ転送のためSCLがHの間にSDAは変化させないが、この間にSDAが変化した場合は不正・無効ではなく、スタートコンディション/ストップコンディションの意味を持つ。
SDAがH→Lに変化した場合はスタートコンディションで、SCLがH→LになったあとLの間に最初のビットの準備をする。
SDAがL→Hに変化した場合はストップコンディションで、その前にSCLがLの間にSDAをLにしてストップコンディションの準備をする。
バイトデータの転送
データはバイト単位で転送される。
マスターからスレーブへの書き込みの場合、フォーマットは以下の様になる(スレーブアドレスが7ビットの場合)。
- マスターからスタートコンディション、スレーブアドレス7ビット、RW = 0を送信
- 指定されたアドレスのスレーブからACK送信→マスターで受信
- マスターから1バイトのデータを送信
- スレーブがデータ受信後、ACK送信→マスターで受信
- 以降、必要バイト数を送信
- 送信終了後、マスターからストップコンディション送信
マスターがスレーブのデータを読み込む場合には、フォーマットは以下の様になる。
- マスターからスタートコンディション、スレーブアドレス7ビット、RW = 1を送信
- 指定されたアドレスのスレーブからACK送信→マスターで受信
- スレーブから1バイトのデータを送信
- マスターが受信後、ACK送信→スレーブで受信
- 以降、必要バイト数を受信
- 受信終了後、マスターからストップコンディション送信
スレーブアドレス送信とRW
マスターからスレーブに対してスタートコンディションを送信し、各スレーブが受信体勢に入る。その後マスターからスレーブアドレスを送信する。
スレーブアドレスが7ビットの場合、MSBから順に7ビット送り、最後にRWを1ビットで送る。RW=1のときマスター側が読み取り、RW=0のときマスターからスレーブへ書き込み。
ACK
I2Cのデータは8ビット単位で転送され、その後にACK/NACKが返される。マスターからスレーブへの書き込みの場合ACKはスレーブからバスに発信され、マスターがスレーブから読み出す場合はマスターから発信される。
スレーブアドレス指定の際、選択されたスレーブはACK信号を1ビットのLで返す。選択されなかったスレーブはストップコンディションを待機。何らかの理由でスレーブ側がデータを受け取れなかったときはNAK信号を1ビットのHで返す。
マスターからスレーブへデータを書き込む場合、8ビット目の送信後にSCLをLにし、スレーブからACKを受け取ってから次のデータの送信を開始する。
マスターがスレーブからデータを読み込む場合、アドレスは上記と同じだが、データについてはマスターがデータ受信後にACKを送る。
ただしスレーブ側で次のクロックサイクルに合わせてデータを送るのに間に合わない場合、スレーブ側でSCLを強制的にLにして、マスターでのデータ読み込みを抑制する(クロックストレッチ)。スレーブの準備完了後にクロックストレッチは解除され、データの読み込みが再開される。
I2Cの有効化
Raspberry PiでI2Cを有効化する手順。
- コマンドラインで
sudo raspi-config
を実行 - 画面が変わるので、
5 Interfacing Options
を選択 P5 I2Cを選択
I2Cツール
LinuxベースのRaspberry Piで利用可能なツール。
i2cdetect
sudo i2cdetect ...
で実行。Raspberry Piで管理者権限を持っているなら、sudo
なしでもok。
i2cdetect -V
バージョン確認。
1 2 |
$ i2cdetect -V i2cdetect version 4.1 |
i2cdetect -l
利用可能なバスの一覧を表示。
1 2 |
$ i2cdetect -l i2c-1 i2c bcm2835 (i2c@7e804000) I2C adapter |
i2c-1
の'1'
がバス番号になる。
i2cdetect -F [bus]
指定したバスで利用可能な機能の一覧を表示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ i2cdetect -F 1 Functionalities implemented by /dev/i2c-1: I2C yes SMBus Quick Command yes SMBus Send Byte yes SMBus Receive Byte yes SMBus Write Byte yes SMBus Read Byte yes SMBus Write Word yes SMBus Read Word yes SMBus Process Call yes SMBus Block Write yes SMBus Block Read no SMBus Block Process Call no SMBus PEC yes I2C Block Write yes I2C Block Read yes |
i2cdetect -y [bus]
指定したバスのデバイスアドレスを表示する。
1 2 3 4 5 6 7 8 9 10 |
$ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- |
各行の2桁目がアドレスの上位桁、各列がアドレスの下位桁を表していて、ここではデバイスアドレスが1つ(0x27)確認できる。
ライブラリー
Raspberry PiとPythonでI2Cを扱うためのライブラリーsmbus2
について(ドキュメントはこちら)。
sudo pip install smbus2
でインストール。SMBusはSystem Management Busの略でI2Cのプロトコルと概ね同じ。
smbus2
モジュールのSMBus
クラスでバスへアクセスするインスタンスを取得。コンストラクターの引数にはバス番号を指定。バス番号はsudo i2cdetect
で確認されたバス番号。
1 2 3 |
import smbus2 as smbus bus = smbus.SMBus(1) |
以降、read_byte
やwrite_byte
など、このインスタンスのメソッドを使う。