VB.Net Serial Comms问题让我疯狂 [英] VB.Net Serial Comms Problem driving me nuts

查看:102
本文介绍了VB.Net Serial Comms问题让我疯狂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,来自Oz的问候:-)



我有一个我以前在VB6(Enterprise)中写过的应用程序。它涉及与RS232设备通信并接收由传统STX / ETX封装的数据包(大小不一)。

现在我需要为应用程序添加一些新功能决定使用VB.Net(VS2010)重写它。

我的问题是DataReceived事件中出现的数据格式不正确或脱节。

例如我创建了一个小的测试程序来演示这种行为,代码如下所示。

如果我使用终端程序(RealTerm)发送标准的'Hello World',我在调试窗口中收到的是....



H

ello

世界



我尝试将Thread.Sleep(100)命令设置为DataReceived事件中的第一行,这缓解了此示例中的问题,但从长远来看,这是不够的,因为数据长度最多可达10行14个字符每。或者它可能只是一个14字符线。将睡眠设置得更高可能会导致下一包数据出现问题。



查看或等待ETX不是一种选择,因为它可能无法到达并且在此如果要丢弃数据包,并保证下一个数据包与包含ETX的数据包相同。基本上有一些检查,如果没有完全收到数据,它会再次发送。



希望有人可以帮我这个。





我的测试编程列表如下......

一个带文本框,多行打开,滚动条的简单表格。



Hi there all, greetings from Oz :-)

I have an application I wrote sometime ago in VB6 (Enterprise). It involves talking to a RS232 device and receiving packets of data (of varying size) that are encapsulated by the traditional STX/ETX.
Now that I need to add a few new features to the application I have decided to rewrite it using VB.Net (VS2010).
My problem is that the data is appearing at the DataReceived Event is malformed or disjointed.
For example I have created a small test program to demonstrate this behavior, code listed below.
If I use a terminal program (RealTerm) to send the standard 'Hello World' what I receive in the debug window is ....

H
ello
World

I have tried setting a Thread.Sleep(100) command as the first line in the DataReceived event, this alleviates the problem in this example but in the long term it would not suffice as the data length varies up to 10 lines of 14 chars each. Or it could be just one 14 char line. Setting the sleep even higher may cause issues with the next packet of data.

Looking or waiting for the ETX is not an option either as it may not arrive and in this case the packet is to be discarded and its guaranteed that the next packet will be the same packet with the ETX included. Essentially there is some checking and if the data is not completely received it is sent again.

Hoping someone can assist me with this.


My test programming listing below ...
A simple form with a textbox, multiline on, scrollbars vert.

Public Class frmMain

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

        With rs232
            .BaudRate = 4800
            .PortName = "COM6"
            .StopBits = IO.Ports.StopBits.One
            .Parity = IO.Ports.Parity.None
            .DataBits = 8
            rs232.Open()
        End With


    End Sub

    Private Sub rs232_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles rs232.DataReceived

        Dim strBuffer As String
        CheckForIllegalCrossThreadCalls = False

        strBuffer = rs232.ReadExisting
        Debug.Print(strBuffer)
        If InStr(strBuffer, Chr(2)) Then rs232.Write("#")

        txtData.Text = txtData.Text & strBuffer & vbCrLf



    End Sub

End Class





干杯



Mike S



Cheers

Mike S

推荐答案

基本上,你不能只看一下你那时收到的数据 - 但它非常非常不可能完成:你通常会为每个角色获得一个DataReceived事件,因为它会进入,特别是在这样的低速时。



相反,建立一个包含所有数据的缓冲区,然后解析它,在它们进来时删除检测到的数据包。

所以当你得到一个接收事件,在当前数据的末尾添加接收的数据,然后检查数据以STX开头并丢弃直到它。如果您仍有数据,请查找ETX。如果它不在那里,什么也不做。

如果是的话,取下整个STX ... ETX包,然后处理它。



(如果ETX损坏,你可能想要添加一些计时器或类似的东西扔掉垃圾)
Basically, you can't just look at the data you receive that time - but it is very, very unlikely to be complete: you would normally get a DataReceived event for each character or so as it comes in, especially at a low speed like that.

Instead, build up a buffer with all the data, and then parse that, removing the detected packets as they come in.
So when you get a receive event, add the received data on the end of the current data, then check the data for "starts with STX" and discard until it does. If you still have data, look for an ETX. If it isn't there, do nothing.
If it is, take off the whole STX...ETX packet, and process it.

(You'll probably want to add some timer or similar to throw away junk if the ETX is corrupted, as well)


感谢OriginalGriff。



没有完成但是由于你的建议,我已经跨过了最大的障碍。我有串口通信排序。我仍然需要更多地使用数据,但现在应该是一个非问题。下面列出的是我的概念证明代码。



Thanks OriginalGriff.

By no means finished but thanks to your advice I have stepped over the biggest hurdle. I have the serial comms sorted. I still have to do heaps more with the data but that should be a non-issue now. Listed below is my proof of concept code.

Public Class frmMain

    'Dim strRawBuffer As String
    Dim strBuffer As String
    'Dim strRealData As String = ""
    'Dim strRawData As String

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

        With rs232
            .BaudRate = 4800
            .PortName = "COM6"
            .StopBits = IO.Ports.StopBits.One
            .Parity = IO.Ports.Parity.None
            .DataBits = 8
            rs232.Open()
        End With

    End Sub

    Private Sub rs232_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles rs232.DataReceived

        '// Pass received data to processing function
        ProcessData(rs232.ReadExisting)

    End Sub

    Private Sub ProcessData(ByVal data)

        CheckForIllegalCrossThreadCalls = False

        For i = 1 To data.Length

            If Mid(data, i, 1) = Chr(3) Then
                ' // we've reached the end of the data packet, deal with it.
                Debug.Print(strBuffer)
                txtData.Text = strBuffer & txtData.Text
                strBuffer = ""
            ElseIf Mid(data, i, 1) = Chr(2) Then
                '// The previous packet maybe missing an ending (ETX) so discard it and start again
                '// Send the # char to confirm connection and tell the unit to keep sending
                rs232.Write("#")
                strBuffer = "" '// clear
            Else
                ' // Keep building the string
                strBuffer &= Mid(data, i, 1)
                '// look out for connection string device
                If InStr(strBuffer, "%T") Then
                    Debug.Print("Connected....")
                    strBuffer = ""
                    Exit Sub
                End If
            End If
        Next

    End Sub
    Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click

        '// Clear the textbox
        txtData.Clear()

    End Sub

    Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click

        '// Request connection, the device will answer back with 
        rs232.Write("%T")

    End Sub
End Class


这篇关于VB.Net Serial Comms问题让我疯狂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