前回までの記事内容をベースにして、I2C通信手順を説明します。
今回の記事の説明内容
I2Cデータ通信手順は、電子部品ごとに異なりますので、この記事では基本的な通信手順を説明します。
基本的な通信手順の例として、ホストが通信相手のデバイスを選択した後、ホストからデバイスに2バイトのデータを送信する内容で説明します。
この実践編で使用するLCDモジュールは、I2C通信で2バイトのデータをホストからデバイスに送信して制御します。
この記事で説明するI2Cの通信手順は、LCDジュールのI2Cデータ通信例になります。
一方で、温度センサーはホストからデバイスにデータを送信した後、デバイスからホストに温度データを返信します。
この温度センサのI2C通信手順は、液晶モジュールのそれに比べると複雑になりますので、まずは簡単な2バイトデータをホストからデバイスに送信する手順を基本形として説明します。
温度センサーの通信手順は温度取得プログラム作成時に説明します。
I2C通信手順の概略
ホストからデバイスに2バイトのデータを送信するには、次の手順で行います。

これから、上のそれぞれの番号ごとに信号の制御方法を説明していきます。
「❶ 通信開始」と「❽ 通信終了」は対になっていますので、一緒に説明します。
❹と❻の「1バイト送信」と❺と❼の「了解信号の返信」は全く同じ内容になりますので、まとめて説明します。
❶ 通信開始・❽ 通信終了の信号制御
最初にSPI通信の通信開始と通信終了方法を復習しておきます。
SPI通信ではチップセレクト信号線がそれぞれのデバイスに用意されていました。
この信号線を制御すれば通信相手にするデバイスを選択すると同時に、通信開始、通信終了を容易に伝えることができました。(クリックすると拡大できます)

I2C通信では、クロック信号線とデータ信号線の2本の信号線でデータの送受信を行いますので、通信相手を選択する物理的な信号線はありません。
そのため、クロック信号とデータ信号のみで「通信開始」と「通信終了」を知らせる必要があります。
一見難しそうですが、I2C通信ではこの課題を次のように解決しています。
最初に、クロック信号とデータ信号を使ってデータを送受信する方法をもう一度よく見てみましょう。

このように、クロックの立ち上がりでデータを読み取り、クロックの立ち下がりで次のデータをセットします。
このタイミングをもう少し詳しく見てみます。
「クロックの立ち上がりでデータを読み取る」と言っても、デバイス側は実際にはクロックが立ち上がったことを確認してからデータ信号線を読み取りますので、「クロックが立ち上がった瞬間にデータを読み取る」ということは難しいです。
そのため、次のようにクロックが立ち上がった後、クロックの立ち下がりまでの期間、データ信号は変更しないようにしています。

つまり、「クロックが1の間はデータ信号は変更しない」というルールがあるわけです。
「通信開始」と「通信終了」を伝えるには、このルールを逆手に取ります。このルールを破ることにより、特殊な状況を作るわけです。
どういうことかというと、クロックが1の間にデータ信号を変化させて特殊な状況を作ってしまおう、アイデアです。

データを送るときは「クロックが1の間はデータ信号は変更しない」わけですから、上の図のような状況はデータ通信ではないわけです。
「通信開始」と「通信終了」の合図はこのように作ります。
次は、「通信開始」と「通信終了」を区別するにはどうすれば良いか、という課題です。
クロックが1の間にデータ変化させる、というのは2通りのパターンがあります。
ひとつは「クロックが1の間にデータを1から0に変化させる」というパターン、もうひとつは「クロックが1の間にデータを0から1に変化させる」というパターンです。
通信開始と通信終了の2つの合図を送りたいので、この2つのパターンをそれぞれ「通信開始」「通信終了」に割り当てます。
具体的には、「クロックが1の間にデータを1から0に変化させる」という特殊な信号パターンを「通信開始」の合図にします。

この通信開始の合図を「スタートコンディション」と呼んでいます。通信開始の条件、というような意味合いです。
また、「クロックが1の間にデータを0から1に変化させる」という特殊な信号パターンを「通信終了」の合図にします。

