しかしPCのシリアルポート(RS-232C/EIA-232)へI2Cデバイスを接続できれば、マイコンの開発環境が無くても手軽にI2Cデバイスを使えそうです。
そこで、PCのシリアルポートとI2Cの信号レベルを相互に変換するアダプタを作りました。
Windowsのアプリケーションから、I2C制御のDLLを介してI2Cデバイスを操作できます。
本機は下図のように使用します。
I2Cの通信速度の上限は、標準モードで100kbps、ファストモードで400kbps、高速モードで3.4Mbpsとなっています。が、このシリアルポート経由だと下は150bpsから、頑張っても40Kbps程度しか出ませんでした(汗
このように書くと使い物にならないようなイメージを持たれるかもしれませんが、センサから一定間隔でデータを取得する用途などでは十分実用になります。
最近はシリアルポートのないPCもあると思います。USB-シリアル変換ケーブルはこちら
回路の POWER にはI2Cデバイスの電源電圧と同じ電圧を供給します。
手元に秋月さんで買ったMOS-FET(2N7000)があったので、これで作りました。
2N7000以外でも、NchエンハンスメントのMOS-FETで、Vgs(th)が3V未満程度のものなら何でもいいかと思います。ただし入力容量が少ないものを選んでください。
当初はSCLとSDA供に双方向の作りにしていましたが、考えてみるとクロックのSCLはマスタからの片方向でよいので、SCLの信号を受ける回路を削除しました。
この回路変更はソフト側へは影響ありません。DLLやアプリケーションはそのまま無変更で使用できます。
念のため旧回路図(2013/09/18版)を残しておきます。
この旧回路で製作された場合も引き続き問題なくご利用いただけます。
ますアダプタをPCのシリアルポートに接続し、電源を供給します。
次に、ダウンロード(後述)した SerialMon.exe を起動します。
SerialMonはシリアルポートの信号線を操作・表示するものです。
メニューの「ファイル→接続」でシリアルポートを選択し、回路が正しければ下記のような表示になるはずです。
SCLへテスタの + 端子を当て、GNDへテスタの - 端子を当てます。
DTRのチェックがONのときは0V、チェックをOFFにすると電源と同電圧になります。
同様にSDAへテスタの + 端子を当て、GNDへテスタの - 端子を当てます。
RTSのチェックがONのときは0V、チェックをOFFにすると電源と同電圧になります。
上記の操作をしてもSCLやSDAの電圧が変化しない場合は、アダプタの製作ミスの可能性があります。
本アダプタから電源を供給する例。
I2Cデバイス基板(ブレッドボード)側から電源を供給する例。
VC++でダイナミックリンクをする場合は i2c.h をインクルードします。
スタティックリンクの場合は i2c_static.h をインクルードし、i2c.lib も必要となります。
VBの場合、I2C.bas がDLLをインポートするためのDeclare文や定数の定義です。
I2CTest.frm から実際にDLLの関数を使用しています。
GUI環境からDLLを使用するサンプルが入っていますので参考にどうぞ。
i2c_connect(iPort) |
シリアルポートに接続します。 一つ目のパラメータにシリアルポートの番号を指定します。 戻り値が IIC_SUCCESS なら成功、IIC_FAILURE なら失敗です。 |
i2c_start() |
I2Cデバイスとの通信を開始します。 |
i2c_write(bDat) |
I2CデバイスへbDatのデータを1バイト書き込みます。 また、デバイスからのAck/Nack状態をそれぞれ IIC_ACK / IIC_NACK で返します。 |
i2c_read(boAckFlg) |
I2Cデバイスから1バイト読み込み、関数の戻り値として返します。 boAckFlgに IIC_ACK / IIC_NACK のいずれかを指定して、それぞれデバイスへAck/Nackを通知します。 |
i2c_stop() |
I2Cデバイスとの通信を終了します。 |
i2c_disconnect() |
シリアルポートを切断します。 戻り値が IIC_SUCCESS なら成功、IIC_FAILURE なら失敗です。 |
LcdMain.cpp/exe |
I2CのLCD(AQM0802A)に現在日時を一定間隔で表示させるサンプルです。 |
PressMain.cpp/exe |
気圧センサのLPS331(AE-LPS331)から一定間隔で気圧と温度を読み出し、画面に表示するサンプルです。 |
PressLcdMain.cpp/exe |
LPS331(AE-LPS331)から取得した気圧・温度をLCD(AQM0802A)に表示するサンプルです。 |
RtcMain.cpp/exe |
RTC-8564NBから一定間隔で日時を読み出し、画面に表示するサンプルです。 |
RadioMain.cpp/exe |
ラジオモジュール(TEA5767)の周波数を、キーボード操作でUp/Downして選局動作させるサンプルです。 |
FMTransmitterMain.cpp/exe |
FMトランスミッタ(NS73M)の周波数を、キーボード操作でUp/Downして設定させるサンプルです。 周波数の計算はゆきさんが公開されているソースからいただきました。有用なソースを公開していただき、まことにありがとうございます。 |
ListDevice.cpp/exe |
I2Cバスに接続されているI2Cデバイスをサーチし、見つかったデバイスを画面に表示するサンプルです。 |
I2C通信のアドレス指定例
上記を8bit分そのまま記載するメーカの場合は、2進数で10101010 になるため、デバイスアドレスは 0xAA と表記されます(Writeの場合)
一方、アドレスの7bit分のみを抜き出して記載するメーカの場合は、2進数で1010101 になるため、デバイスアドレスは 0x55 と表記されます。
この違いにご注意ください。
Athlon64 3500+ 2.2GHz
マザーボードのシリアルポート
Celeron 2GHz i845GL
マザーボードのシリアルポート
マザーボードのシリアルポートは速いです。逆にUSB-シリアル変換器はかなり遅い結果になりました。
また、CPUパワーにも左右されています。