title: Phi::CommX
author: YOSHIDA Kazuhiro
mailto: moriq@moriq.com

1. Phi::CommX

Phi::CommX は， Delphi 5 用の RS232C 通信コンポーネントです。基本的には， Windows API をラップしているだけですが，送信や受信にスレッドとメッセージを使い，効率的に通信させることができます。

Phi::CommX には以下の特徴があります。

Delphi 5 で使用できる RS232C 通信コンポーネントです。 Delphi 4 以降わずかながら仕様の変更があったので， Delphi 3.1 で動作していたコンポーネントが，正しく動作しない場合があります。このコンポーネントなら，そのまま利用することができます。送信に別のスレッドを用意し，ウィンドウメッセージでデータを送るようにしているので，送信時に別の処理を行うことができます。さらに，送信処理中に送信しても，キューに溜まるだけで問題なく動作します。

受信に別のスレッドを用意し，受信時にイベントを発生させることができます。ウィンドウメッセージを送り，メインスレッド側でイベントを発生させるようにしているので，スレッドセーフでない処理 (VCL など ) を含めることができます。

同時に複数のポートに対してアクセスできます。複数のポートをオープンすると，それに応じてスレッドやウィンドウハンドルを生成します。

半二重通信機能をサポートしています。 RS232C-RS485 コンバータなど，送信時のみ RTS を ON/OFF しなければならないフローコントロールを行うことができます。

Phi::CommX は， Delphi 2 以降，または C++Builder1 以降で動作することが確認されています。ただ作者の環境が Delphi 5 のみとなったため正式にはサポートできません。

Phi::CommX は，フリーウェアコンポーネントです。十分ご確認の上，ご使用ください。

1.1. super class

%c:Object%

1.1. class methods

: new(parent[, name, caption]) : Phi::CommX

1.1. properties

: port_no : Fixnum = 1

  通信ポートの番号を指定します。たとえば， COM1 を使用するには， 1 を設定します。デフォルトは 1 に設定されています。

  通信ポートがオープンされている状態で，このプロパティを変更した場合，現在のポートがクローズされたあとに，新しいポートがオープンされます。

  ポートをオープンする前に，必ずこのプロパティの値を設定しておいてください。このプロパティが使用できないポート番号を示している時にオープンした場合，手続きは失敗し，例外が発生します。

: bit_rate : Fixnum = 9600

  通信速度を bps 単位で指定します。デフォルトは 9600bps に設定されています。

  このプロパティで，どのような値が設定できるかどうかは，ハードウェアやデバイスドライバによって異なります。

  基本的には，次のような値が設定できます。

  300 / 600 / 1200 / 2400 / 4800 / 9600 / 14400 / 19200 / 38400 / 56000 / 57600 / 115200 / 128000 / 256000

  標準的な DOS/V パソコンでは， 38400bps までは指定できます。最近のパソコンでは，ほとんど 115200bps まで指定できるようです。

  正しく設定できない場合，例外が発生します。

: char_size : Fixnum = 8

  1 キャラクタのビット数を指定します。デフォルトは 8 ビットです。

  このプロパティで，どのような値が設定できるかどうかは，ハードウェアやデバイスドライバによって異なります。

  基本的には， 5 ビットから 8 ビットまで指定できます。

  通信 IC に 8250 系のものを使用した標準的 DOS/V パソコンでは，ストップビット長が 2 のときには，ビット長 5 は指定できません。また，ストップビット長が 1.5 のときには，ビット長 6, 7, 8 は指定できません。

  正しく設定できない場合，例外が発生します。

: parity_bit : Fixnum (CommParityBits) = CPB_NONE

  パリティチェックの方式を指定します。次の値から指定できます。

  : CPB_NONE
    パリティなし
  : CPB_ODD
    奇数パリティ
  : CPB_EVEN
    偶数パリティ

  デフォルトは %c:CPB_NONE% ( パリティなし ) です。

: stop_bit : Fixnum (CommStopBits) = CSB1

  ストップビット長を指定します。次の値から指定できます。

  : CSB1
    1 ビット
  : CSB1P5
    1.5 ビット
  : CSB2
    2 ビット

  デフォルトは %c:CSB1% ( 1 ビット ) です。

  このプロパティで，どのような値が設定できるかどうかは，ハードウェアやデバイスドライバによって異なります。詳しくは， CharSize プロパティを参照してください。

  正しく設定できない場合，例外が発生します。