この通信終了のパターンを「ストップコンディション」と呼んでいます。
I2C通信の「❶ 通信開始」と「❽ 通信終了」は、このスタートコンディションとストップコンディションという制御方法で行います。
❷ デバイスアドレスの送信
ホストがスタートコンディションを生成したあと、通信相手を選択するために、ホストはデバイスアドレスを送信します。
ここで送るデータは8ビットで、上位7ビットがデバイスのアドレス、下位1ビットが読み取りか書き込みかを示す値になっています。
この8ビットはデータ送信と同じ要領で次のタイミングチャートになります。(クリックすると拡大できます)
スタートコンディション生成後、すぐにデバイスアドレスを送信する点に注意してください。

❸ 通信相手となるデバイスからの「了解」返信
I2C通信では、デバイスアドレス送信やデータ送信後、そのデータを受信した側は「了解信号」を返信します。
具体的には、データ受信側はクロック信号に合わせて「了解」のときは「0」、何か問題があって受信できていないときは「1」を返信します。
この「了解信号」のことを「ACK」(アック)と呼んでいます。Acknowlegement(受領通知)の略です。
また、何か問題があって受信できていないときの返信を「NACK」(ナック)と呼んでいます。Negative Acknowlegement(未受領通知)の略です。
このACK/NACK(アック/ナック)はI2C通信に限らず、何かのデータをやりとりするシステムではよく出てくる用語ですので、頭の片隅に置いておいていただければと思います。
ACKを返信するタイミングチャートは次のようになります。(クリックすると拡大できます)

❹ 1バイト送信と❺「了解」の返信
1バイト送信と「了解」の返信は、先ほど説明した「デバイスアドレスの送信」と「了解の返信」と同じパターンになります。
タイミングチャートは次のようになります。(クリックすると拡大できます)
ホストが生成するクロックに合わせて、ホスト側が8ビットのデータを送信、デバイス側はACKを返信します。

以上を組み合わせるとI2C通信の基本的な通信手順になります。
その他の通信手順
今回の記事では、「I2C通信手順の基本」を説明しました。でも「基本」ということは、他の通信手順も気になりますよね。
I2C通信はさまざまなケースに対応できるように、いろいろな仕組みが用意されています。
例えば、ホストからデバイスにデータを送るとき、デバイス側で処理が間に合わなくなってデータを送るのを一時的にやめてもらいたいことがあります。I2C通信では、このようなときのための通信手順も用意されています。
また、複数のホストやデバイスが同じ配線に接続されている場合、データ通信が衝突(データ通信が同時に発生)することがあります。
このようなときに通信を再開する通信手順などもあります。
今回の実践編では、この記事で説明した通信手順のみを実装しますが、製作するものによっては他の通信手順も必要になってくることがあります。
もしご興味があれば調べてみてください。
PICマイコンI2C通信
今までI2C通信手順を説明してきましたが、SPI通信に比べると信号制御が複雑ですよね。
SPI通信のプログラムを作るときは、SPIの通信手順に合わせてピンをデジタル制御していました。
これからI2C通信のプログラムを作っていきますが、ピンのデジタル制御をするプログラムを作るのは大変そうですよね。
というのは、データ信号線(SDA)は送信だけではなく受信も行います。
PICマイコンはピンの入出力設定はTRISレジスタでいつでも変更できますが、データを送受信するたびに入力と出力の切り替えを行うのも大変そうです。
他にもスタートコンディションやストップコンディションの信号を作るのもタイミング制御が難しそうですよね。
PICマイコンでは、I2C通信を簡単に実装できるように、マイコン内部にI2C通信のモジュールが搭載されています。
これから作成するI2C通信のプログラムではそのモジュールを使用します。
実は、PICマイコンにはSPI通信のモジュールも搭載されているのですが、実践編では使用しませんでした。
理由は、モジュールを使うには設定などいろいろ大変なのと、SPI通信は通信手順はわかりやすいため、ピンのデジタル制御でプログラムを作成した方がより理解が深まるためです。
次回から、PICマイコンのI2C通信モジュールを使用したI2C通信プログラムを作成していきます。
更新履歴
日付 | 内容 |
---|---|
2018.6.11 | 新規投稿 |
2025.8.8 | 「マスター」「スレーブ」を「ホスト」「デバイス」に変更 |