RS-232C ループテスト | |
|
一台のPCによる、RS-232Cのループテスト
RS-232Cのプログラムを作成して他の機器やコンピュータに接続してテストした時に上手く動作しない事が有る。
いったいプログラムが悪いのか、ケーブルの不良なのか又は相手の機器の不具合なのか途方にくれてしまう。 こんな時はまずは自分のコンピューターには少なくても異常が無い事を確認したい。 RS-232Cにはループバックテストという方法が有る、この方法はRS-232Cのコネクタ部分又はケーブルの終端で、 RxDとTxD、DSRとDTRと言った具合に、RS-232cのINとOUTを互いに端子部でショートさ、自分で出した信号を 自分で受け取る事で機能をチェックする。 この場合は送受信が出来るプログラムを1つ立ち上げれば良い。 接続の仕方はクロスケーブルと同じなので「 RS-232Cの基礎 」を御覧頂きたい。 ループバックはかなり有力なチェック方法で有るが、ピンをショーとさせる為、ある程度ハードウェアーの知識が必要で 有る点が少々難点である。 ここでは一台のコンピューターの2つのRS-232Cのポートを使用して、プログラム及びハードウェアのチェックをする プログラムを考えて見る。 この方法を仮に「RS-232Cのループテスト」と名づけた、これは自分のコンピュータから出した信号を自分で読み込んで いると言う意味で、ループバックテストとは全く異なる方法であるので注意されたい。
必要なハードウェア
最近はRS-232Cのポートが無いコンピュータが増えてきた、もしお使いのコンピュータにRS-232Cのポートが1つも無かったら、
USB-RS232Cコンバータを2つ用意し、コンピュータのUSBポートに装着した後クロスケーブルで接続する。 もしコンピュータにRS-232Cのポートが1つ有る場合はUSB-RS232Cコンバータは1つで良いし、RS-232Cのポートが 2つ有る場合は当然の事ながらUSB-RS232Cは要らない。 肝心なことはいずれにしろクロスケーブルで接続することである。
仕様
下の画像を御覧頂きたい、ポートの名前を入れるテキストボックスが2つ有る。
このテキストボックスには、プログラムロード時に自動的にポート名が入るものとする。 なお自分でポート名を入力することも出来る。 各ポート名横にはOpenボタンが有り、Close時に押すとOpenにOpen時に押すとCloseになる。 その他DTR、RTSのチェックボックスが有りこれにチェックを入れると、相手のDST、CTSのラベルのバックカラーが明るい緑に 変わるものとする。 各ポートには送信と受信のテキストボックスが有り、送信テキストボックスに文字を書き込み送信ボタンを押すとデータが送られ、 相手の受信ボックスに表示される。 更にログ表示テキストボックスが有り、ログが表示出来るが、ここではエラー表示のみ表示することにする。 このテストプログラムは文字列の送信専用で有り、バイナリデータは送信出来ない。 送信文字は必ず改行が最後に付く物とし、改行が無い場合は自動的に改行を追加する。 受信側は改行を文字列の区切りとみなし、改行を受信した時に、テキストを表示する。 送信文字は全てSift-Jisで送信し受信側ではSift-JisからUnicodeに変換して表示する。 VB.NETもC#も文字操作は全てUnicode(UTF-16)で処理が行なわれる。 従って文字列をShift-Jisで送受信する場合は、送信側でUnicode - Shift-Jis変換が、 受信側でShift-Jis - Unicode変換が必要となる。 なおUnicode-Unicodeで送受信すると変換は不要となるが、現在の機器がの殆どが、 Shift-Jisでの送受信を行なっていることを考えると、一旦Shift-Jisに直して送信する事をお奨めしたい。 FrameworkのSrialPortクラスのWriteLineで送信する場合は受信側は、ReadLineで受信することになる。 この辺はMSDNにサンプルが有るのでそれを参考にされたし。 ここで注意するのは、文字列の送信と言ってもWriteLineを使用しないので、送信は バイト配列を使用する、文字列をバイト配列に変えて送信し、受信時はバイト配列から文字列に変換する。 さて文字列の代わりにバイナリデータで送受信したい場合はどうしたらいいのか? 先ず送りたいバイナリデータを「A B F 2」等とテキストボックスに書き込み、送信字にバイトデータに変換すれば良く、 受信時もバイナリデータを「1 2 A」などのHex表示に直して表示すれば良いことになる。 今回はこのモードは実装していないが 「RS-232C 送信モジュールの作成」 にこのモードを乗せて有るので参考にされたい。
コードの説明
ポート名の読み込み
先ずプログラムの起動時の自動でポート名を読み込む部分を説明する。
C#のコード
//起動時にポート名をマシンから取得し、テキストに書き出す
VB2005のコード
'起動時にポート名をマシンから取得し、テキストに書き出す
SerialPortクラスにはGetPortNames()というメソドが有り、使用可能なポートが取得出来る。
これで取得した名前をテキストに表示しているのである。 さてこの時に表示されるはずのポート名が表示されない場合はどうしたら良いのか? 「コントロールパネル」- 「コンピュータの管理」-「デバイスマネジャ」-「ポート」を確かめて頂きたい、 ここに使用可能なポートが表示されていなければ、ハードウエア的に何か不具合がある。 なお幾つかのポートが有る場合は、テキストボックスに適当な名前を入力すれば其の名前のポートが使用可能となる。
送信
送信はUnicode をSift-Jisに変換しByte配列に入れて送信する、送信する文字列の最後に改行が無い場合は
自動的に改行を挿入する。 なおencSjisクラスはコードの全体で宣言して有るので、全体のコードを見ていただきたい。
C#のコード
VB2005のコード
'送信ボタン押下
受信
受信はSerialPortクラスのDataReceivedイベントで行なう。
このイベントはメインスレッドとは別のスレッドでイベントが発生するので注意されたい。 すなわちこのスレッドで受信した文字をメインスレッドのテキストボックスに書き出す為には、デリゲートを使いInvokeメソドで 書き込む必要が有るのだ。 デリゲートにInvokeに関しては 「デリゲート入門」 「マルチスレッド入門」 を見ていただきたい。 ここで注意すべき点はデータの一時保持にListクラスを使用している点だ。 Listクラスはobject(Object)を配列で持てる非常に便利なクラスである。 Listクラスを知らない方は、使い方はほぼListBoxと同じでStringの替わりにこの場合はIntegerが格納されると思って戴きたい。 ここでは受信したデータをIntegerとしてListクラスで保持し、改行が来た段階でByte配列に移し、其の配列を文字に変換している。 ListクラスからByte配列に移した受信したデータはSift-Jisの文字データである。 これをUnicodeのByte配列に変換し、更にこれを文字列に変換している。 もちろんListクラスを使わずにByte配列だけの処理も可能であり、たぶんその方が速度的には速いと思われるが反面、 配列の確保や開放、書き込み、読み出しのポインターの管理など面倒な操作が必要で有る。 セリアルポートの受信文字の受信バイト数はserialPort1.BytesToReadのメソドで取得出来る。 取得した長さでバイト配列を確保する。 C# コード
byte[] byteRead = new byte[serialPort1.BytesToRead];
VB2005 コード
Dim byteRead(serialPort1.BytesToRead - 1) As Byte(VB2005)
そして次のコードで読み込む。
C# コード
serialPort1.Read(byteRead, 0, serialPort1.BytesToRead); VB2005 コード
serialPort1.Read(byteRead, 0, serialPort1.BytesToRead)
読み込んだデータを1バイトづつListクラスに追加しながら、
C# コード
lstInt1.Add(byteRead[i]); VB2005 コード
lstInt1.Add(byteRead(i))
改行が有るか否か探す。
C# コード
if (lstInt1.Count >= 2 && lstInt1[lstInt1.Count - 2] == 13 && VB2005 コード
If lstInt1.Count >= 2 AndAlso lstInt1(lstInt1.Count - 2) = 13 _
VB2005の場合はAndではなくAndAlsoを使用すること。
Andを使うとlstInt1.Countが2より小さい場合lstInt1.Count - 2でエラーになる。 AndAlsoを使うと前の条件は不成立の場合は次を評価しないので問題が起きない。 C#はもともと前の条件がfalseなら次を評価しないのだ、微妙な言語仕様の差に注意しよう。 改行が有ったらListクラスのIntegerの値をByte配列に移し、このShift-JisのByte配列をUnicodeの配列に変換して 更にUnicodeのByte配列を文字列に変換する。 メインスレッドへの書き込みはデリゲートを使ってInvokeで書き込む。 ここまで終わったらListクラスの保持している値を全てクリアーし次の文字列に備える。
C#のコード
//受信文字を保持するListクラス
VB2005のコード
'受信文字を保持するリストクラス
最後に
主だったコードの説明はこれで終わるが、PicChangedイベントやDSRやCTSのラベルのバックカラーを変える説明は
「RS-232Cのピンチェンジ表示 」 で詳しく説明しているのでそちらを参考にして戴きたい。 なお今回のプログラムを実行してみて気がついたことが有る。 serialPort1_DataReceivedイベントでserialPort1.ReadByteで1バイトずつデータを読み込ませたら、 かなりの確立でデータの取りこぼしが発生した。 多分これはハードウェア依存で有ろう、 serialPort1.Readに変えてからは取りこぼしは一回も発生しなかった。 |