: flow_ctrl : Fixnum (CommFlowCtrls) = CFC_RTS_CTS

  フローコントロールの方式を指定します。次の値を指定できます。

  : CFC_RTS_CTS
    RTS/CTS 制御を行う
  : CFC_DTR_DSR
    DTR/DSR 制御を行う
  : CFC_XON_XOFF
    XON/XOFF 制御を行う
  : CFC_HALF_HIGH
    半二重制御を送信時 ON で行う
  : CFC_HALF_LOW
    半二重制御を送信時 OFF で行う
  : CFC_NONE
    何も制御を行わない

  デフォルトは %c:CFC_RTS_CTS% ( RTS/CTS 制御 ) です。

  RTS/CTS, DTR/DSR, XON/XOFF 制御のときの，受信可しきい値は， #buf_len_receive の 4 分の 1 ，受信不可しきい値は， #buf_len_receive の 4 分の 3 となります。

  %c:CFC_HALF_HIGH% , %c:CFC_HALF_LOW% は，送信時のみ RTS 信号線をオンまたはオフ操作します。この機能は， RS232C RS485 コンバータなどで使用します。 RS485 では信号線が一対しかないために， RTS 信号をアクティブにしたところのデータだけが回線にのります。通信相手からの応答に答えるプログラムの場合，通信相手がまだ RTS をアクティブにしている場合があるため，自動的に送信に少しウェイトが入るようになっています。

  正しく設定できない場合，例外が発生します。

  通信 IC に 8251 系 を使用した NEC PC-9801 シリーズ等では，これらの設定に関わらず，送信ハードウェア制御がかかります。

  また， PC-9801 シリーズで RTS/CTS 制御を行ったときに， CTS がオフの状態でポートをオープンすると， CTS がオンになっても送信できないというバグがあるようです。これは，おそらくシリアルドライバの問題ですが，本コンポーネントでは，何も対策を行っていないので注意が必要です。

: time_out_send : Fixnum

  送信のタイムアウトを ms 単位で指定します。送信相手の準備ができていない状態のときに，送信手続きを呼び出してからタイムアウト時間が経過すると，送信データは失われます。

  この値を 0 に設定すると，送信タイムアウトの動作は行われず，何時間でもバッファに残ったままとなります。 0 の設定はなるべく行わないで下さい。

  正しく設定できない場合，例外が発生します。

: time_out_receive : Fixnum

  受信のタイムアウトを ms 単位で指定します。受信手続きを行ってから，タイムアウト時間経過すると，それぞれの手続きから復帰します。

  受信バッファの内容は，この値に関係なく #clear_receive_buf メソッドでクリアするか，通信ポートをクローズするまで保持されます。

  正しく設定できない場合，例外が発生します。

: xon_char : Fixnum (Char)

  XON/XOFF 制御で使用する XON 文字を指定します。

  正しく設定できない場合，例外が発生します。

: xoff_char : Fixnum (Char)

  XON/XOFF 制御で使用する XOFF 文字を指定します。

  正しく設定できない場合，例外が発生します。

: buf_len_send : Fixnum = 2048

  送信バッファの大きさをバイト単位で指定します。デフォルトは 2048 バイトです。

  このプロパティで，どのような値が設定できるかどうかは，ハードウェアやデバイスドライバによって異なります。

  小さな値を設定しても，最適な値に増やされる場合もあります。

  正しく設定できない場合，例外が発生します。

: buf_len_receive : Fixnum = 2048

  受信バッファの大きさをバイト単位で指定します。デフォルトは 2048 バイトです。

  このプロパティで，どのような値が設定できるかどうかは，ハードウェアやデバイスドライバによって異なります。

  小さな値を設定しても，最適な値に増やされる場合もあります。

  正しく設定できない場合，例外が発生します。

: Handle : Fixnum (Handle)

  通信ハンドルの値を示します。

  このプロパティは，拡張のために用意されています。また，オープンされていない状態のときは，必ず -1 となるので通信コンポーネントの状態を知ることもできます。

1.1. methods

: open : nil

  通信ポートをオープンします。本コンポーネントのメソッドやイベントを使用するには必ず呼び出さなければなりません。

  プログラム中コンポーネントを使う必要がなくなった場合は， #close メソッドを使用して通信ポートをクローズして下さい。

  この手続きによって，信号線の状態がフロー制御の内容に従って制御されます。フロー制御なしの場合は， RTS ， DTR ともに ON になります。

: close : nil

  通信ポートをクローズします。この手続きは，プログラム終了時に自動的に呼び出されますが，なるべく明示的に呼び出すようにして下さい。

  この手続きで RTS 信号と DTR 信号は OFF になります。ただし機種によってはポートをクローズすると ON 状態になるものもあるようです ( 未確認 ) 。そのため，このメソッドでは， 100ms 以上の間 OFF 状態を保ってから ( モデム切断のため ) クローズするようにしています。

