エレファイン

I2Cモード



USB-ISSは、常にバスマスターとして動作します。
I2Cモードでは、I2Cデバイスの内部アドレスへのアクセス、ユーザー独自のI2Cシーケンスを構築するためのコマンドがあります。

I2Cモードコマンド一覧
コマンド 説明
I2C_SGL 0x53
Philips PCF8574 I/Oチップのように内部レジスター(内部アドレス)を持ってないデバイスに1バイトでリード/ライトを行います。
I2C_AD0 0x54
内部アドレスを持ってない、または、内部アドレスを設定する必要がないデバイスに対して、複数バイトのリード/ライトを行います。
I2C_AD1 0x55
1バイトの内部アドレスを指定し、リード/ライトを行います。大半のデバイスはこれを使用します。
I2C_AD2 0x56
2バイトの内部アドレスを指定し、リード/ライトを行います。32kビット(4k×8)以上のEEPROM等で使用します。
I2C_DIRECT 0x57
ユーザー独自のI2Cシーケンスを構築するために使用します。
I2C_TEST 0x58
I2Cバス上にデバイスが存在するかどうかを確認するために使用します。(V5以降のファームウェアのみ対応)

USB-ISSは、スタート・リスタート・ストップシーケンスなどといったI2Cバスの条件に基づき、自動的にアクノリッジ・サイクルを処理します。USB-ISSに何をさせるかのバイト列を送るだけで動作します。

内部アドレスレジスターを持たないI2Cデバイスへの1バイト書き込み
これは、Philips PCF8574 I/Oエキスパンダーのようなデバイスで使用します。
以下のとおり、I2C_SGLコマンドでI2Cのアドレスと書き込むデータを送信します。

USB-ISS主コマンド デバイスアドレス + R/Wビット データ
バイトタイプ I2C_SGL Addr+R/W Data
0x53 0x40 0x00
意味 直接 リード/ライト コマンド PCF8574 I2C アドレス 全てLをセット

この3バイトのシーケンスでPCF8574 I/Oエキスパンダーの全てのビットをLに設定します。
3バイトのデータは、1回でUSB-ISSに送る必要があります。各バイト間に間が空くとUSB-ISSの内部コマンド同期ループが初期化され、無視されてしまいます。
全てのバイトが受信されるとUSB-ISSは、I2Cバス経由でPCF8574へデータを出力し、PCに対し1バイト返信します。この返信バイトは、失敗の場合は0x00、成功したときは、0x00以外です。この返信バイトが受信できるまで待ってから、PCより次のデータを送ってください。0.5秒待っても返信がないときはタイムアウト処理をしてください。

内部アドレスレジスターを持たないI2Cデバイスから1バイト読み出し
これは、アドレスに1加算する以外、書き込みの場合と似ています。
アドレスが0x40のPCF8574から読み出すときは、0x41を指定します。
I2Cアドレスの最下位ビットは、1のとき、読み出しサイクルであることを表します。
下記は、PCF8574 I/Oエキスパンダーからの入力の例です。
I2C_SGL PCF8574 I2C アドレス+ リードビット
0x53 0x41

I2Cバス上のデータ読み取り動作を終えると、PCに1バイト(PCF8574から入力した値)返信します。この返信バイトが受信できるまで待ってから、PCより次のデータ(読み出しコマンド等)を送ってください。0.5秒待っても返信がないときはタイムアウト処理をしてください。

内部アドレスレジスターを持ってないデバイスへ複数のバイトを書き込む
このようなデバイスは、とても少ないですが、USB-ISSはこれにも対応しています。
I2C_AD0 デバイスI2C アドレス 書き込むバイト数 Data 1 Data 2 Data 3 Data 4
0x54 0x30 0x04 0x12 0x34 0x56 0x78

内部アドレスレジスターを設定せずにデバイスから複数のバイトを読み出す
これは、内部アドレスレジスターを持ってないが複数のバイトを返すデバイスで使用します。たとえば、Honeywell ASDX DOシリーズ圧力センサーです。
また、このコマンドは、EEPROMのように自動的にアドレスがインクリメントされ、毎回、アドレスを指定する必要がないデバイスでも使用することができます。この場合は、初めにI2C_AD1またはI2C_AD2を使用してアドレスを指定して読み出した後、I2C_AD0で続きのデータを読み出します。
下記は、Honeywellのセンサーから読み出す例です。
I2C_AD0 ASDX I2Cアドレス + リードビット 読み出すバイト数
0x54 0xF1 0x02

USB-ISSは、I2Cバス上の読み出し動作を行った後、PCにセンサーから送信されたデータを2バイト返信します。この例では、ASDXセンサーより上位バイトから先に送信されます。この返信バイトが受信できるまで待ってから、PCより次のデータ(読み出しコマンド等)を送ってください。0.5秒待っても返信がないときはタイムアウト処理をしてください。

