C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: serialPortの受信が遅い


(過去ログ 109 を表示中)

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■64865 / inTopicNo.1)  serialPortの受信が遅い
  
□投稿者/ tonn (8回)-(2013/01/18(Fri) 14:20:03)

分類:[VB.NET/VB2005 以降] 

VB2005でserialPortを使った232C通信のプログラムで問題があり質問させて頂きます。

・ざっくりの仕様
自社製品との通信で、パワーオン時製品から送信される特定文字列を受信したら"OK"+0x0dを返す。
製品との接続はUSBで、FTDIの仮想シリアルドライバを使用。
通信設定は9600bps,データ8bit,Stop 1bit,パリティー無し、ハード制御無し

・問題点
一応文字列受信及びOK返信はできるが、反応が異常に遅く装置側がタイムアウトしてしまう。

・備考
フリーウェアのSerialDebugToolを実機の代わりにして同文字列を送信すると問題無いスピードで反応する。
逆にSerialDebugToolと実機で、SerialDebugToolで文字列受信及び手作業でOK返信するとこちらも問題無し。
下のソースのように受信処理内で1バイト毎にTextBoxに表示していますが、それを見てると実機相手の場合は受信が遅く、ランダムに間が空くようです。

・ソース

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        SerialPort1.NewLine = vbCr  '文字列読み込みの終端を 0x0d 指定
        SerialPort1.ReceivedBytesThreshold = 1  '1byte受信毎にイベント発生
        
    End Sub

'受信スタート
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnKisyumei.Click
        If SerialPort1.IsOpen = False Then
            MsgBox("ポートはクローズされています")
            Exit Sub
        End If

        TextBox1.Clear()
        Array.Clear(rBuf, 0, UBound(rBuf))	'受信バッファクリア
        loc = 0	'受信配列を先頭に
        rCnt = 4	'受信バイト数4に
        tEnd = False	'受信終了フラグ Falseに
        TextBox1.Text = "コード受信待ち、装置の電源を入れて下さい" + Chr(13) + Chr(10)
        TextBox1.Text = TextBox1.Text + "<-" + Chr(13) + Chr(10)

        trFlg = "PUP"	'動作種別をパワーアップに
    End Sub

'受信からTextBox1を使うためのDelegate    
Delegate Sub AddDataDelegate(ByVal str As String)
    Private Sub AddData(ByVal str As String)
        TextBox1.Text = TextBox1.Text + str
    End Sub

'受信処理
    Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        Dim strDataReceived As String
        Dim tmpBuf(5) As Byte
        Dim add As New AddDataDelegate(AddressOf AddData)

        Try
            SerialPort1.Read(tmpBuf, 0, 1)
        Catch ex As Exception
            strDataReceived = ex.Message
        End Try
        
        rBuf(loc) = tmpBuf(0)
        TextBox1.Invoke(add, rBuf(loc).ToString("X") + ",")
        loc = loc + 1
        jusin()
    End Sub

'受信内の処理
    Private Sub jusin()
        Dim add As New AddDataDelegate(AddressOf AddData)

        Select Case trFlg
            Case "PUP"
                If loc >= rCnt Then
                    Dim i, j As Integer
                    Dim jFlg As Boolean = False
                    Dim s As String
                    Dim tmpB(3) As Byte

                    For i = 0 To loc
                        For j = 0 To 3
                            tmpB(j) = rBuf(i + j)
                        Next
                        s = System.Text.Encoding.ASCII.GetString(tmpB)
                        If s = "abcd" Then '文字列"abcd"受信確認
                            s = "OK"
                            SerialPort1.WriteLine(s)	'"OK"送信
                            trFlg = ""
                            TextBox1.Invoke(add, Chr(13) + Chr(10) + "->" + Chr(13) + Chr(10) + s)
                            jFlg = True
                            Exit For
                        End If
                    Next
                    If jFlg = False Then
                        Exit Sub
                    End If
                    
                End If
'ケース文の他の処理は省略
            Case "VR0"
                
            Case "WMS"
                
            Case "RMS"
                
        End Select
    End Sub

以上よろしくお願いします。

引用返信 編集キー/
■64869 / inTopicNo.2)  Re[1]: serialPortの受信が遅い
□投稿者/ Azulean (82回)-(2013/01/18(Fri) 23:00:58)
一点確認なのですが、DataReceived イベントで 1 バイトしか読み込まないのはなぜでしょうか?

http://msdn.microsoft.com/ja-jp/library/system.io.ports.serialport.datareceived.aspx より:
> DataReceived イベントは、受信されたバイトごとに発生するとは限りません。
引用返信 編集キー/
■64872 / inTopicNo.3)  Re[1]: serialPortの受信が遅い
□投稿者/ オショウ (58回)-(2013/01/19(Sat) 09:45:21)
あくまで参考コード

Public Sub OnReceive(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)

Dim dev As SerialPort
Dim sz As String

dev = DirectCast(sender, SerialPort)

If e.EventType = SerialData.Chars Then
sz = devSerial.ReadTo(vbCr)
If sz <> String.Empty Then
RaiseEvent ReceiveData(sz)
End If
End If

End Sub

デリミタとして、0x0d が、必ず受信データの最後にあるなら、それを受信するまで待って
一気に読み出した方が早い。

あと、OnReceive イベントは、データ受信以外でも発生する(信号線の変化)為、イベント
が何で発生したのか、判断してやる必要がある。

以上。
引用返信 編集キー/
■64880 / inTopicNo.4)  Re[2]: serialPortの受信が遅い
□投稿者/ tonn (9回)-(2013/01/19(Sat) 16:52:08)
Azulean様
オショウ様

ありがとうございます。

>一点確認なのですが、DataReceived イベントで 1 バイトしか読み込まないのはなぜでしょうか?

この箇所はアスキー文字列なのですが、他にHEXデータで送られてくる(頭にデータ数が付く)データもあり、できるだけ共通の処理にしたいと思いこういった処理にしていました。

>DataReceived イベントは、受信されたバイトごとに発生するとは限りません。
>あと、OnReceive イベントは、データ受信以外でも発生する(信号線の変化)為、イベント
>が何で発生したのか、判断してやる必要がある。

そうですね、この点が分かっていなかったようです。
マイコンの受信割り込みと同じようなものと考えていました。
SerialDebugToolと実機で同一データでも動作が異なるのは信号線関係のように見えますがまだ調べていません。

それで、その後この部分に関してはオショウさんの言われるように文字列読み込みに変えたところ問題なく動くようになりました。

HEX受信部分については、タイマーを併用してやることで一応動いています。
無駄な待ち時間が発生するのであまりいい処理とは思わないですが、安定してますしそう処理時間が問題になるソフトではないのでこれでいけそうです。

どうもありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -