USB-101(FT2232H)によるMPSSEを使ったI2C通信例 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FTDIデバイスにはMPSSE(Multi-Protocol Synchronous Serial Engine)というモードが用意されています。 このモードを使用することによりシリアル通信(I2C、SPI、JTAG等)をエミュレートし、通信することが可能です。 UTL-015で使用しているSMBus通信温度センサIC TMP401(TI)とUSB-101を通信させてみました。 USB-102やUSB-103でも同様の実験が可能です。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
◆構成 とても単純です。USB-101とUTL-015を直接接続しています。 UTL-015への3.3VはUSB-101から供給しています。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
◆ピン割付け USB-101とUTL-015は以下のように接続されています。他は未接続です。
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
◆SMBusとI2C SMBus (System Management Bus)はI2Cが発展した規格ですので、I2Cインタフェースとして通信できます。 今回の実験ではI2Cとして通信しています。SMBusとして扱ってはおりませんのでご了承ください。 SMBusの詳細は省略致します。詳しくは参考サイト(こちらなど)をご参照ください。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
◆I2C通信規格 単純なものは、以下のような手順で通信を行います。 「START」 「デバイスアドレス+(W/R#)」 「レジスタアドレス」 「データ」 「STOP」 >>-------------------------------------------------------------->> SDAの遷移は、SCLがLowのときに行われる必要があります。 SDAの遷移が、SCLがHighのときに行われると、「START/STOP」シーケンスとなります。 通信波形の例を下図に示します STARTシーケンスの位置を拡大してみました。SCLがHのときにSDAがLになっているのがわかります。 STOPシーケンスでは逆に、クロックが先にHに上がり、そのあとSDAがHになります。 間に挟まれたデータ8bit毎に、ACKが返ったきたり、ACKを返したりします。 (クリックして拡大) 詳細はTMP401のデータシートや、他参考サイトをご覧になってください。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
◆MPSSEの動かし方 MPSSEモードではコマンドとデータを送信して動作させます。 VCPモードで0x86, 0x01, 0x00をFT_Write()すると、3Byteのデータがポートから出力されますが、 MPSSEモードでは、クロックレート(0x86)を0x0001に変更する、という動作になります。 0x2C, 0x10, 0x00ならばTDOポートから16Byte取得します。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
◆MPSSEをI2Cとして動作させる サンプルプロジェクトよりコードを一部抜粋しました。(ここをクリック) 合わせてご覧ください。 まずはじめにUSB-101をMPSSEモードに切り替えます。 MPSSEへの切り替えはFT_SetBitMode関数で行います。APIのみで移行できますので、EEPROMに特別な設定は必要ありません。 第3引数の0x02でMPSSEモードに切り替わります。第2引数はポートの方向で1:OUTPUT、0:INPUTです。 FT_SetBitMode(ftHandle, (UCHAR)0xFB, (UCHAR)0x02); 動作設定は以下の配列内容で行います。 BYTE outBuffer[] = { 0x85, //Disconnect TDI to TDO LoopBack 0x97, //Turn off Adaptive clocking 0x8C, //Enable 3 Phase Data Clocking 0x86, 0x13, 0x00, //Set TCK Divisor }; 0x86, 0x13, 0x00 にてSCLのレートを設定します。 今回は300kHzを使用します。outBuffer[]はFT_Write()でまとめて送信できます I2Cの波形とするために「3 Phase Data Clocking (0x8C)」の設定が必要です。 このモードにより、3段階のクロックでデータを出力できます。 「I2C通信規格」でもご説明したように、SDAはSCLがHのときに遷移してもらっては困りますので、このモードが必要となります。 下図に参考波形を示します。 下の波形では、SCLがHのときにデータが遷移してしまっています。(赤線部) 上の波形では、データ遷移用に半周期分のSCLが追加されおり、遷移はこの領域で行われていることがわかります。 ということは実際のレートは2/3と言うことになりそうです。(200kHz) (クリックして拡大) クロックエッジに対するデータの出力タイミングは ・MSBから ・立ち下がりエッジで更新 ・バイト単位で出力 という条件から0x11となります。下記は「data」1バイト分の出力コードです。 BYTE outBuffer[] = { 0x11, 0x00, 0x00, data, ・・・ }; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
◆ACKの受け方 8bitのデータ送信毎にACKが返ってきます。(もしくは返します) FT2232H側のDOとDIをショートしていますので、DOを一時的に入力として、LowByteを読み込みます。 BYTE outBuffer[] = { ・・・ //Get Ack SET_DATA_BITS_LOW_BYTE, 0x00, 0x01, //SCLK:out, DO:in, DI:in MSB_RISING_EDGE_CLOCK_BIT_IN, 0x00, //Get 1 Byte 0x87, //Send Immediate SET_DATA_BITS_LOW_BYTE, 0x00, 0x03, //SCLK:out, DO:out, DI:in }; FT_Write(ftHandle, outBuffer, sizeof(outBuffer), &dwByteWritten); FT_Read(ftHandle, &ret, 1, &dwByteRead); retの2bit目が0であれば、ACKが返っているということになります。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
◆実際の通信例 TMP401のManufacture IDを読み出してみました。 (クリックして拡大) @ スタートシーケンス A スレーブアドレス+Write、Ack応答 B ポインタレジスタバイト C スタートシーケンス D スレーブアドレス+Read、Ack送信 E Manufacture ID、Ack送信 F エンドシーケンス 今回は読み出しコマンドですので、まず読み出しアドレスをWriteして、返答データをReadします。 その際スタートシーケンスを再発行する必要があります(4)。 2や5ではスレーブアドレスの後の1bitでWrite/Read#を指定します。 TMP401のスレーブアドレスは0x1001100ですので、Writeの場合0をLSBに付加し0x10011000(0x98)となります。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
◆UTL-015サンプルアプリケーション 今回の実験で作成したサンプルアプリケーションを配布しております。 UTL-015の製品ページよりダウンロードしてご利用ください。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
どうぞ皆さんのご参考になさってください。ただし、コードやアプリのご使用は皆さまの責任で(At Your Own Risk!)お願いいたします。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
メールでのご質問はこちらへどうぞ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FTDIシリーズTOPへ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||