I2C通信の考え方(2)PICマイコン入門-実践PICマイコン入門-実践I2C通信のハードウエア構成と通信手順の概略を説明します。I2C通信のハードウエア前回の記事で、I2C通信では1本のクロック信号線と1本のデータ信号線のみの構成で、マスターと複数のスレーブ間でデータ通信を行うことを説明しました。最初に、例のリビングと勉強部屋間の通信システムで、このような通信を行うためにはどのようなハードウエア構成にすれば実現できるか考えてみます。考えるポイントは、以下の2点です。1本の信号線で、クロック信号をマスターから複数のスレーブに伝える方法1本の信号線で、データ信号をマスターからスレーブ、スレーブからマスターの双方向に伝える方法まずはクロック信号です。クロック信号はSPI通信の時と同様に以下のように構成すれば問題ありません。マスターがスイッチを操作すると、すべてのスレーブにクロック信号を伝えることができます。クロック信号はマスターしか操作できない点もSPI通信と同じです。データ信号線は1本しかありませんので、この1本の信号線でマスターからスレーブ、スレーブからマスターの双方向に信号を送る必要があります。難しそうですが、このような回路は以下のように構成すれば実現できます。わかりづらいですよね。回路部分だけにしてもう少しわかりやすくすると、以下のようになります。このような回路にすると、マスターからスレーブ、スレーブからマスターの双方向で信号を送ることができます。マスターが送信者になり、マスターからスレーブにデータを送る場合、以下のように送信者以外はスイッチを閉じておきます。この状態で送信者がスイッチを操作すると、データが送信できるわけです。この例ではマスターが送信者ですが、スレーブ(兄)が送信者になる場合は、マスターとスレーブ(弟)がスイッチを閉じた状態にしておけば、スレーブ(兄)はスイッチを操作してデータ信号を送信することができます。この回路には特徴があります。普通、データの送受信というと1対1で通信するイメージがありますよね。上のような回路では、送信者の信号は受信者全員が受信してしまいます。SPI通信の時にあったようなスレーブを選択する信号線はありませんので、受信者は自分宛の通信なのか判別する仕組みが必要になります。この仕組みについては、後半で説明します。これまでの話はあくまでリビングと勉強部屋の通信システムの話ですが、実際のI2C通信のハードウエアはどうなっているのでしょうか。実際のI2C通信の回路図を見ると、抵抗が接続されていますよね。この抵抗の目的も含めて、実際のI2C通信のクロック信号線とデータ信号線のハードウエアを説明します。I2C通信のクロック信号線クロック信号はマスター側が送信し、スレーブ側は受信のみ行います。マスター側のクロック信号端子(SCLピン)の内部構成は以下のようになっています。このようにマスター側には単に電子的なスイッチが入っているだけです。スレーブ側はマスターから送信されるクロック信号の電圧値を読むだけです。このような構成のマスターとスレーブのSCLピンを接続すると、以下のようになります。この回路でマスターがスイッチを操作した時にどうなるか考えてみます。マスターがスイッチを押した場合は、0Vになりますので、スレーブは「0」というデータを受信できます。一方で、マスターがスイッチを離した場合は、、、このような状況は、どこかで見覚えがありませんか?基礎編の第24回でスイッチ回路を検討しましたが、そのときと全く同じ状況なんです。スイッチを離した場合、クロック信号線はどこにも接続されていませんので、電圧値が不安定になります。そこで、基礎編のスイッチ回路と同じように「プルアップ抵抗」が必要になるんです。このプルアップ抵抗は数k〜10kΩ程度にします。I2C通信の場合のプルアップ抵抗は適切な値があるのですが、その値の見積もりはかなり難しい内容になってしまいます。実践編のプログラムで設定するI2C通信の条件であれば、10kΩで問題ありません。スレーブが複数ある場合は、以下のように接続すればOKです。I2C通信のデータ信号線データ信号は、マスター、スレーブ関係なく、お互いに送受信できますので、内部構成はマスターもスレーブも同じです。最初に説明したリビングと勉強部屋の通信システムでは、リビングも勉強部屋も回路構成は同じでした。I2C通信のデータ信号も同様に、マスター、スレーブ共に電子的なスイッチと、電圧値を読み取る部分があります。マスターの内部構成は以下のようになっています。スレーブの内部構成も同様です。先ほどのクロック信号と同様の理由で、データ信号線も以下のようにプルアップ抵抗が必要になります。このような構成にした場合、受信者はスイッチを離しておき、送信者はスイッチを操作します。この説明だけですと理解しづらいかもしれませんので、マスターがデータ送信者、スレーブがデータ受信者の時を考えてみます。この時、スレーブは受信者ですのでスイッチを離した状態にします。スレーブ側のスイッチはないものとして考えることができます。マスターは送信者ですので、スイッチの操作のみを行い、電圧値の読み取り部分はないものとして考えることができます。このように考えると、マスターからスレーブのデータ送信は以下のような構成になり、先ほどのクロック信号と同様の構成になります。スレーブからマスターにデータ送信する場合はこれと逆になりますが、仕組みは同じです。I2C通信手順のイメージここまでの説明でI2C通信では2本の信号線を使用して、マスターとスレーブ間でデータ(0か1か)を送受信できることがわかりました。SPI通信の時はこれ以外にチップセレクト信号線がありましたので、チップセレクト信号を使って「通信相手のスレープを選択」と「通信の開始」「通信の終了」をマスターからスレーブに知らせることができました。I2C通信の場合は、マスターとスレーブ間で0か1かのデータのやり取りしかできませんので、クロック信号とデータ信号のみを使って、スレーブ選択、通信の開始、通信の終了のルールを決める必要があります。I2C通信の通信手順は少ない信号線で多くのことを表現する必要があるため、SPI通信に比べるとかなり複雑です。詳細な通信手順は次回の記事で説明しますが、それに先立って通信手順の概略を説明します。I2C通信ではどのように通信を行なっているか概要を把握してみてください。最初にスレーブの選択方法の概略について説明します。I2C通信でマスターがスレーブを選択する場合、スレーブ毎に固有に割り振られている番号を使用します。この番号のことを「スレーブアドレス」と呼んでいます(「バスアドレス」と呼ばれることもあります)。スレーブアドレスは7ビットの数値です(10ビットのモードもありますが、あまり使われないためこの入門シリーズでは7ビットのみを扱います)。実践編で使用している温度センサは0x48、液晶モジュールは0x3Eというスレーブアドレスが割り当てられています。マスターはクロック信号線とデータ信号線を使って、このスレーブアドレスの数値を送信してスレーブを選択するわけです。全てのスレーブは、マスターから送信されるスレーブアドレスを受信します。スレーブは、送られてきた数値が自分のアドレスだったら「あっ、自分だ」って感じでマスターの話し相手(通信相手)になります。このように、I2C通信の回路に複数のスレーブが接続されていても、スレーブアドレスという数値を送ることにより、通信相手となるスレーブを選択するようになっています。このスレーブアドレスについて、ちょっと疑問が出てくると思います。同じI2C通信の回路に温度センサを2個接続したい場合、2個のセンサのスレーブアドレスが両方とも0x48ですとスレーブが正しく選択できません。このような場合、スレーブアドレスを変更する必要がありますが、変更できるのでしょうか。スレーブアドレスが変更できるかどうかは、モジュール毎に異なります。今回使用する温度センサ(ATD7410)ではスレーブアドレスは4種類のいずれかが選択できます。以下はADT7410温度センサモジュールの説明書の抜粋です。(秋月電子通商「ADT7410温度センサモジュール説明書」より抜粋)モジュールの基板上に半田付けする箇所がありますので、その箇所を半田付けするかしないかで4種類のアドレスから選択できるようになっています。液晶モジュールはスレーブアドレスの変更はできません。温度センサは1つのI2C通信回路に4個まで接続できますが、液晶モジュールは1個しか接続できない、という仕様になります。温度センサを5個以上、液晶モジュールを2個以上接続したい場合は、PICマイコンに空きピンがありますので、I2C通信回路をもう一つ用意する必要があります。スレーブアドレスが選択できるか固定かは、スレーブモジュールの性格によります。温度センサは複数の地点の観測をする可能性が高いので4種類のアドレスが選択できるようになっているのだと思います。液晶モジュールは2個も3個も接続するケースは稀だろう、ということでアドレスが固定になっているものと思われます。スレーブ選択方法の概要がわかったところで、I2C通信の通信手順概略を説明します。これから説明する例は一番簡単なケースで、マスターから何バイトかデータを送信する例です。PICマイコン(マスター)がスレーブ(液晶モジュール)に対して、「表示文字を全て消してください」というデータを送信する例です。マスターの信号を監視データ通信が行われていない時、以下のようにスレーブはマスターの信号を監視します。I2C通信を開始する際、マスターは通信開始を知らせるので、全てのスレーブはマスターの通信開始の信号を監視しています。通信開始マスターがスレーブと通信を開始する際、最初に通信開始の合図を送ります。具体的にどのようにクロック信号線とデータ信号線を操作するかは次回の通信手順の記事で詳しく説明します。通信開始の合図の後、マスターからスレーブアドレスの数値が送られてきますので、全てのスレーブはスレーブアドレスの受信待ちに入ります。スレーブアドレス送信マスターが通信開始の合図を送った後、マスターはこれから通信を行う相手を指定するためにスレーブアドレスの数値を送ります。データの送り方はSPIと同様、データ信号線にデータをセットして、クロック信号線を変化させます。スレーブアドレスを送信する際、7ビットのスレーブアドレスに加えて1ビットの情報を追加して8ビットデータとして送ります。この追加する1ビットの情報は、これから読み取りを行うのか、書き込みを行うのか、という情報です(読み取りが1、書き込みが0)。マスターがスレーブアドレスが「0x3E」で書き込み、というデータを送信した場合、スレーブアドレスが0x3Eの液晶モジュールは自分が選択されたと認識し、またこれから書き込みが行われることを認識します。スレーブアドレスが0x48のセンサモジュールはこれから行われる通信は自分宛ではないと認識します。送信する8ビットのフォーマットは以下のようになっています。I2C通信の場合、このスレーブアドレスの数値に注意する必要があります。液晶モジュールのスレーブアドレスは0x3Eです。液晶モジュールは表示データをマスターからスレーブに送るだけ、つまりデータの書き込みしか行いませんので、読み書きの設定は常に0(=書き込み)となります。先ほどのフォーマットに合わせると、以下のように表現できます。今までの説明でこのようになるのは当たり前、という感じですよね。データシートによっては読み書きまで含めてスレープアドレス、と呼んでいるケースがありますので注意が必要です。以下は実践編で使用している液晶モジュールの説明書に書かれているスレーブアドレスの説明部分です。(秋月電子通商「I2C通信液晶モジュール説明書」より抜粋・加工)この説明書では読み書き指定ビットまで含めてスレーブアドレスと呼んでいますので、0x7Cになります。Arduinoのプログラムの場合、I2C制御関数でアドレス指定する場合は7ビット本来の指定になりますので「Arduino表現では0x3Eになります」と説明されています。ややこしいですが、ご自分でI2Cモジュールを使用する場合、スレーブアドレスの表現に注意していただければと思います。次に選択されたスレーブは、認識したことをマスターに伝えるために「了解!」という1ビットのデータをマスターに伝えます。具体的にはスレーブからマスターに0を送ります。マスターはスレーブから1ビットの0が返信されてきたら了解された、と認識します。選択されなかったスレーブは、今回の通信終了の信号を確認し続けます。データ送信ここまでの手順でマスターは通信相手のスレーブが選択できましたので、必要なデータを送信します。データ送信の手順はSPI通信と同様に、データ信号線にデータをセットした後、クロック信号を変化させます。6.「了解」返信マスターからスレーフに8ビットのデータを送るごとに、スレーブはマスターに「了解」信号を返信します。1ビットの0をスレーブからマスターに送信します。スレーブは今回のデータ通信が終わったことを認識し、次の通信開始に備えて全てのスレーブは、マスターの通信開始信号の監視を始めます。通信終了マスターからスレーブに全てのデータを送信したら、マスターは「通信終了」の信号を送ります。以上がI2C通信手順の概要です。なんだかずいぶん複雑な気もしますが、2本の信号線のみ(2組のスイッチと電球のみ)でデータ通信を行いますので、スレーブ選択の手順などが複雑になってきてしまいます。