第37回 I2C通信の考え方(2)

I2C通信のハードウエア構成と通信手順の概略を説明します。

I2C通信のハードウエア

前回の記事で、I2C通信では1本のクロック信号線と1本のデータ信号線のみの構成で、マスターと複数のスレーブ間でデータ通信を行うことを説明しました。

最初に、例のリビングと勉強部屋間の通信システムで、このような通信を行うためにはどのようなハードウエア構成にすれば実現できるか考えてみます。

考えるポイントは、以下の2点です。

まずはクロック信号です。

クロック信号はSPI通信の時と同様に以下のように構成すれば問題ありません。マスターがスイッチを操作すると、すべてのスレーブにクロック信号を伝えることができます。また、クロック信号はマスターしか操作できない点もSPI通信と同じです。

Pic practice 37 switch lamp clock

次にデータ信号です。

データ信号線は1本しかありませんので、この1本の信号線でマスターからスレーブ、スレーブからマスターの双方向に信号を送る必要があります。

一見難しそうですが、このような回路は以下のように構成すれば実現できます。

Pic practice 37 switch lamp data

、、、、、ってちょっとわかりづらいですよね。回路部分だけにしてもう少しわかりやすくすると、以下のようになります。

Pic practice 37 switch lamp data simple

このような回路にすると、マスターからスレーブ、スレーブからマスターの双方向で信号を送ることができます。

例えば、マスターが送信者になり、マスターからスレーブにデータを送る場合、以下のように送信者以外はスイッチを閉じておきます。

Pic practice 37 switch lamp data send

この状態で送信者がスイッチを操作すると、データが送信できるわけです。

Pic practice 37 switch lamp data send 2

この例ではマスターが送信者ですが、スレーブ(兄)が送信者になる場合は、マスターとスレーブ(弟)がスイッチを閉じた状態にしておけば、スレーブ(兄)はスイッチを操作してデータ信号を送信することができます。

なお、この回路には特徴があります。普通、データの送受信というと1対1で通信するイメージがありますよね。でも上のような回路では、送信者の信号は受信者全員が受信してしまいます。SPI通信の時にあったようなスレーブを選択する信号線はありませんので、受信者は自分宛の通信なのか判別する仕組みが必要になります。この仕組みについては、後半で説明します。

これまでの話はあくまでリビングと勉強部屋の通信システムの話ですが、実際のI2C通信のハードウエアはどうなっているのでしょうか。実際のI2C通信の回路図を見ると、抵抗が接続されていますよね。この抵抗の目的も含めて、実際のI2C通信のクロック信号線とデータ信号線のハードウエアを説明します。

I2C通信のクロック信号線

クロック信号はマスター側が送信し、スレーブ側は受信のみ行います。

マスター側のクロック信号端子(SCLピン)の内部構成は以下のようになっています。

Pic practice 37 clock pin master

このようにマスター側には単に電子的なスイッチが入っているだけです。

一方、スレーブ側はマスターから送信されるクロック信号の電圧値を読むだけです。

Pic practice 37 clock pin slave

このような構成のマスターとスレーブのSCLピンを接続すると、以下のようになります。

Pic practice 37 clock pin p2p connection

この回路でマスターがスイッチを操作した時にどうなるか考えてみます。

まず、マスターがスイッチを押した場合は、0Vになりますので、スレーブは「0」というデータを受信できます。

Pic practice 37 clock pin low

一方で、マスターがスイッチを離した場合は、、、

Pic practice 37 clock pin high

このような状況は、どこかで見覚えがありませんか?

基礎編の第24回でスイッチ回路を検討しましたが、そのときと全く同じ状況なんです。スイッチを離した場合、クロック信号線はどこにも接続されていませんので、電圧値が不安定になります。そこで、基礎編のスイッチ回路と同じように「プルアップ抵抗」が必要になるんです。

Pic practice 37 clock pin pullup

なお、このプルアップ抵抗は数k〜10kΩ程度にします。I2C通信の場合のプルアップ抵抗は適切な値があるのですが、その値の見積もりはかなり難しい内容になってしまいます。実践編のプログラムで設定するI2C通信の条件であれば、10kΩで問題ありません。

また、スレーブが複数ある場合は、以下のように接続すればOKです。

Pic practice 37 clock pin connection

 

I2C通信のデータ信号線

データ信号は、マスター、スレーブ関係なく、お互いに送受信できますので、内部構成はマスターもスレーブも同じです。最初に説明したリビングと勉強部屋の通信システムでは、リビングも勉強部屋も回路構成は同じでした。I2C通信のデータ信号も同様に、マスター、スレーブ共に電子的なスイッチと、電圧値を読み取る部分があります。

マスターの内部構成は以下のようになっています。

Pic practice 37 data pin master