1バイトアドレスの内部レジスターへの書き込み
ほとんどのI2Cデバイスがこれに含まれます。I2C_AD1コマンドの後、書き込みたいデバイスのアドレス、内部レジスターのアドレス、書き込むデータのバイト数、データ(複数可)の順で送信します。1回に受け付けられるデータバイト数は、USB-ISSの内部バッファサイズの60で、それを超えてはいけません。

USB-ISS主コマンド デバイスアドレス デバイス内部レジスター データバイト数 データバイト
バイトタイプ I2C_AD1 Addr+R/W Reg Byte Count Data
0x55 0xE0 0x00 0x01 0x51
意味 USB-ISS主コマンド
SRF08 I2C アド
レス
SRF08 コマンドレジスター 1バイト cmで測定

上記の5バイトのシーケンスでアドレス0xE0のSRF08は、測定を開始します。
5バイトのデータは、1回でUSB-ISSに送る必要があります。各バイト間に間が空くとUSB-ISSの内部コマンド同期ループが初期化され、無視されてしまいます。
全てのバイトが受信されるとUSB-ISSは、I2Cバス経由でSRF08へデータを出力し、PCに対し1バイト返信します。この返信バイトは、失敗の場合は0x00、成功したときは、0x00以外です。この返信バイトが受信できるまで待ってから、PCより次のデータを送ってください。0.5秒待っても返信がないときはタイムアウト処理をしてください。

下記は、別の例です。DCモータードライバーMD22を初期設定するための8バイトシーケンスの例です。

I2C_AD1

MD22アドレス

モード レジスター

データバイト数

MD22モード
1

左モーター
停止

右モーター
停止

加速度

0x55

0xB0

0x00

0x04

0x01

0x00

0x00

0x02


1バイトアドレスの内部レジスターからの読み出し
これは、アドレスに1加算して奇数にする必要があること以外、書き込みの場合と似ています。
アドレスが0xE0のSRF08から読み出すときは、0xE1を指定します。
I2Cアドレスの最下位ビットは、1のとき、読み出しサイクルであることを表します。
読み出すバイト数は、USB-ISSの内部バッファサイズの60を超えてはいけません。
下記は、CMPS03コンパスモジュールから方角データを読み出す例です。
I2C_AD1 CPMS03 I2Cアドレス+リードビット CMPS03方角レジスター 読み出しバイト数
0x55 0xC1 0x02 0x02

USB-ISSは、I2Cバス上の読み出し動作を行った後、PCにセンサーから送信されたデータを2バイト返信します。上位バイトから先に送信されます。この返信バイトが受信できるまで待ってから、PCより次のデータ(読み出しコマンド等)を送ってください。0.5秒待っても返信がないときはタイムアウト処理をしてください。

2バイトアドレスの内部レジスターへの書き込み
これは、主にEEPROMの24LC32(4K×8)から24LC1024(2×64K×8)のためのものです。
I2C_AD1コマンドの後、書き込みたいデバイスのアドレス、内部レジスターのアドレスの上位バイト、アドレスの下位バイト、書き込むデータのバイト数、データ(複数可)の順で送信します。1回に受け付けられるデータバイト数は、最大59バイトです。

USB-ISS
主コマンド
デバイスアドレス 内部アドレス
上位バイト
内部アドレス
下位バイト
データバイト数 データバイト
バイトタイプ I2C_AD2 Addr+R/W アドレス上位 アドレス下位 バイト数 データ
0x56 0xA0 0x00 0x00 0x20 0xnn
意味 主USB-ISS コマンド 24LC32 I2C アドレス アドレス
0x0000
アドレス
0x0000
データが32バイト 32 (0x20) 個のデータバイト

この37バイトシーケンスは、EEPROM内のアドレス0x0000から32バイトのデータを書き込みます。
37バイトのデータは、1回でUSB-ISSに送る必要があります。各バイト間に間が空くとUSB-ISSの内部コマンド同期ループが初期化され、無視されてしまいます。
全てのバイトが受信されるとUSB-ISSは、I2Cバス経由でSRF08へデータを出力し、PCに対し1バイト返信します。この返信バイトは、失敗の場合は0x00、成功したときは、0x00以外です。この返信バイトが受信できるまで待ってから、PCより次のデータを送ってください。0.5秒待っても返信がないときはタイムアウト処理をしてください。

