[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
SerialPortコントロールを使い方を以下の記事で紹介しましたが、 今回は外部装置との簡単な送受信ができるクラスの紹介を行います。
⇒SerialPortコントロールの使用方法:[SerialPort,Invoke]
クラスの概要は以下の通りです。
- 外部装置との通信は調歩同期とし、Shift-JIS文字列での送受信を対象とする。
- 通信ポート設定は「ボーレート:9600BPS、データビット:8、パリティビット:無し、ストップビット:1」とする。
- 送受信文字列の終端文字は「CR:0xD」とする。
- 外部装置からのデータ受信は、最初にコマンド文字列を送信し、その後データ受信する手順とする。
- コマンド文字列送信後、約5秒以内にデータ受信できない場合はエラーとする。
- 受信文字列は4096バイトのバッファで行う。
SerialPortコントロールの使い方その2(通信用クラス)
Imports System.IO.Ports ''' ----------------------------------------------------------------------- '''''' シリアル通信クラス ''' ''' ----------------------------------------------------------------------- Public Class ClsSerial '''''' シリアルポートクラス ''' '''Private SerialPort As SerialPort ''' ''' 読込データ格納先 ''' '''データ受信イベントで蓄えられる Private RxBuf() As Byte '''''' コマンド応答受信フラグ ''' '''''' コマンドを送信した後での応答を受信したフラグ。送受信文字列のターミネータ[CR](0x0d)を発見したとにオンする ''' Private fRxResponse As Boolean = False '''''' 送受信文字列のターミネータ(0x0d) ''' Private Const CMD_TERM As Byte = &HD ''' ----------------------------------------------------------------------- '''''' コンストラクタ ''' ''' <param name="SerialPort">シリアルポートコントロール</param> ''' ----------------------------------------------------------------------- Sub New(ByVal SerialPort As SerialPort) 'シリアルポートの退避 Me.SerialPort = SerialPort '受信イベントのハンドラ設定 AddHandler Me.SerialPort.DataReceived, AddressOf DataReceivedHandler End Sub ''' ----------------------------------------------------------------------- '''''' ポートオープン ''' '''True:正常終了, False:エラー ''' ----------------------------------------------------------------------- Function Open() As Boolean '戻り値初期化 Open = False Try 'ポートチェック If Me.SerialPort.IsOpen = False Then '未オープンならば、オープンする 'ポート設定(ここは通信相手に合わせる) Me.SerialPort.PortName = "COM7" Me.SerialPort.BaudRate = 9600 Me.SerialPort.DataBits = 8 Me.SerialPort.Parity = Parity.None Me.SerialPort.StopBits = StopBits.One 'オープン Me.SerialPort.Open() End If '結果を返す Open = Me.SerialPort.IsOpen Catch ex As Exception 'エラー処理 End Try End Function ''' ----------------------------------------------------------------------- '''''' ポートクローズ ''' '''True:正常終了, False:エラー ''' ----------------------------------------------------------------------- Function Close() As Boolean '戻り値初期化 Close = False Try 'ポートチェック If Me.SerialPort.IsOpen = True Then 'オープン済みならば、クローズする Me.SerialPort.Close() End If '結果を返す Close = Not (Me.SerialPort.IsOpen) Catch ex As Exception 'エラー処理 End Try End Function ''' ----------------------------------------------------------------------- '''''' データ受信ハンドラ ''' ''' ----------------------------------------------------------------------- Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs) Try Dim SP As SerialPort = CType(sender, SerialPort) 'バッファのバイト数チェック Dim DataLen As Integer = SP.BytesToRead If DataLen = 0 Then Exit Sub End If 'データ長チェック If DataLen > 4096 Then DataLen = 4096 End If '読込バッファの確保 Dim Buf(DataLen) As Byte '読込 SP.Read(Buf, 0, DataLen) ' If RxBuf Is Nothing Then '格納バッファの領域確保 RxBuf = Array.CreateInstance(GetType(Byte), DataLen) 'コピー Array.Copy(Buf, RxBuf, DataLen) Else '後ろに追加する Dim Length As Integer = RxBuf.Length ReDim Preserve RxBuf(Length + DataLen - 1) Buf.CopyTo(RxBuf, Length) End If '格納先の最後の文字が「CR」(0x0d)か確認する If RxBuf(UBound(RxBuf)) = CMD_TERM Then 'コマンド応答受信フラグON Me.fRxResponse = True End If Catch ex As Exception 'エラー処理 End Try End Sub ''' ----------------------------------------------------------------------- '''''' コマンド送信・レスポンス受信処理 ''' ''' <param name="strCmd">コマンド文字列</param> ''' <param name="strRsv">レスポンス文字列</param> '''応答受信結果(True:OK, False:NG) ''' ----------------------------------------------------------------------- Public Function SendCmdGetRsv(ByVal strCmd As String, ByRef strRsv As String) As Boolean '戻り値初期化 SendCmdGetRsv = False Try 'コマンド送信 If Me.SendData(strCmd) = False Then Return False End If 'コマンド受信 Dim strRX As String = "" If Me.ReceiveData(strRX) = False Then Return False End If strRsv = strRX '正常を返す Return True Catch ex As Exception 'エラー処理 End Try End Function ''' ----------------------------------------------------------------------- '''''' コマンド送信 ''' ''' <param name="strSend">送信文字列</param> '''送信結果(True:OK, False:NG) ''' ----------------------------------------------------------------------- Private Function SendData(ByVal strSend As String) As Boolean '戻り値初期化 SendData = False Try 'ポートオープンチェック If Me.SerialPort.IsOpen = False Then Return False End If 'Shift JISとしてバイト型配列に変換 Dim bytesData As Byte() bytesData = System.Text.Encoding.GetEncoding(932).GetBytes(strSend) 'CRの1バイト分領域拡張 Dim nIdx As Integer = UBound(bytesData) ReDim Preserve bytesData(nIdx + 1) bytesData(nIdx + 1) = CMD_TERM 'コマンド応答受信フラグOFF Me.fRxResponse = False 'コマンド送信 Me.RxBuf = Nothing '受信バッファのクリア Me.SerialPort.Write(bytesData, 0, bytesData.Length) '正常 Return True Catch ex As Exception 'エラー処理 End Try End Function ''' ----------------------------------------------------------------------- '''''' レスポンス受信処理 ''' ''' <param name="RcvRes">受信レスポンス</param> '''受信結果(True:OK, False:NG) ''' ----------------------------------------------------------------------- Private Function ReceiveData(ByRef RcvRes As String) As Boolean '戻り値初期化 ReceiveData = False Try 'リトライ件数 Dim nRetry As Integer = 50 '50×100msec=5sec While nRetry > 0 System.Threading.Thread.Sleep(100) Application.DoEvents() If Me.fRxResponse = True Then '受信フラグONの場合、ループを抜ける Exit While End If 'リトライカウンタ-- nRetry -= 1 End While '----- 'タイムアウトチェック '----- If nRetry = 0 Then 'タイムアウトエラー Return False End If '受信バイトを文字列変換 Dim strRx As String = System.Text.Encoding.GetEncoding(932).GetString(Me.RxBuf) strRx = strRx.Substring(0, strRx.Length - 1) '最後の「CR」は省く '----- '受信データ処理 '----- '以下の処理などが在れば記述 '・BCC等のチェック処理 '・レスポンスチェック処理(送信側のエラーメッセージ等) '----- '受信レスポンスを返す RcvRes = strRx '結果正常 Return True Catch ex As Exception 'エラー処理 End Try End Function End Class
突っ込みどころが満載なクラスですが、簡単なコマンドを送信し、レスポンスを受信するぐらいであれば使用できると思います。
尚、受信イベントでの処理で、受信バッファを4096に限定していますので、この辺りを改良してみて下さい。
また、レスポンスの受信データをそのまま返していますが、エラー処理などは通信先の装置に合わせて下さい。
このクラスを使用した例を以下のソースに示します。
SerialPortコントロールの使い方その2(通信用クラスの使用例)
Public Class frmSerial2 'シリアル通信クラス Private mclsSerial As ClsSerial '''''' フォームクローズイベント ''' Private Sub frmSerial2_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed 'シリアル通信のクローズ mclsSerial.Close() End Sub '''''' フォームロードイベント ''' Private Sub frmSerial2_Load(sender As Object, e As EventArgs) Handles Me.Load 'シリアル通信クラスの生成 mclsSerial = New ClsSerial(Me.SerialPort1) 'シリアル通信のオープン If mclsSerial.Open() = False Then 'オープンエラー(必要があれば処理する) End If End Sub '''''' [コマンド送信]クリックイベント ''' Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'レスポンス表示クリア Me.TextBox2.Text = "" 'コマンド取得 Dim strCmd As String = Me.TextBox1.Text.Trim If strCmd <> "" Then Dim strRsv As String = "" If Me.mclsSerial.SendCmdGetRsv(strCmd, strRsv) = True Then '正常受信、レスポンス表示 Me.TextBox2.Text = strRsv Else 'エラー Me.TextBox2.Text = "エラー発生" End If End If End Sub End Class
このフォームは、送信用の文字列を入力する TextBox と、受信結果を表示する TextBox を画面に張り付け、 通信の処理をさせるボタンを張り付けてあります。
実行の様子を下図に示します。
送信する文字列を 送信コマンド: TextBox に入力し、「コマンド送信」ボタンを押下します。
「RS232Cテストツール」側でコマンドの受信を確認して、「TEXT送信」ボタンを押下しますと、 受信レスポンス: TextBox にデータが表示されます。
(尚、通信相手のシミュレーションとしてフリーソフトの「RS232Cテストツール」を使用しています。)
尚、通信相手用の仮想シリアルポートとしてcom0com というドライバを使用し、 2個のシリアルポートを作成し、ループバックで接続しています。 今回のプログラムをテストするためには外部装置か、もう一台別のPCが必要になりますが、 そんなことをしなくてもデバッグができるソフト(ドライバ)が在ります。
com0com というドライバで、PC上に仮想シリアルポートを2個作成し、 その2個をループバックできる様に仮想的に接続できるという優れものです。 以下のリンク先でソフトをダウンロードしてインストールしてみて下さい。 (尚、もう一台のPCなどがあれば必要ありませんが)
⇒「com0com ドライバ」
COM8側を通信相手側(外部装置)とするのですが、通信テスト用に以下のフリーソフトを使いました。
「のん」さんといわれる方が作成された「RS232Cテストツール」です。
以下のサイトにアクセスすれば、ダウンロードできます。
⇒「RS232Cテストツール」
USB ⇒ RS232C 変換ケーブル
シリアル通信に関連してですが、 最近のPC、特にノートPCの場合ではRS232Cのコネクタがついていることは殆んどありません。そのため、以下の様なUSBを使ったRS232Cの変換ケーブルが使えそうです。
⇒iBUFFALO USBシリアルケーブル(USBtypeA to D-sub9ピン)1.0m ブラックスケルトン BSUSRC0610BS
⇒サンワサプライ USB-RS232Cコンバータ USB-CVRS9
⇒Plugable USB‐9ピンRS232シリアルアダプター (Prolific社製 PL2303HX Rev Dチップセット採用)
関連する記事
⇒SerialPortコントロールの使用方法 :[SerialPort,Invoke]⇒SerialPortコントロールの使い方その3(外部装置からの垂れ流しデータ受信)
⇒SerialPortコントロールの使い方その4(データ受信時にイベントを発生させる)
⇒SerialPortコントロールの使い方その5(データ受信時及び、信号変化時にイベントを発生させる)
⇒SerialPortコントロールの使い方その6(ハンドシェィクによるデータ送受信)
コメント