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 |