2バイトアドレスの内部レジスターからの読み出し
これは、アドレスに1加算して奇数にする必要があること以外、書き込みの場合と似ています。
アドレスが0xA0のEEPROMから読み出すときは、0xA1を指定します。
I2Cアドレスの最下位ビットは、1のとき、読み出しサイクルであることを表します。
読み出すバイト数は、USB-ISSの内部バッファサイズの64を超えてはいけません。
下記は、デバイスアドレス0xA0の内部アドレス0x0000から64(0x40)バイトのデータを読み出す例です。
I2C_AD2 デバイスI2Cアドレス+リードビット 内部アドレス
上位バイト
内部アドレス
下位バイト
読み出しバイト数
0x56 0xA1 0x00 0x00 0x40

USB-ISSは、I2Cバス上の読み出し動作を行った後、PCにセンサーから送信されたデータを64バイト返信します。この返信バイトが受信できるまで待ってから、PCより次のデータ(読み出しコマンド等)を送ってください。0.5秒待っても返信がないときはタイムアウト処理をしてください。

I2C_DIRECTコマンド
I2C_DIRECTコマンドは、独自のI2Cシーケンスを構築するために使用します。
まず、I2C_DIRECTコマンド(0x57)を送信し、必要に応じて、下記のサブコマンドを送信してください。

I2C Start 0x01 シーケンス開始
I2C Restart 0x02 シーケンス再開
I2C Stop 0x03 シーケンス終了
I2C Nack 0x04 NACK を送った後、読み出し
I2C Read 0x20〜0x2F 読み出し  1〜16バイト
I2C Write 0x30〜0x3F 書き込み 1〜16バイト

下記は、PCF8574 I / Oエキスパンダに0x55を書き込むためのシーケンスです。
I2Cアドレスを含めて2バイトなので2バイトの書き込みである0x31を送ります。
I2C_DIRECT I2C_START I2C_WRITE2 PCF8574 I2C 書込アドレス Data I2C_STOP
0x57 0x01 0x31 0x40 0x55 0x03

下記は、24LC512 EEPROMに4バイトを書き込みます。これは、内部アドレスに2バイト使用します。
I2Cアドレス、内部アドレスを含めて7バイトなので7バイトの書き込みである0x36を送ります。
Direct Start Write7 I2C アドレス アドレス上位 アドレス下位 Data1 Data2 Data3 Data4 Stop
0x57 0x01 0x36 0xA0 0x00 0x00 0x11 0x22 0x33 0x44 0x03

下記は、24LC512 EEPROMから4バイトを読み込みます。
まず、アドレスを書き込み(0xA0のアドレスに対して送信)として送信し、Restartを送った後、読み出しアドレスを送り(書き込み)、読み出しコマンドを送ります。
Direct Start Write3 I2C Address アドレス
上位
アドレス
下位
Restart Write1 I2C address+RD Read3 Nack Read1 Stop
0x57 0x01 0x32 0xA0 0x00 0x00 0x02 0x30 0xA1 0x22 0x04 0x20 0x03

読み出しシーケンスでは、初めに読み出したいアドレスを書き込む必要があることに注意してください。
4バイト読み出すうち、3バイトを読み出した後、NACKを設定し、最後の1バイトを読み出します。このような動作をさせなくて、下記のような方法でも読み出すことは可能ですが、I2Cの仕様では、上記のやり方が正しいです。
Direct Start Write3 I2C Address アドレス上位 アドレス下位 Restart Write1 I2C address+RD Read4 Stop
0x57 0x01 0x32 0xA0 0x00 0x00 0x02 0x30 0xA1 0x23 0x03

I2C_DIRECTコマンドに対する返信は、コマンド、結果によってバイト数が異なりますが、少なくとも2バイトあります。
1バイト目は、成功したか否かを表し、成功・ACK(0xFF)、または、失敗・NACK(0x00)です。
ACKの場合は、2バイト目で返信のデータ数が入り、その後にI2Cデバイスから送られてきた(読み出した)データが続きますので、それらを受信してください。読み出しデータがないときは、0です。
NACKの場合は、2バイト目に下記のエラーコード(エラーの理由)が送られてきます。
エラータイプ エラーコード 説明
デバイスエラー 0x01 デバイスよりACKが来ません
バッファーオーバーフロー 0x02 フレームサイズを60バイト以下に抑えてください
バッファーアンダーフロー 0x03 書き込みデータ数が少なすぎます
不明なコマンド 0x04 おそらくコマンドまたはデータの個数が違っています

I2Cデバイス存在確認(V5以降のファームウェアのみ)

この2バイトのコマンドは、ユーザーからの要望で加えられました。指定したアドレスのI2CデバイスからのACK返信を確認します。
1バイトの返信があり、デバイスが検出されないときは0、検出されたときは0以外が返されます。
I2C_TEST I2Cデバイスのアドレス
0x58 0xA0