: send_char(c) : Boolean

  : c : Fixnum (Char)

  %v:c% に渡された文字を送信します。正常終了のとき %c:true% を，異常終了のとき %c:false% を返します。

: send(s) : Boolean

  : s : String

  %v:s% に渡された文字列を送信します。正常終了のとき %c:true% を，異常終了のとき %c:false% を返します。

: receive_char : Fixnum (Char)

  通信ポートから 1 文字受信し受信データを返します。データがない場合やエラーの場合は， -1 を返します。

  データがない場合， #time_out_receive で設定された時間を待ってから返ります。

: receive(s) : Fixnum

  : s : String

  通信ポートから， %c:s.size% バイト数受信して， %v:s% 領域に格納します。返り値には，受信バイト数を返します。エラーの場合は， -1 を返します。

  データがない場合， #time_out_receive で設定された時間を待ってから返ります。

  タイムアウトかどうかを判断するには，指定した %c:s.size% と返り値が同じかどうかを比較して下さい。

  タイムアウトのとき，返り値に -1 が返るわけではありません。タイムアウトのときは，それまでに受信できたバイト数を返します。まったく受信できなかったときは， 0 になります。

: clear_send_buf : nil

  送信バッファをクリアします。

: clear_receive_buf : nil

  受信バッファをクリアします。

: get_send_length : Fixnum

  送信バッファにたまっているバイト数を返します。

: get_receive_length : Fixnum

  受信バッファにたまっているバイト数を返します。

: set_rts_signal(signal) : nil

  : signal : Boolean

  RTS 信号を ON/OFF します。 %v:signal% に %c:true% を渡すと ON に， %c:false% を渡すと OFF になります。

: set_dtr_signal(signal) : nil

  DTR 信号を ON/OFF します。 %v:signal% に %c:true% を渡すと ON に， %c:false% を渡すと OFF になります。

: cts_signal? : Boolean

  CTS 信号を返します。 ON の場合 %c:true% に， OFF の場合 %c:false% になります。

: dsr_signal? : Boolean

  DSR 信号を返します。 ON の場合 %c:true% に， OFF の場合 %c:false% になります。

: ring_signal? : Boolean

  リングインジゲータ (RI, CI) 信号を返します。 ON の場合 %c:true% に， OFF の場合 %c:false% になります。

: rlsd_signal? : Boolean

  RLSD (DCD, CD) 信号を返します。 ON の場合 %c:true% に， OFF の場合 %c:false% になります。

: send_break : nil

  300 ミリ秒間，ブレーク信号を送信します。

1.1. event handler

: on_receive(receive_size) : nil

  : receive_size : Fixnum

  受信イベントです。受信すると呼び出されます。 %v:receive_size% に受信バイト数が渡ってきます。

  このイベントの中で， %v:receive_size% を越えるバイト数を受信しようとしてはいけません。そのようにすると，次のイベントが呼び出され誤動作してしまう場合があります。

: on_break : nil

  ブレーク信号イベントです。ブレーク信号を受信すると呼び出されます。

: on_error(error_state) : nil

  : error_state : Fixnum

  通信エラーイベントです。通信エラーが発生すると呼び出されます。 %v:error_state% に，次の値の組み合わせが入ります。この値は Windows API ( %c:Win:module% ) で定義されています。

  : CE_FRAME
    フレーミングエラー
  : CE_OVERRUN
    バッファオーバーラン
  : CE_RXPARITY
    パリティエラー

  組み合わせなのでマスクして判定して下さい。

  : 例
    
--ruby
if error_state & Win::CE_FRAME
  Phi.message_dlg 'frame'
end
--

1.1. 操作方法

1.1.1. とりあえず送信してみる

フォームにボタンを一つ配置して，ボタンを押したときに送信するプログラムを示します。

%href:send.rb%

これでボタンを押したときに，デフォルトの通信設定で %c:'abc'% が送られます。

1.1.1. とりあえず受信してみる

フォームにメモを一つ配置して，受信内容を表示するプログラムを示します。

%href:recv.rb%

これで受信があると，その内容がメモに表示されます。

1.1.1. 制御機器などとの通信

制御機器などとの通信では，受信イベントを使用すると面倒な場合があります。ここではコマンドを送信してレスポンスを受信するような例を示します。

%href:control.rb%

