この記事ではSiglent製オシロスコープ(SDS804X)と評価ボード(STB3)を用いてシリアル通信(UART、SPI、I2C)を解析する方法を解説します。
I2Cの解析方法
I2Cとは
I2Cは半二重・同期式のシリアル通信です。クロック信号SCLによってマイコンとデバイスが同期制御されます。1対多の通信にも対応していますが、半二重通信でデータ線がSDAしかないため、送信と受信を同時に行うことはできません。
複数デバイスとの接続はSCLとSDAを分岐させることで実現されています。またSPIのようにCSによってデバイスを選択できないため、マスターは各スレーブに対してアドレスを割り当てて、アドレスを指定した上でデータ通信を行います。
データ通信の流れ
I2Cのデータ通信は他の2つと比較してやや複雑です。
出典:NXPセミコンダクター UM10204
- マスターがSCLにクロック信号を供給します
- SDAにスレーブアドレスとリード・ライトを指定するデータを送信します
(アドレスは7ビット長で、8ビット目にリード・ライトを示すビットが続く)
- スレーブ側の準備が完了したらACK信号をマスターに返します
- ACK信号を確認したら、マスターからデータを送信、または受信します
(データ量に制限はありませんが、データ長は1バイトでなければならない)
- 通信を終了する場合はマスターからストップコンディション(P)を生成し、別のデバイスと通信を続ける場合はリピートスタートコンディション(Sr)を生成しアドレスを再指定します.
10ビットアドレス
I2Cではスレーブアドレスを10ビットで指定することも可能です。10ビットアドレスを使用する場合、1バイト目の先頭7ビット(11110XX)のうち末尾の2ビット(XX)が10ビットアドレスの最上位2ビットとなり、2バイト目の8ビットが10ビットアドレスの下位8ビットとなります。
プルアップ抵抗
I2CのSCLとSDAにはプルアップ抵抗を接続する必要があります。このプルアップ抵抗はノイズ対策として用いられるものですが、動作速度や配線パターンの長さによって適切な抵抗値が変化します。目安としては数kΩ程度とすることが一般的です。
測定セットアップ
STB3のSERIAL PROTOCOLボタン(S8)を押下して、I2Cと印字されたLED(HL3)を点灯させます。ここではSCLとSDAの2つの信号を測定します。
チャネル1はI2C SCLと印字されたピンヘッダー(J24)に接続します。チャネル2はI2C SDAと印字されたピンヘッダー(J23)に接続します。接続が完了したら、チャネル1とチャネル2をアクティブ状態にしてAuto Setupボタンを押します。
このままだと波形が見づらいので、各チャネルのスケールとオフセットを変更します。
ここでは1V/divとし、オフセット電圧はチャネル1が0V、チャネル2が-3.5Vとしています。また横軸は1つのバースト信号が画面内に収まるようにスケールが100us/div、オフセット時間を450usとしています。
I2C信号の仕様
STB3から出力されるI2C信号の仕様は以下のとおりです。
通信速度は100kbpsです。アドレス長は7ビットと10ビットの両方を使用しており、リードとライトの両方の動作を行っています。
I2Cフレーム
I2C信号のフレームは下図の4種類で構成されています。
Sはスタートビット、Pはストップビット、Srはリピートスタートビット、A●はACK信号、A1■はNACK信号を意味しています。データはD1とD12です。
- フレーム①:7ビットアドレスに対してライトモードでアクセス
- フレーム②:10ビットアドレスに対してライトモードでアクセス
- フレーム③:7ビットアドレスに対してリードモードでアクセス
- フレーム④:10ビットアドレスに対してライトモードでアクセスし、続けて7ビットアドレスに対してリードモードでアクセス
トリガーセットアップ
まずはフレーム①に対してトリガーを設定します。TriggerのSetupボタンを押して「Type」を「Edge」から「Serial」に変更します。シリアル通信の種類は「Protocol」から「I2C」を選択します。
次に「Signal」からチャネルと信号の関係性を設定します。ここではSCLがチャネル1、SDAがチャネルとしています。
「Trigger Setting」ではトリガー条件を指定します。「Condition」でI2Cフレームのどのビットでトリガーをかけるかを選択できます。単純に信号を捕捉するだけなら「Start」を選択しておけばよいです。特定のデータやアドレスに対してトリガーをかけたい場合は「7Add&Data」または「10Add&Data」を選択します。ここでは「7Add&Data」を選択し、7ビットアドレス(7’b1001110)のライトモードに対してトリガーをかけます。
アドレスは2進数(Binary)以外にも16進数(Hex)や8進数(Oct)でも指定できます。トリガーの設定を変更すると波形の見え方が変わるため、改めてオフセット時間を調整します。ここでは300usとしています。
デコードセットアップ
デコード機能を有効にするためにフロントパネルの「Decode」ボタンを押し、「Bus Protocol」を「I2C」に変更します。
次に「Protocol Copy」から「Copy From Trigger」を選択します。
すると画面上にデコードされた結果が表示されます。
デコーダーの先頭に示されている「W=0x4E」はライトモードでアドレスが0x4E(0b1001110)であることを意味しています。なおデフォルトでは「Protocol Config」の「Include R/W Bit」がOFFになっていますが、ONに切り替えるとデコーダーの先頭のバイトがライトモード(0)のビットを加味した表示0x9C(0b10011100)になります。
波形の解析
Formatが「ASCII」に設定されている場合、デコーダーに「SIGLENT_****(*はランダムで変化)」という文字が表示されるはずでが、ここでは「NT_****」となっており「S」「I」「G」「L」「E」の文字が足りていません。これはおそらくフレーム①のうちD12の分しかデコードされていないためと考えられます。
1つ前のフレームの解析
時間スケールを広げて、1つ前のフレームを確認してみます。ここでは時間スケールを1ms/div、オフセット時間を2msに設定し、ズーム機能を使って1つ前のフレームの波形を拡大しています。
1つ前のフレームはライトモードで10ビットアドレスの0x2ABにアクセスし、続けてリードモードで同じアドレスにアクセスしています。またここで読み取れるデータも「NT_****」となっており「S」「I」「G」「L」「E」の文字が抜けています。どうやらデータシートで規定された値が出力されていないようです。
4フレーム分の解析
データシートと実際の波形の関係を整理するためにリスト表示してみます。リスト表示は「Result List」から「Bus1」を選択します。また合計4フレーム分のデータを合わせて表示させるために時間スケールを2ms/div、オフセット時間を9msとします。
- フレーム①:0x4E(0b 100 1110)にライトモードでアクセス
- フレーム②:0x2EB(0b 10 1110 1011)にライトモードでアクセス
- フレーム③:0x64(0b 110 0100)にリードモードでアクセス
- フレーム④:0x2AB(0b 10 1010 1011)にライトモードでアクセスしたのちに、0x2AB(0b 10 1010 1011)にリードモードでアクセス
この解析リストとデータシートのフレームを見比べると、動作モードとアドレスは完全に一致していますが、データはすべて「NT_****」となっています。
つまりフレームの順序と動作はデータシートどおりですが、中身のデータにバグが生じているということです。
デコード機能の有効性
I2C信号の解析を通じて、デコード機能がバグの発見に非常に有効であることが理解できたはずです。もしオシロスコープにデコード機能が搭載されていなければ、自らデータを解読してどこにバグが有るのかを探さなければいけません。これは開発スピードが年々早くなっている現代において許容されることではありません。そのため実務のデバッグ作業にオシロスコープを使用するならデコード機能は必須です。
© 2024 T&Mコーポレーション株式会社