使用 VB.net 手动从串行端口读取
我需要使用 RS232 连接到 AND GF 3000 电子秤。我已经使用 HyperT 和 AND 自己的程序测试了连接,它正在工作。现在我正在创建一个 VB 应用程序来读取该内容,到目前为止它实际上可以工作。然而,它在几个部分有很多错误,所以我想优化它。
我之前的读取命令使用:
Private Sub mscport_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles mscport.DataReceived
Dim tmpBuf As String
tmpBuf = mscport.ReadLine
End Sub
这不是我正在使用的完整版本,但在其他方面是有效的。但是,退出并重新连接(我正在使用 Windows 窗体控件)会出现“由于线程退出或应用程序请求,I/O 操作已中止”异常。环顾网络,我从迪克·格里尔那里找到了原因:http://www.pcreview.co.uk/forums/serial-port-error-o-operation-has-been-已中止,因为-either-thread-exit-application-request-t2781073.html:
几乎可以肯定,这意味着 SerialPort 对象 尝试在端口被占用后完成对 ReadLine 的调用 关闭。发生这种情况是因为之间缺乏同步 可能导致端口关闭的UI事件以及后台线程 在执行实际 ReadFile 的 SerialPort 对象中 操作(这作为委托中 ReadLine 的结果执行)。
ReadLine 的问题以及我不使用它的原因是 它会阻塞直到行终止条件发生——这 关闭端口后可能会好起来。因此例外。
我更喜欢简单地在静态或类级别缓冲我自己的数据 变量(所有 ReadExisting 并将新数据附加到缓冲区),以及 测试该缓冲区中的 vbCrLf 终止字符。如果 找到 vbCrLf(InStr 或 Substring,您的选择),然后调用 委托处理并显示缓冲区中的数据。记得 在处理并显示其内容后清除该缓冲区。 如果您这样做,异常应该得到解决。
迪克
以前我的应用程序使用 ReadExisting 而不是 ReadLine 进行串行连接。后来,当使用USB串行电缆时,ReadExisting不起作用,所以我改用ReadLine。我想使用USB线,所以我需要找到一种方法来替代ReadLine。现在我对串行端口没有什么大的震动,但我已经成功地编写了一个几乎可以工作的代码,使用 ReadChar 替换了 ReadLine,如下所示:
Private Sub mscport_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles mscport.DataReceived
Dim tmpbuf As String
Dim bytebuffer(17) As Byte
Dim count As Integer = 17
Try
While count > 0
bytebuffer(17 - count) = mscport.ReadChar
'If bytebuffer(17 - count) = vbCrLf Then
'End If
'tmpBuf = tmpBuf & mscport.ReadExisting
count = count - 1
End While
Catch ex As InvalidOperationException
MessageBox.Show(ex.Message)
Catch ex As UnauthorizedAccessException
MessageBox.Show(ex.Message)
Catch ex As System.IO.IOException
MessageBox.Show(ex.Message)
End Try
tmpbuf = tmpbuf & System.Text.Encoding.ASCII.GetString(bytebuffer, 0, 17)
'tmpBuf = bytebuffer.ToString()
ReceiveData(tmpbuf)
End Sub
新代码的问题:
IO 异常仍然存在。有时打开应用程序时会触发。即使有所有这些异常,它仍然没有捕获。
有时收到的数据都是混乱的。例如,ST 0009.80 g 显示为 .80 gST 0009。数据以 CrLf 结尾,所以我仍在考虑如何在显示之前重新排列它。
我知道有更好的方法来做到这一点,我只是想不出一个,或者也许我搜索得不够。
I need to connect to an AND GF 3000 e-scale using RS232. I've tested the connection using HyperT and AND's own program and it's working. Now I'm creating a VB app to read the thing and so far it's actually working. However it's quite buggy in several parts so I want to optimize the thing.
My previous read command uses:
Private Sub mscport_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles mscport.DataReceived
Dim tmpBuf As String
tmpBuf = mscport.ReadLine
End Sub
which is not the full version of what I'm using but otherwise works. However, exiting and reconnecting (I'm using Windows Form Controls) turns up that "The I/O operation has been aborted because of either a thread exit or an application request" exception. Looking around the 'net I found the reason so from Dick Grier over here: http://www.pcreview.co.uk/forums/serial-port-error-o-operation-has-been-abortedbecause-either-thread-exit-application-request-t2781073.html:
What this means, almost certainly, is that the SerialPort object
attempted to complete the call to ReadLine after the port has been
closed. This can happen because of the lack of synchronization between
UI events which may cause the port to close, and the background thread
in the SerialPort object that is performing the actual ReadFile
operation (this executes as a result of ReadLine in your delegate).The problem with ReadLine, and the reason that I DO NOT use it, is
that it blocks until the the line terminating condition occurs -- this
may be well AFTER you have closed the port. Thus the exception.I prefer simply buffering my own data in a Static or class-level
variable (all ReadExisting and append new data to the buffer) , and
testing that buffer for the vbCrLf terminating characters. If the
vbCrLf is found (InStr or Substring, your choice), then call a
delegate to process and display the data in the buffer. Remember to
clear this buffer AFTER you have processed and displayed its content.
If you do this, the exception should be resolved.Dick
Previously my app uses ReadExisting instead of ReadLine for serial-serial connection. Later, when using USB-serial cable, ReadExisting didn't work so I used ReadLine instead. I want to use the USB cable so I need to find a way to replace ReadLine. Now I'm no great shakes at serial ports but I've managed to make an almost working code replacing the ReadLine using ReadChar which is here:
Private Sub mscport_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles mscport.DataReceived
Dim tmpbuf As String
Dim bytebuffer(17) As Byte
Dim count As Integer = 17
Try
While count > 0
bytebuffer(17 - count) = mscport.ReadChar
'If bytebuffer(17 - count) = vbCrLf Then
'End If
'tmpBuf = tmpBuf & mscport.ReadExisting
count = count - 1
End While
Catch ex As InvalidOperationException
MessageBox.Show(ex.Message)
Catch ex As UnauthorizedAccessException
MessageBox.Show(ex.Message)
Catch ex As System.IO.IOException
MessageBox.Show(ex.Message)
End Try
tmpbuf = tmpbuf & System.Text.Encoding.ASCII.GetString(bytebuffer, 0, 17)
'tmpBuf = bytebuffer.ToString()
ReceiveData(tmpbuf)
End Sub
The problem with the new code:
The IO exception is still there. Sometimes it triggers when opening the app. Even with all that exceptions it still didn't catch.
The Data sometimes get received all jumbled up.For example, ST 0009.80 g is displayed as .80 gST 0009. The data ends with a CrLf so I'm still thinkking on how to rearrange it before displaying.
I know there's a better way to do this, I just couldn't think of one, or maybe I'm not searching enough.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论