ボタンをクリックするとコマンドを送信し， 10 文字受信するまで受信手続きの中で待機します。 10 文字受信すると’正常終了’ と表示します。 %c:len% が 10 ではない場合は，タイムアウトやエラーで抜けてきた場合なので，’異常終了’ と表示しています。

1.1. 基礎知識

1.1.1. RS232C

: RS232C

RS232C は， 1969 年に米国の EIA が， DTE ( データ端末装置 ) と DCE ( 回線終端装置 ) とのインターフェイス条件を定めた規格です。

DTE は主にコンピュータなどの制御装置を， DCE はモデムなどの回線端末の事を示します。

この規格はもともと，コンピュータとモデムを接続するためのものですが，標準でパソコンに搭載されたことから，外部の機器を制御したりデータを吸い上げたり，さまざまな目的に使用されています。

: 接続方法

コンピュータとモデムを接続する場合は，ストレートケーブルと呼ばれる 1 対 1 のケーブルを使用します。

コンピュータ同士を接続する場合は， 1 対 1 のケーブルだと出力信号同士がぶつかり合うことになるので，出力が相手の入力に入るような，クロスケーブルと呼ばれるものを使用します。

やっかいなのは，コンピュータとなんらかの制御機器を接続する場合です。これらの制御機器では， DTE として作られている場合と DCE として作られている場合があり，さらに簡易に作るために制御線を省略している場合があります。結線方法は千差万別といってよいので，使用する制御機器をよく調べておく必要があります。

1.1.1. シリアル通信

パソコンのインターフェイスには大きく分けて，パラレル通信とシリアル通信があります。パラレル通信には，プリンタを接続するためのパラレルポートや SCSI などがあります。シリアル通信には， RS232C を使用するシリアルポートや USB などがあります。

パラレル通信では， 1 つのデータ ( たとえば 1 バイト ) のコードを送るのに， 1 ビットずつ専用の線を使用して送信します。この方法では高速にデータを送信できますが，多くの配線をしないといけないために高価になります。

一方シリアル通信では， 1 対の線を使用して順番に送信します。この方法ではパラレル通信にくらべて低速ですが，少ない本数で通信することができます。

RS232C は多数の線を使用しますが，シリアル通信です。基本的に，送信と受信と共通の GND の 3 本があれば通信を行うことができます。

1.1.1. スタートビットとストップビット

: スタートビット

RS232C 規格では，データ線の信号レベルによって，データを 0 と 1 で表します。データを通信するときデータの開始を示すために， 1 ビット幅の信号を挿入します。これがスタートビットです。

: ストップビット

スタートビットを検出するためには，データがない間はスタートビットの反対の論理になっていなければ，判断することができません。そして連続でデータを送った場合に，スタートビットの前を反対の論理にしておくために 1 ビット幅のデータを挿入します。これがストップビットです。

ストップビットは必ず 1 ビット幅必要ですが， 1.5 ビット幅や 2 ビット幅にすることもできます。

受信側で本来送られてくるはずのストップビットが検出できない場合，フレーミングエラーが発生します。

1.1.1. ビットレート

ビットレートは， 1 秒間に送受信可能なビット数で規定する通信速度のことです。単位はビット毎秒 (bps) です。実際の伝送速度は，スタートビットやストップビットがあるために，若干劣ります。

1.1.1. ビット数

ビット数は， 1 キャラクタのデータビット数のことで，通常では 7 ビットか 8 ビットを使用します。

1.1.1. パリティビット

パリティビットは，伝送するデータの誤りを検出するために，データに挿入するビットの事です。偶数パリティと奇数パリティがあり，偶数パリティの場合は，データビットの '1' の数が偶数になるようにビットを挿入します。奇数パリティの時も同様に，データビットの '1' の数が奇数になるようにビットを挿入します。パリティビットでは，誤りを検出することはできてもデータを修復することはできないので，使用しないことが多いようです。

1.1. よくある質問

: Q.
拡張ボードは使用できますか ?
: A.
Windows が認識する通信ポートであれば問題なく使用できます。

: Q.
複数のポートを使用するにはどうすれば良いでしょうか ?
: A.
使用するポートの数だけ，フォーム上に %c:Comm% を配置し，それぞれの #port_no プロパティにポート番号を割り当てて下さい。

: Q.
ポートがオープンできないのですが
: A.
機種によっては，ポートが BIOS で無効になっている場合があります。とくに 2 ポート目は無効になっていることが多いので， BIOS で有効にして下さい。

: Q.
バイナリ通信をするにはどうすればよいのでしょうか ?
: A.
バイナリ通信をするには， 以下のように #send を使用して下さい。
--ruby
str = "\x02\x41\x03"
comm.send(str)
--