スレーブの内部構成も同様です。

Pic practice 37 data pin slave

先ほどのクロック信号と同様の理由で、データ信号線も以下のようにプルアップ抵抗が必要になります。

Pic practice 37 data pin pullup

このような構成にした場合、受信者はスイッチを離しておき、送信者はスイッチを操作します。この説明だけですと理解しづらいかもしれませんので、マスターがデータ送信者、スレーブがデータ受信者の時を考えてみます。

この時、スレーブは受信者ですのでスイッチを離した状態にします。つまりスレーブ側のスイッチはないものとして考えることができます。また、マスターは送信者ですので、スイッチの操作のみを行い、電圧値の読み取り部分はないものとして考えることができます。このように考えると、マスターからスレーブのデータ送信は以下のような構成になり、先ほどのクロック信号と同様の構成になります。

Pic practice 37 data pin from master to slave

スレーブからマスターにデータ送信する場合はこれと逆になりますが、仕組みは同じです。

 

I2C通信手順のイメージ

ここまでの説明でI2C通信では2本の信号線を使用して、マスターとスレーブ間でデータ(0か1か)を送受信できることがわかりました。

SPI通信の時はこれ以外にチップセレクト信号線がありましたので、チップセレクト信号を使って「通信相手のスレープを選択」と「通信の開始」「通信の終了」をマスターからスレーブに知らせることができました。

I2C通信の場合は、マスターとスレーブ間で0か1かのデータのやり取りしかできませんので、クロック信号とデータ信号のみを使って、スレーブ選択、通信の開始、通信の終了のルールを決める必要があります。

I2C通信の通信手順は少ない信号線で多くのことを表現する必要があるため、SPI通信に比べるとかなり複雑です。詳細な通信手順は次回の記事で説明しますが、それに先立って通信手順の概略を説明します。まずは、I2C通信ではどのように通信を行なっているか概要を把握してみてください。

最初にスレーブの選択方法の概略について説明します。

I2C通信でマスターがスレーブを選択する場合、スレーブ毎に固有に割り振られている番号を使用します。この番号のことを「スレーブアドレス」と呼んでいます(「バスアドレス」と呼ばれることもあります)。

スレーブアドレスは7ビットの数値です(10ビットのモードもありますが、あまり使われないためこの入門シリーズでは7ビットのみを扱います)。実践編で使用している温度センサは0x48、液晶モジュールは0x3Eというスレーブアドレスが割り当てられています。

Pic practice 37 i2c slave address

マスターはクロック信号線とデータ信号線を使って、このスレーブアドレスの数値を送信してスレーブを選択するわけです。全てのスレーブは、マスターから送信されるスレーブアドレスを受信します。スレーブは、送られてきた数値が自分のアドレスだったら「あっ、自分だ」って感じでマスターの話し相手(通信相手)になります。

このように、I2C通信の回路に複数のスレーブが接続されていても、スレーブアドレスという数値を送ることにより、通信相手となるスレーブを選択するようになっています。

このスレーブアドレスについて、ちょっと疑問が出てくると思います。例えば同じI2C通信の回路に温度センサを2個接続したい場合、2個のセンサのスレーブアドレスが両方とも0x48ですとスレーブが正しく選択できません。このような場合、スレーブアドレスを変更する必要がありますが、変更できるのでしょうか。

スレーブアドレスが変更できるかどうかは、モジュール毎に異なります。

今回使用する温度センサ(ATD7410)ではスレーブアドレスは4種類のいずれかが選択できます。以下はADT7410温度センサモジュールの説明書の抜粋です。

Pic practice 37 adt7410 address selection
(秋月電子通商「ADT7410温度センサモジュール説明書」より抜粋)

モジュールの基板上に半田付けする箇所がありますので、その箇所を半田付けするかしないかで4種類のアドレスから選択できるようになっています。

一方、液晶モジュールはスレーブアドレスの変更はできません。0x3E固定です。

つまり、温度センサは1つのI2C通信回路に4個まで接続できますが、液晶モジュールは1個しか接続できない、という仕様になります。もし、温度センサを5個以上、液晶モジュールを2個以上接続したい場合は、PICマイコンに空きピンがありますので、I2C通信回路をもう一つ用意する必要があります。

スレーブアドレスが選択できるか固定かは、スレーブモジュールの性格によります。温度センサは複数の地点の観測をする可能性が高いので4種類のアドレスが選択できるようになっているのだと思います。また、液晶モジュールは2個も3個も接続するケースは稀だろう、ということでアドレスが固定になっているものと思われます。

スレーブ選択方法の概要がわかったところで、I2C通信の通信手順概略を説明します。

