DOBON.NET DOBON.NETプログラミング掲示板過去ログ

シリアル通信について

環境/言語:[OS:Win2000 Framework 1.1]
分類:[.NET]

いつも参考にさせて頂いています。
今、シリアル通信のソフトの作成をしていますが、200バイト程度の受信データを
受信する際、20秒近くかかってしまいます。これだけかかるのはおかしいと思いま
すがどこがおかしいのかわかりません。
APIの ReadFile関数を使用して1バイトずつ受信を行っています。
> すがどこがおかしいのかわかりません。

少し考えてみれば分かることと思いますが、具体的にどんな手順で受信しているのかが説明されなければ、どこがおかしいかを指摘するのは困難です。

> APIの ReadFile関数を使用して1バイトずつ受信を行っています。

少なくとも、1バイトずつの受信では効率が悪すぎます。

ClearCommError() で、受信バッファに何バイト溜まっているかを調べて、そのバイト数分を一括で ReadFile() するべきです。
>>APIの ReadFile関数を使用して1バイトずつ受信を行っています。
>
> 少なくとも、1バイトずつの受信では効率が悪すぎます。

自分も効率が悪いと思ったのですが、ReadFile関数では、指定したバイト数受信するまで
ブロックしてしまうため受信するバイト数が可変なためバイト数を指定して受信することができなかったのです。

> ClearCommError() で、受信バッファに何バイト溜まっているかを調べて、そのバイト数分を一括で ReadFile() するべきです。

ClearCommError()関数はしりませんでした。いろいろ調べてみたのですがどのように
使用したらよいのかわかりません。

Private Const BUFFER_SIZE As Integer = 4095
Private m_abytRcvData(BUFFER_SIZE) As Byte
Private m_intRcvSize As Integer = 0
Private mabtRxBuf As Byte()

'// 受信開始 //
While (Read(1) <> -1)
If m_intRcvSize = 0 Then
m_abytRcvData(m_intRcvSize) = mabtRxBuf(0)
m_intRcvSize += 1
ElseIf m_intRcvSize > 0 Then
m_abytRcvData(m_intRcvSize) = mabtRxBuf(0)
m_intRcvSize += 1
End If

'// 受信完了確認 //
If m_abytRcvData(m_intRcvSize - 1) = 10 Then
blnFlg = True
Exit While
End If

End While

'// 受信処理 //
Public Function Read(ByVal Bytes2Read As Integer) As Integer
Dim iReadChars, iRc As Integer

If Bytes2Read = 0 Then Bytes2Read = miBufferSize
If mhRS = -1 Then
Throw New ApplicationException( _
"Please initialize and open port before using this method")
Else
Try
'// 受信 //
ReDim mabtRxBuf(Bytes2Read - 1)
iRc = ReadFile(mhRS, mabtRxBuf, Bytes2Read, iReadChars, Nothing)
If iRc = 0 Then
' Read Error
Else
If iReadChars < Bytes2Read Then
Throw New IOTimeoutException("Timeout error")
Else
mbWaitOnRead = True
Return (iReadChars)
End If
End If
Catch Ex As Exception
' Others generic erroes
Throw New ApplicationException("Read Error: " & Ex.Message, Ex)
End Try
End If
End Function
> ClearCommError()関数はしりませんでした。いろいろ調べてみたのですがどのように
> 使用したらよいのかわかりません。

具体的にどの辺が分かりませんでしたか?

「分かりませんでした、コードどべっ」とされても困ります。

ClearCommError() の機能等については MSDN Library で説明されています。

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpfileio/html/_win32_clearcommerror.asp

また、P/Invoke の書式については PINVOKE.NET が参考になります。

http://www.pinvoke.net/

が、今のところ VB.NET 用の宣言は登録されていないようですね。
質問の仕方が悪くてすいません。

> ClearCommError() の機能等については MSDN Library で説明されています。
>
> http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpfileio/html/_win32_clearcommerror.asp

上記は見てみたのですが、自分にはどうしてよいかわからず以下のようにしてみたのですが受信バッファに何バイトあるかわかりませんでした。

<StructLayout(LayoutKind.Sequential, Pack:=1)> Private Structure COMSTAT
Public fCtsHold As Integer
Public fDsrHold As Integer
Public fRlsdHold As Integer
Public fXoffHold As Integer
Public fXoffSent As Integer
Public fEof As Integer
Public fTxim As Integer
Public fReserved As Integer
Public cbInQue As Integer
Public cbOutQue As Integer
End Structure

<DllImport("kernel32.dll")> Private Shared Function ClearCommError( _
ByVal hFile As Integer, ByVal lpErrors As Integer, _
ByRef lpCOMSTAT As COMSTAT) As Integer
End Function
-----------------------------------------------------------------------
Dim lpErrCode As Integer
Dim uComstat As COMSTAT

iRc = ClearCommError(mhRS, lpErrCode, uComstat)

ReDim mabtRxBuf(Bytes2Read - 1)
iRc = ReadFile(mhRS, mabtRxBuf, Bytes2Read, iReadChars, Nothing)

uComstat.cbInQue に受信バイト数が入ってくると思うのですが、実行すると
COMSTAT構造体には何もデータが入ってきません。
> uComstat.cbInQue に受信バイト数が入ってくると思うのですが、実行すると
> COMSTAT構造体には何もデータが入ってきません。

てことは、COMSTAT 構造体の参照が正しく渡されていない可能性が高いですね。

VB.NET の細かい文法は知りませんが

ByRef lpCOMSTAT As COMSTAT

はこれで正しいんですか?
■No11984に返信(渋木宏明(ひどり)さんの記事)
> てことは、COMSTAT 構造体の参照が正しく渡されていない可能性が高いですね。
>
> VB.NET の細かい文法は知りませんが
>
> ByRef lpCOMSTAT As COMSTAT
>
> はこれで正しいんですか?

あっているとは思うのですが…
いろいろ試しているのですがいまだ解決できません。
>>ByRef lpCOMSTAT As COMSTAT
>>
>>はこれで正しいんですか?
>
> あっているとは思うのですが…

新たに検索してみましたが

http://network.programming-in.net/articles/art9-1.asp?f=ClearCommError

に書かれている定義と異なっているようですよ。
■No11995に返信(渋木宏明(ひどり)さんの記事)
> >>ByRef lpCOMSTAT As COMSTAT
> >>
> >>はこれで正しいんですか?
>>
>>あっているとは思うのですが…
>
> 新たに検索してみましたが
>
> http://network.programming-in.net/articles/art9-1.asp?f=ClearCommError
>
> に書かれている定義と異なっているようですよ。
>

渋木宏明(ひどり)さんありがとうございました。受信データを一括で受信することが
できました。 定義が違っていました。

Declare Function ClearCommError Lib "kernel32" (ByVal hFile As Integer, ByRef lpErrors As Integer, ByRef lpStat As COMSTAT) As Integer

Structure COMSTAT
Dim fBitFields As Integer 'See Comment in Win32API.Txt
Dim cbInQue As Integer
Dim cbOutQue As Integer
End Structure
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板