-
標準コントロールのTimerコントロールとは異なり、タイマイベントを別スレッドとして起動する スレッドタイマの説明をします。
タイマイベントはSystem.Threadingの名前空間にある、Timerクラスで、 MSDNの説明によれば以下の様になっています。System.Threading.Timer について
<コンストラクター(複数ある中の今回利用のもの)> Public Sub New ( callback As TimerCallback, :TimerCallback を実行するメソッドを表すデリゲート state As Object, :コールバック メソッドで使用される情報を格納したオブジェクト または nullです。 dueTime As Integer, :前に遅延する時間 callback ミリ秒単位で呼び出されます。 指定 Timeout.Infinite 、タイマーが起動しないようにします。 0 を指定して、タイマーをすぐに開始します。 period As Integer :呼び出しの間の時間間隔 callback, 、(ミリ秒単位)。 指定 Timeout.Infinite 周期的なシグナル通知を無効にします。 ) <メソッド> Public Function Change ( dueTime As Integer, :時に指定されたコールバック メソッドを呼び出す前に遅延する時間数、 Timer (ミリ秒単位) が作成されました。 指定 Timeout.Infinite タイマーが再開されないようにします。 0 を指定して、タイマーをすぐに再開します。 period As Integer :コールバック メソッドの呼び出し間の時間間隔が指定されたときに、 Timer (ミリ秒単位) が作成されました。 指定 Timeout.Infinite 周期的なシグナル通知を無効にします。 ) As Boolean 戻り値:true の場合は、タイマーが正常に更新されました。それ以外の場合、 falseです。
今回の例としては、スレッドタイマを作成し、 TimerCallback イベントで 出力ウインドウに現在の時刻を表示する動作をします。
スレッドタイマの使い方
Imports System.Threading Imports System.Threading.Thread Public Class frmTimer2 'スレッドタイマ Private mtimer As System.Threading.Timer '''''' フォームロードイベント ''' Private Sub frmTimer2_Load(sender As Object, e As EventArgs) Handles Me.Load 'タイマコールバック関数 Dim timerDelegate As TimerCallback = New TimerCallback(AddressOf TimerEvent) '1000msecタイマ生成(コールバック関数の設定) mtimer = New Timer(timerDelegate, Nothing, 0, 1000) End Sub '''''' System.Threading.Timer からの呼び出しを処理するメソッド ''' ''' <param name="state">このデリゲートで呼び出されたメソッドに関連するアプリケーション固有の情報を格納するオブジェクト</param> Private Sub TimerEvent(ByVal state As Object) '出力ウインドウに時刻表示 Console.WriteLine("Time:" & Now.ToString("hh:mm:ss")) End Sub End Class実行させると、1000msec毎に関数 TimerEvent が呼び出され、出力ウインドウに現在の時刻が表示されることが確認できます。
そこで、以下のページの様にフォーム上のラベルに時刻を表示させてみようとしました。
・Timerコントロールの使い方 :[Timer,Interval]
しかし、思っていた様にラベルには時刻が表示されずに、以下の様なエラーが表示されてしまいました。
「有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'Label1' がアクセスされました。」スレッドタイマの使い方・エラーの出たフォーム上のラベルへの表示
Imports System.Threading Imports System.Threading.Thread Public Class frmTimer2 'スレッドタイマ Private mtimer As System.Threading.Timer '''''' フォームロードイベント ''' Private Sub frmTimer2_Load(sender As Object, e As EventArgs) Handles Me.Load 'タイマコールバック関数 Dim timerDelegate As TimerCallback = New TimerCallback(AddressOf TimerEvent) '1000msecタイマ生成(コールバック関数の設定) mtimer = New Timer(timerDelegate, Nothing, 0, 1000) End Sub '''''' System.Threading.Timer からの呼び出しを処理するメソッド ''' ''' <param name="state">このデリゲートで呼び出されたメソッドに関連するアプリケーション固有の情報を格納するオブジェクト</param> Private Sub TimerEvent(ByVal state As Object) ''出力ウインドウに時刻表示 'Console.WriteLine("Time:" & Now.ToString("hh:mm:ss")) 'ラベルに現在時刻表示 Me.Label1.Text = Now.ToString("hh:mm:ss") End Sub End Class「有効ではないスレッド間の操作...」エラーは、 あるスレッドから異なるスレッド上のコントロールにアクセスしようとしたことが原因でした。
つまりスレッドタイマの TimerEvent と、 フォームのラベルがあるスレッドとは全く別にスレッド上で動作していることになります。
これを解決するには、デリゲートという方法を使います。 デリゲートを使えば別スレッドからフォーム上のコントロールへのアクセスが出来る様になります。
デリゲートの方法ですがソースを見た方が分かりやすいと思いますので、 以下に示します。スレッドタイマの使い方・デリゲート宣言とInvoke関数
Imports System.Threading Imports System.Threading.Thread Public Class frmTimer2 'スレッドタイマ Private mtimer As System.Threading.Timer '''''' フォームロードイベント ''' Private Sub frmTimer2_Load(sender As Object, e As EventArgs) Handles Me.Load 'タイマコールバック関数 Dim timerDelegate As TimerCallback = New TimerCallback(AddressOf TimerEvent) '1000msecタイマ生成(コールバック関数の設定) mtimer = New Timer(timerDelegate, Nothing, 0, 1000) End Sub '''''' System.Threading.Timer からの呼び出しを処理するメソッド ''' ''' <param name="state">このデリゲートで呼び出されたメソッドに関連するアプリケーション固有の情報を格納するオブジェクト</param> Private Sub TimerEvent(ByVal state As Object) 'ラベルに現在時刻表示 Dim strDate As String = Now.ToString("hh:mm:ss") Invoke(New SetLabelTextDelegate(AddressOf SetLabelText), New Object() {strDate}) End Sub ' ラベル表示デリゲート宣言 Private Delegate Sub SetLabelTextDelegate(ByVal strText As String) '''''' ラベル表示 ''' ''' <param name="strText">表示文字列</param> Private Sub SetLabelText(ByVal strText As String) Label1.Text = strText End Sub End Classこのソースで一応ラベルへの表示は以下図の様に出来る様になりました。
ここで重要なのは、ラベル表示用関数のデリゲート宣言と Invoke 関数です。 デリゲート(delegate)という動詞には「委譲する、委任する」、名詞では「代理人」などという意味が有りますが、 デリゲートの呼び出し側からすれば、関数の引数を合わせて、デリゲートされたものを Invoke 関数で 呼出すだけのことになります。
デリゲートとして宣言されている中身の処理については、そちらままかせの感じになります。
デリゲートとして宣言された関数を Invoke で呼出してやれば、スレッドを超えて処理が可能になります。 さて、 Invoke ですがMSDNの説明では以下の様になっています。Public Function Invoke(method As System.Delegate, ParamArray args() As Object) As Object 概要: コントロールの基になるウィンドウ ハンドルを所有するスレッド上で、 指定した引数リストを使用して、指定したデリゲートを実行します。 パラメーター: method: args パラメーターに指定されている数および型と同じ数 および型のパラメーターをとるメソッドへのデリゲート。 args: 指定したメソッドに引数として渡すオブジェクトの配列。 メソッドが引数をとらない場合、このパラメーターは null になります。
関連する記事
⇒Timerコントロールの使い方 :[Timer,Interval]
⇒複数のTimerコントロールの使い方 :[Timer,Interval]
⇒スレッドタイマの使い方(イベント処理が時間が掛かる場合):[System.Threading.Timer,Delegate,Invoke]
PR -
指定された Decimal Double Long の値を、指定された桁で切り上げる関数です。
指定された値が正の場合は、有効桁数の10の累乗で割ったものを Math.Ceiling 関数で最小の整数値を求めて、更に累乗値を掛けてやります。 指定された値が負の場合は、有効桁数の10の累乗で割ったものを Math.Floor 関数で最小の整数値を求めて、更に累乗値を掛けてやります
テストプログラムの動作としては、Double値が「123456」で有効桁数が「3」の場合、「123456」を先ず「1000」で割って「123.456」となり Math.Ceiling 関数を通すことで「124.000」となり結果「124000」が関数戻り値となります。指定した精度の桁数に数値を切り上げ
''' ------------------------------------------------------------------------ '''''' 指定した精度の数値の切り上げ ''' ''' <param name="Val">丸め対象の倍精度浮動小数点数</param> ''' <param name="intUnit">戻り値の有効桁数の精度</param> '''切り上げられた数値。 ''' ------------------------------------------------------------------------ Public Function RoundUp(ByVal Val As Double, ByVal intUnit As Integer) As Double Dim dblPow As Double = System.Math.Pow(10, intUnit) If Val > 0 Then 'Ceiling:指定した倍精度浮動小数点数以上の数のうち、最小の整数値を返します Return System.Math.Ceiling(Val / dblPow) * dblPow Else 'Floor:指定した倍精度浮動小数点数以下の数のうち、最大の整数を返します Return System.Math.Floor(Val / dblPow) * dblPow End If End Function Public Function RoundUp(ByVal Val As Decimal, ByVal intUnit As Integer) As Decimal Dim decPow As Decimal = System.Math.Pow(10, intUnit) If Val > 0 Then 'Ceiling:指定した 10 進数以上の数のうち、最小の整数値を返します Return System.Math.Ceiling(Val / decPow) * decPow Else 'Floor:指定した 10 進数以下の数のうち、最大の整数を返します Return System.Math.Floor(Val / decPow) * decPow End If End Function Public Function RoundUp(ByVal Val As Long, ByVal intUnit As Integer) As Long Dim decPow As Decimal = System.Math.Pow(10, intUnit) If Val > 0 Then Return System.Math.Ceiling(Val / decPow) * decPow Else Return System.Math.Floor(Val / decPow) * decPow End If End Function '***** '仮にテストプログラム '***** Private Sub BtnRoundUp_Click(sender As Object, e As EventArgs) Handles BtnRoundUp.Click Try Dim decData As Decimal = 123456 Dim dblData As Double = 123456 Dim lngData As Long = 123456 Dim str As String = "" str &= "Decimal:" & decData.ToString & "-->" & RoundUp(decData, 3).ToString & vbCrLf str &= "Double :" & dblData.ToString & "-->" & RoundUp(dblData, 2).ToString & vbCrLf str &= "Long :" & lngData.ToString & "-->" & RoundUp(decData, 1).ToString & vbCrLf decData = -decData dblData = -dblData lngData = -lngData str &= "Decimal:" & decData.ToString & "-->" & RoundUp(decData, 3).ToString & vbCrLf str &= "Double :" & dblData.ToString & "-->" & RoundUp(dblData, 2).ToString & vbCrLf str &= "Long :" & lngData.ToString & "-->" & RoundUp(decData, 1).ToString & vbCrLf MsgBox(str) Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub
-
指定されたコピー元のバイト配列から、指定されたコピー先バイト配列に、右詰でコピーを行う関数です。
関数としては、コピー元の配列数がコピー先の配列数より多い場合は、コピー先のコピー開始位置を右にずらして配列数分までをコピーします。
また、コピー元の配列数がコピー先の配列数より少ない場合、コピー先の残りに指定のバイト値を埋めます。右詰でバイト配列のコピーを行う
''' ----------------------------------------------------------------------------- '''''' 右詰でバイト配列のコピーを行う。 ''' ''' <param name="srcArr">コピー元バイト配列</param> ''' <param name="desArr">コピー先バイト配列</param> ''' <param name="fillByte">指定バイトデータ(規定値:0x00)</param> '''コピー元のバイト数が、コピー先より小さい場合に、先頭から余った領域にバイトデータを埋める。 ''' ----------------------------------------------------------------------------- Public Sub CopyByteArrRight(ByVal srcArr As Byte(), ByVal desArr As Byte(), Optional ByVal fillByte As Byte = &H0) Dim idx As Integer If srcArr.Length = 0 Then '元の配列長が0の場合、指定バイトデータを埋める For idx = 0 To desArr.Length - 1 desArr(idx) = fillByte Next Else 'コピー先に収まるバイト数を計算 Dim copyBytes As Integer = srcArr.Length 'コピー元の長さ If srcArr.Length > desArr.Length Then 'コピー元の長さがコピー先の長さより大きい場合、コピー先の長さをコピー数にする copyBytes = desArr.Length End If 'コピー元の長さで、コピー先の開始位置を右にずらして、左からコピー Array.Copy(srcArr, 0, desArr, desArr.Length - copyBytes, copyBytes) 'コピー元のバイト数が、コピー先のバイト数より小さい場合、指定バイトデータを埋める If copyBytes < desArr.Length Then For idx = 0 To (desArr.Length - copyBytes) - 1 desArr(idx) = fillByte Next End If End If End Sub '***** '仮にテストプログラム '***** Private Sub CopyArrRight_Click(sender As Object, e As EventArgs) Handles CopyArrRight.Click Try '配列宣言 Dim byteArr(10) As Byte 'コピー元 Dim byteArr2(12) As Byte 'コピー先 'コピー元配列を「&H55」で埋める FillByteArr(byteArr, &H55) ' 'コピー元からコピー先へコピーする CopyByteArrRight(byteArr, byteArr2, &HAA) '結果の表示 Dim str As String = "" For i = 0 To byteArr2.Length - 1 str &= String.Format("byteArr2[{0}] = {1}", i, byteArr2(i).ToString("X")) & vbCrLf Next MsgBox(str) Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub関連する記事
⇒配列の使い方について(Dim, Redim)
⇒配列の使い方の注意点について(コピー, Clone)
⇒配列の範囲指定によるコピー(Array.Copy, Skip, Take)
-
指定されたコピー元のバイト配列から、指定されたコピー先バイト配列に、左詰でコピーを行う関数です。
関数としては、コピー元の配列数がコピー先の配列数より多い場合は、コピー先の配列数分までをコピーします。
また、コピー元の配列数がコピー先の配列数より少ない場合、コピー先の残りに指定のバイト値を埋めます。左詰でバイト配列のコピーを行う
''' ----------------------------------------------------------------------------- '''''' 左詰でバイト配列のコピーを行う。 ''' ''' <param name="srcArr">コピー元バイト配列</param> ''' <param name="desArr">コピー先バイト配列</param> ''' <param name="fillByte">指定バイトデータ(規定値:0x00)</param> '''コピー元のバイト数が、コピー先より小さい場合に、余った領域に埋めるバイトデータを埋める。 ''' ----------------------------------------------------------------------------- Public Sub CopyByteArrLeft(ByVal srcArr As Byte(), ByVal desArr As Byte(), Optional ByVal fillByte As Byte = &H0) Dim idx As Integer If srcArr.Length = 0 Then 'コピー元の配列長が0の場合、指定バイトデータを埋める For idx = 0 To desArr.Length - 1 desArr(idx) = fillByte Next Else 'コピー先に収まるバイト数を計算 Dim copyBytes As Integer = srcArr.Length 'コピー元の長さ If srcArr.Length > desArr.Length Then 'コピー元の長さがコピー先の長さより大きい場合、コピー先の長さをコピー数にする copyBytes = desArr.Length End If '左からコピー Array.Copy(srcArr, desArr, copyBytes) 'コピー元のバイト数が、コピー先のバイト数より小さい場合、後ろに指定バイトデータ埋める If copyBytes < desArr.Length Then For idx = copyBytes To desArr.Length - 1 desArr(idx) = fillByte Next End If End If End Sub '***** '仮にテストプログラム '***** Private Sub CopyArrLeft_Click(sender As Object, e As EventArgs) Handles CopyArrLeft.Click Try '配列宣言 Dim byteArr(10) As Byte 'コピー元 Dim byteArr2(12) As Byte 'コピー先 'コピー元配列を「&H55」で埋める FillByteArr(byteArr, &H55) ' 'コピー元からコピー先へコピーする CopyByteArrLeft(byteArr, byteArr2, &HAA) '結果の表示 Dim str As String = "" For i = 0 To byteArr2.Length - 1 str &= String.Format("byteArr2[{0}] = {1}", i, byteArr2(i).ToString("X")) & vbCrLf Next MsgBox(str) Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub関連する記事
⇒配列の使い方について(Dim, Redim)
⇒配列の使い方の注意点について(コピー, Clone)
⇒配列の範囲指定によるコピー(Array.Copy, Skip, Take)
-
最近では通信と言えば、BlueTooth, USBやネットでの通信が当たり前で、 シリアルポート(RS232C)を使って外部装置と通信することも少なくなりました。 しかし稀に外部装置との接続をシリアル通信(調歩同期)で行うこともありますので 今回はシリアルポートを使う方法を説明します。
SerialPortコントロールを使うには、フォーム上にツールボックスからSerialPortを選択し貼り付けます。 以下の図は、SerialPortコントロールを貼り付けた後の様子です。
MSDNの説明によれば以下の様になっています。(代表的なものを示しています。青色は今回使用しているものです。)SerialPort コントロール・について
<プロパティ> ・PortName :通信用のポートを取得または設定します。 このポートには、使用可能なすべての COM ポートが含まれますが、 これに限定されるわけではありません。 ・BaudRate :シリアル ボー レートを取得または設定します。 ・BytesToRead :受信バッファー内のデータのバイト数を取得します。 ・BytesToWrite:送信バッファー内のデータのバイト数を取得します。 ・CtsHolding :Clear To Send ラインの状態を取得します。 ・DsrHolding :DSR (Data Set Ready) シグナルの状態を取得します。 ・IsOpen :SerialPort オブジェクトの開いている状態または 閉じた状態を示す値を取得します。 ・Parity :パリティ チェック プロトコルを取得または設定します。 ・DtrEnable :シリアル通信中に、DTR (Data Terminal Ready)シグナルを 有効にする値を取得または設定します。 ・DataBits :バイトごとのデータ ビットの標準の長さを取得または設定します。 ・StopBits :バイトごとのストップ ビットの標準の数を取得または設定します。 ・ReadBufferSize:SerialPortの入力バッファーのサイズを取得または設定します。 ・ReadTimeout :読み取り操作が完了していないときに、 タイムアウトになるまでのミリ秒数を取得または設定します。 <メソッド> ・Close() :ポート接続を閉じ、IsOpenプロパティを false に設定し、 内部 Stream オブジェクトを破棄します。 ・Open() :新しいシリアル ポート接続を開きます。 ・Read(Byte(), Int32, Int32): SerialPort の入力バッファーから複数のバイトを読み取り、 読み取ったバイトを指定したオフセットでバイト配列に書き込みます。 ・ReadByte() :SerialPort の入力バッファーから、同期で 1 バイトを読み取ります。 ・Write(Byte(), Int32, Int32): バッファーのデータを使用して、指定したバイト数をシリアル ポートに書き込みます。 <イベント> ・DataReceived:SerialPort オブジェクトによって表される ポートを介してデータが受信されたことを示します。
今回のプログラムをテストするためには外部装置か、もう一台別のPCが必要になりますが、 そんなことをしなくてもデバッグができるソフト(ドライバ)が在ります。
com0com というドライバで、PC上に仮想シリアルポートを2個作成し、 その2個をループバックできる様に仮想的に接続できるという優れものです。 以下のリンク先でソフトをダウンロードしてインストールしてみて下さい。 (尚、もう一台のPCなどがあれば必要ありませんが)
⇒http://sourceforge.net/projects/com0com/
このドライバをインストールすると、私のPCではCOM7、COM8が追加で生成されました。
インストール後のPCの状況を以下の図に示します。
COM7側をテスト用送信プログラムとするのですが、 通信テスト用に以下のフリーソフトを使いました。
「のん」さんといわれる方が作成された「RS232Cテストツール」です。
以下のサイトにアクセスすれば、ダウンロードできます。
⇒http://nonsoft.la.coocan.jp/Download/Rs232cTool/index.html
この方はいろいろなフリーソフトを作成されている様です。使えるソフトが満載です。
インストール後の「RS232Cテストツール」を動作させている様子を以下に示します。
では実際のプログラムを以下に示しますので、説明します。
フォームにSerialPort、TextBox、Buttonを各1個ずつ貼り付けます。
フォームロードイベントでは、シリアルポートの設定を行い、ポートのオープン処理を行います。 ポートの設定は、ポート名「COM8」、通信速度「9600BPS」、パリティ「無し」、データビット数「8」、 ストップビット「1Bit」です。
SerialPortの受信イベントにより、受信バッファー内のデータのバイト数分のバイト配列を宣言し SerialPortのReadコマンドで受信バイトを全て読込みます。
読込んだバイト配列を文字列に変換し、TextBoxに設定します。
プログラム的には出来ている様な感じがしますが、これをデバッグモードで実行してみます。SerialPortコントロールの使い方(最初)
Public Class frmSerial '''''' フォームロードイベント ''' Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load With SerialPort1 'シリアルポートの設定 .PortName = "COM8" 'ポート名 .BaudRate = 9600 '通信速度指定 .Parity = IO.Ports.Parity.None 'パリティ指定 .DataBits = 8 'ビット数指定 .StopBits = IO.Ports.StopBits.One 'ストップビット指定 'シリアルポートのオープン .Open() End With End Sub '''''' フォームクローズイベント ''' Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed 'シリアルポートのクローズ SerialPort1.Close() End Sub '''''' シリアルポート受信イベント ''' Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived 'データ受信 Dim arrByte As Byte() = New Byte(SerialPort1.BytesToRead - 1) {} '受信バッファー内のデータのバイト数分 'SerialPort の入力バッファーからバイト数を読み取り SerialPort1.Read(arrByte, 0, arrByte.GetLength(0)) '受信バイト配列を文字列変換 Dim str As String = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(arrByte) 'テキストBOXに文字列表示関数 DisplayText(str) End Sub '''''' テキストBOXに文字列表示関数 ''' ''' <param name="strDisp">表示文字列</param> Private Sub DisplayText(ByVal strDisp As String) 'テキストBOXに文字列を追加 Me.TextBox1.Text &= strDisp End Sub '''''' [Clear]ボタン処理 ''' Private Sub btnClear_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnClear.Click Me.TextBox1.Text = "" End Sub End Classこのプログラムをデバッグモードで実行させて待機状態にして置き、 先ほどの「RS232Cテストツール」を実行し、送信TEXTにデータを設定し、送信します。 送信ボタン押下した時に、今回のプログラムのTextBoxにデータが表示されるはずですが 実際は以下の様なエラーが発生しました。
スレッド間のアクセスが起きてエラーが発生した様です。
そこで調べたところ、MSDNの説明によれば、
DataReceived イベントは、データが SerialPort オブジェクトから受信されたときにセカンダリ スレッドで発生します。 メインの Form または Control で要素を変更する必要がある場合は、 Invoke を使用して変更要求をポストバックします。これにより、適切なスレッドで処理が実行されるようになります。
とあります。結局、DataReceivedイベントは別スレッドなので、フォームのコントロールなどにアクセスする場合は Invoke等を使用しなさいとのことの様です。
プログラムを以下の様に書き換えました。SerialPortコントロールの使い方(正常処理)
Public Class frmSerial '''''' フォームロードイベント ''' Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load With SerialPort1 'シリアルポートの設定 .PortName = "COM8" 'ポート名 .BaudRate = 9600 '通信速度指定 .Parity = IO.Ports.Parity.None 'パリティ指定 .DataBits = 8 'ビット数指定 .StopBits = IO.Ports.StopBits.One 'ストップビット指定 'シリアルポートのオープン .Open() End With End Sub '''''' フォームクローズイベント ''' Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed 'シリアルポートのクローズ SerialPort1.Close() End Sub '''''' シリアルポート受信イベント ''' Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived 'データ受信 Dim arrByte As Byte() = New Byte(SerialPort1.BytesToRead - 1) {} '受信バッファー内のデータのバイト数分 'SerialPort の入力バッファーからバイト数を読み取り SerialPort1.Read(arrByte, 0, arrByte.GetLength(0)) 'デリゲート生成 Dim dlg As New DisplayTextDelegate(AddressOf DisplayText) '受信バイト配列を文字列変換 Dim str As String = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(arrByte) 'デリゲート関数をコールする Me.Invoke(dlg, New Object() {str}) End Sub 'Invokeメソッドで使用するデリゲート宣言 Delegate Sub DisplayTextDelegate(ByVal strDisp As String) '''''' テキストBOXに文字列表示関数 ''' ''' <param name="strDisp">表示文字列</param> Private Sub DisplayText(ByVal strDisp As String) 'テキストBOXに文字列を追加 Me.TextBox1.Text &= strDisp End Sub '''''' [Clear]ボタン処理 ''' Private Sub btnClear_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnClear.Click Me.TextBox1.Text = "" End Sub End Class
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コントロールの使い方その2
⇒SerialPortコントロールの使い方その3(外部装置からの垂れ流しデータ受信)
⇒SerialPortコントロールの使い方その4(データ受信時にイベントを発生させる)
⇒SerialPortコントロールの使い方その5(データ受信時及び、信号変化時にイベントを発生させる)
⇒SerialPortコントロールの使い方その6(ハンドシェィクによるデータ送受信)
おすすめ本