これから説明する例は一番簡単なケースで、マスターから何バイトかデータを送信する例です。例えば、PICマイコン(マスター)がスレーブ(液晶モジュール)に対して、「表示文字を全て消してください」というデータを送信する例です。

1. マスターの信号を監視

データ通信が行われていない時、以下のようにスレーブはマスターの信号を監視します。I2C通信を開始する際、マスターは通信開始を知らせるので、全てのスレーブはマスターの通信開始の信号を監視しています。

Pic practice 37 i2c idle

 

2. 通信開始

マスターがスレーブと通信を開始する際、最初に通信開始の合図を送ります。具体的にどのようにクロック信号線とデータ信号線を操作するかは次回の通信手順の記事で詳しく説明します。

通信開始の合図の後、マスターからスレーブアドレスの数値が送られてきますので、全てのスレーブはスレーブアドレスの受信待ちに入ります。

Pic practice 37 i2c start bit

 

3. スレーブアドレス送信

マスターが通信開始の合図を送った後、マスターはこれから通信を行う相手を指定するためにスレーブアドレスの数値を送ります。データの送り方はSPIと同様、データ信号線にデータをセットして、クロック信号線を変化させます。

スレーブアドレスを送信する際、7ビットのスレーブアドレスに加えて1ビットの情報を追加して8ビットデータとして送ります。この追加する1ビットの情報は、これから読み取りを行うのか、書き込みを行うのか、という情報です(読み取りが1、書き込みが0)。

例えば、マスターがスレーブアドレスが「0x3E」で書き込み、というデータを送信した場合、スレーブアドレスが0x3Eの液晶モジュールは自分が選択されたと認識し、またこれから書き込みが行われることを認識します。一方、スレーブアドレスが0x48のセンサモジュールはこれから行われる通信は自分宛ではないと認識します。

Pic practice 37 i2c address

なお、送信する8ビットのフォーマットは以下のようになっています。

Pic practice 37 slave address format

I2C通信の場合、このスレーブアドレスの数値に注意する必要があります。

液晶モジュールのスレーブアドレスは0x3Eです。また液晶モジュールは表示データをマスターからスレーブに送るだけ、つまりデータの書き込みしか行いませんので、読み書きの設定は常に0(=書き込み)となります。

先ほどのフォーマットに合わせると、以下のように表現できます。

Pic practice 37 slave address value separate

今までの説明でこのようになるのは当たり前、という感じですよね。ただ、データシートによっては読み書きまで含めてスレープアドレス、と呼んでいるケースがありますので注意が必要です。

Pic practice 37 slave address value combined

以下は実践編で使用している液晶モジュールの説明書に書かれているスレーブアドレスの説明部分です。

Pic practice 37 lcd slave address
(秋月電子通商「I2C通信液晶モジュール説明書」より抜粋・加工)

この説明書では読み書き指定ビットまで含めてスレーブアドレスと呼んでいますので、0x7Cになります。またArduinoのプログラムの場合、I2C制御関数でアドレス指定する場合は7ビット本来の指定になりますので「Arduino表現では0x3Eになります」と説明されています。

ちょっとややこしいですが、ご自分でI2Cモジュールを使用する場合、スレーブアドレスの表現に注意していただければと思います。

 

4.「了解」返信

次に選択されたスレーブは、認識したことをマスターに伝えるために「了解!」という1ビットのデータをマスターに伝えます。具体的にはスレーブからマスターに0を送ります。マスターはスレーブから1ビットの0が返信されてきたら了解された、と認識します。

Pic practice 37 i2c slave ack

なお、選択されなかったスレーブは、今回の通信終了の信号を確認し続けます。

 

5. データ送信

ここまでの手順でマスターは通信相手のスレーブが選択できましたので、必要なデータを送信します。データ送信の手順はSPI通信と同様に、データ信号線にデータをセットした後、クロック信号を変化させます。

Pic practice 37 i2c data

 

6.「了解」返信

マスターからスレーフに8ビットのデータを送るごとに、スレーブはマスターに「了解」信号を返信します。1ビットの0をスレーブからマスターに送信します。スレーブは今回のデータ通信が終わったことを認識し、次の通信開始に備えて全てのスレーブは、マスターの通信開始信号の監視を始めます。

Pic practice 37 i2c slave ack

 

7. 通信終了

マスターからスレーブに全てのデータを送信したら、マスターは「通信終了」の信号を送ります。

Pic practice 37 i2c stop bit

以上がI2C通信手順の概要です。なんだかずいぶん複雑な気もしますが、2本の信号線のみ(2組のスイッチと電球のみ)でデータ通信を行いますので、スレーブ選択の手順などが複雑になってきてしまいます。

次回の記事では、それぞれのステップの具体的なタイミングチャートを説明します。

 

更新履歴

日付 内容
2018.6.5 新規投稿