简体   繁体   English

如何从vb.net的串行端口读取数据?

[英]How to read data from serial port in vb.net?

I made a class and there is this sub named SendUSSD, when this is called it sends a ussd code like *123# to a COM port where a gsm mobile is connected. 我做了一个类,有一个名为SendUSSD的子类,当它被调用时,它会向连接了gsm mobile的COM端口发送一个* 123#之类的ussd代码。 This ussd is supposed to return the mobile balance. 此usdd应该返回流动余额。

If IsOpen = True Then 'checks if the port is open
            SMSPort.WriteLine("AT+CUSD=1,""*123#""" vbCr) 'this sends the ussd code
            Form1.TextBox2.Text = SMSPort.ReadLine().ToString() 'this shows the response
End If

Now the problem is sometimes I get the full response like "Your current balance is so and so". 现在的问题是有时我会得到完整的答复,例如“您的当前余额如此之高”。 But, most of the time I get a part of the message like "Your curr". 但是,大多数情况下,我会收到诸如“您的curr”之类的消息。 My guess is that it takes some time to get the response, so how do I make this Form1.TextBox2.Text = SMSPort.ReadLine().ToString() line wait until the last character which is a full-stop to appear and then execute the line? 我的猜测是,获取响应需要一些时间,因此如何使此Form1.TextBox2.Text = SMSPort.ReadLine()。ToString()行等到最后一个出现句号的字符,然后再显示执行行?

im using this class to connect com ports. 即时通讯使用此类连接com端口。

'connect like this
Public comm As New CommunicationManager
comm.Parity = "None"
    comm.StopBits = "One"
    comm.DataBits = "8"
    comm.BaudRate = "38400"
    comm.PortName = comport_ismi
    comm.OpenPort()

and the class 和班级

    Imports System.Text
    Imports System.Drawing
    Imports System.IO.Ports
    Imports System.Windows.Forms

Public Class CommunicationManager
#Region "Manager Enums"
    ''' <summary>
    ''' enumeration to hold our transmission types
    ''' </summary>
    Public Enum TransmissionType
        Text
        Hex
    End Enum

    ''' <summary>
    ''' enumeration to hold our message types
    ''' </summary>
    Public Enum MessageType
        Incoming
        Outgoing
        Normal
        Warning
        [Error]
    End Enum
#End Region

#Region "Manager Variables"
    'property variables
    Private _baudRate As String = String.Empty
    Private _parity As String = String.Empty
    Private _stopBits As String = String.Empty
    Private _dataBits As String = String.Empty
    Private _portName As String = String.Empty
    Private _transType As TransmissionType
    Private _displayWindow As RichTextBox
    'global manager variables
    Private MessageColor As Color() = {Color.Blue, Color.Green, Color.Black, Color.Orange, Color.Red}
    Private comPort As New SerialPort()
#End Region

#Region "Manager Properties"
    ''' <summary>
    ''' Property to hold the BaudRate
    ''' of our manager class
    ''' </summary>
    Public Property BaudRate() As String
        Get
            Return _baudRate
        End Get
        Set(value As String)
            _baudRate = value
        End Set
    End Property

    ''' <summary>
    ''' property to hold the Parity
    ''' of our manager class
    ''' </summary>
    Public Property Parity() As String
        Get
            Return _parity
        End Get
        Set(value As String)
            _parity = value
        End Set
    End Property

    ''' <summary>
    ''' property to hold the StopBits
    ''' of our manager class
    ''' </summary>
    Public Property StopBits() As String
        Get
            Return _stopBits
        End Get
        Set(value As String)
            _stopBits = value
        End Set
    End Property

    ''' <summary>
    ''' property to hold the DataBits
    ''' of our manager class
    ''' </summary>
    Public Property DataBits() As String
        Get
            Return _dataBits
        End Get
        Set(value As String)
            _dataBits = value
        End Set
    End Property

    ''' <summary>
    ''' property to hold the PortName
    ''' of our manager class
    ''' </summary>
    Public Property PortName() As String
        Get
            Return _portName
        End Get
        Set(value As String)
            _portName = value
        End Set
    End Property

    ''' <summary>
    ''' property to hold our TransmissionType
    ''' of our manager class
    ''' </summary>
    Public Property CurrentTransmissionType() As TransmissionType
        Get
            Return _transType
        End Get
        Set(value As TransmissionType)
            _transType = value
        End Set
    End Property

    ''' <summary>
    ''' property to hold our display window
    ''' value
    ''' </summary>
    Public Property DisplayWindow() As RichTextBox
        Get
            Return _displayWindow
        End Get
        Set(value As RichTextBox)
            _displayWindow = value
        End Set
    End Property
#End Region

#Region "Manager Constructors"
    ''' <summary>
    ''' Constructor to set the properties of our Manager Class
    ''' </summary>
    ''' <param name="baud">Desired BaudRate</param>
    ''' <param name="par">Desired Parity</param>
    ''' <param name="sBits">Desired StopBits</param>
    ''' <param name="dBits">Desired DataBits</param>
    ''' <param name="name">Desired PortName</param>
    Public Sub New(baud As String, par As String, sBits As String, dBits As String, name As String, rtb As RichTextBox)
        _baudRate = baud
        _parity = par
        _stopBits = sBits
        _dataBits = dBits
        _portName = name
        _displayWindow = rtb
        'now add an event handler
        AddHandler comPort.DataReceived, New SerialDataReceivedEventHandler(AddressOf comPort_DataReceived)
    End Sub

    ''' <summary>
    ''' Comstructor to set the properties of our
    ''' serial port communicator to nothing
    ''' </summary>
    Public Sub New()
        _baudRate = String.Empty
        _parity = String.Empty
        _stopBits = String.Empty
        _dataBits = String.Empty
        _portName = comport_ismi
        _displayWindow = Nothing
        'add event handler
        AddHandler comPort.DataReceived, New SerialDataReceivedEventHandler(AddressOf comPort_DataReceived)
    End Sub
#End Region

#Region "WriteData"
    Public Sub WriteData(msg As String)
        Select Case CurrentTransmissionType
            Case TransmissionType.Text
                'first make sure the port is open
                'if its not open then open it
                If Not (comPort.IsOpen = True) Then
                    comPort.Open()
                End If
                'send the message to the port
                comPort.Write(msg)
                'display the message
                DisplayData(MessageType.Outgoing, msg & Convert.ToString(vbLf))
                Exit Select
            Case TransmissionType.Hex
                Try
                    'convert the message to byte array
                    Dim newMsg As Byte() = HexToByte(msg)
                    'send the message to the port
                    comPort.Write(newMsg, 0, newMsg.Length)
                    'convert back to hex and display
                    DisplayData(MessageType.Outgoing, ByteToHex(newMsg) & Convert.ToString(vbLf))
                Catch ex As FormatException
                    'display error message
                    DisplayData(MessageType.[Error], ex.Message)
                Finally
                    _displayWindow.SelectAll()
                End Try
                Exit Select
            Case Else
                'first make sure the port is open
                'if its not open then open it
                If Not (comPort.IsOpen = True) Then
                    comPort.Open()
                End If
                'send the message to the port
                comPort.Write(msg)
                'display the message
                DisplayData(MessageType.Outgoing, msg & Convert.ToString(vbLf))
                Exit Select
        End Select
    End Sub
#End Region

#Region "HexToByte"
    ''' <summary>
    ''' method to convert hex string into a byte array
    ''' </summary>
    ''' <param name="msg">string to convert</param>
    ''' <returns>a byte array</returns>
    Private Function HexToByte(msg As String) As Byte()
        'remove any spaces from the string
        msg = msg.Replace(" ", "")
        'create a byte array the length of the
        'divided by 2 (Hex is 2 characters in length)
        Dim comBuffer As Byte() = New Byte(msg.Length / 2 - 1) {}
        'loop through the length of the provided string
        For i As Integer = 0 To msg.Length - 1 Step 2
            'convert each set of 2 characters to a byte
            'and add to the array
            comBuffer(i / 2) = CByte(Convert.ToByte(msg.Substring(i, 2), 16))
        Next
        'return the array
        Return comBuffer
    End Function
#End Region

#Region "ByteToHex"
    ''' <summary>
    ''' method to convert a byte array into a hex string
    ''' </summary>
    ''' <param name="comByte">byte array to convert</param>
    ''' <returns>a hex string</returns>
    Private Function ByteToHex(comByte As Byte()) As String
        'create a new StringBuilder object
        Dim builder As New StringBuilder(comByte.Length * 3)
        'loop through each byte in the array
        For Each data As Byte In comByte
            'convert the byte to a string and add to the stringbuilder
            builder.Append(Convert.ToString(data, 16).PadLeft(2, "0"c).PadRight(3, " "c))
        Next
        'return the converted value
        Return builder.ToString().ToUpper()
    End Function
#End Region

#Region "DisplayData"
    ''' <summary>
    ''' method to display the data to & from the port
    ''' on the screen
    ''' </summary>
    ''' <param name="type">MessageType of the message</param>
    ''' <param name="msg">Message to display</param>
    <STAThread> _
    Private Sub DisplayData(type As MessageType, msg As String)
        '_displayWindow.Invoke(New EventHandler(Sub()
        '                                           _displayWindow.SelectedText = String.Empty
        '                                           _displayWindow.SelectionFont = New Font(_displayWindow.SelectionFont, FontStyle.Bold)
        '                                           _displayWindow.SelectionColor = MessageColor(CInt(type))
        '                                           _displayWindow.AppendText(msg)
        '                                           _displayWindow.ScrollToCaret()

        '                                       End Sub))
    End Sub
#End Region

#Region "OpenPort"
    Public Function OpenPort() As Boolean
        Try
            'first check if the port is already open
            'if its open then close it
            If comPort.IsOpen = True Then
                comPort.Close()
            End If

            'set the properties of our SerialPort Object
            comPort.BaudRate = Integer.Parse(_baudRate)
            'BaudRate
            comPort.DataBits = Integer.Parse(_dataBits)
            'DataBits
            comPort.StopBits = DirectCast([Enum].Parse(GetType(StopBits), _stopBits), StopBits)
            'StopBits
            comPort.Parity = DirectCast([Enum].Parse(GetType(Parity), _parity), Parity)
            'Parity
            comPort.PortName = _portName
            'PortName
            'now open the port
            comPort.Open()
            'display message
            DisplayData(MessageType.Normal, "Port AÇILDI: " + DateTime.Now + vbLf)
            'return true
            Return True
        Catch ex As Exception
            DisplayData(MessageType.[Error], ex.Message)
            Return False
        End Try
    End Function
#End Region

#Region "ClosePort"

    Public Function ClosePort() As Boolean
        Try
            'first check if the port is already open
            'if its open then close it
            If comPort.IsOpen = True Then
                comPort.Close()
            End If
            'display message
            DisplayData(MessageType.Normal, "Port KAPANDI: " + DateTime.Now + vbLf)
            'return true if port is closed
            If comPort.IsOpen = False Then
                Return True
            End If
            DisplayData(MessageType.Normal, "Kapatmada hata oluştu" & vbLf)
            Return False
        Catch ex As Exception
            DisplayData(MessageType.[Error], ex.Message)
            Return False
        End Try
    End Function

#End Region

#Region "SetParityValues"
    Public Sub SetParityValues(obj As Object)
        For Each str As String In [Enum].GetNames(GetType(Parity))
            DirectCast(obj, ComboBox).Items.Add(str)
        Next
    End Sub
#End Region

#Region "SetStopBitValues"
    Public Sub SetStopBitValues(obj As Object)
        For Each str As String In [Enum].GetNames(GetType(StopBits))
            DirectCast(obj, ComboBox).Items.Add(str)
        Next
    End Sub
#End Region

#Region "SetPortNameValues"
    Public Sub SetPortNameValues(obj As Object)

        For Each str As String In SerialPort.GetPortNames()
            DirectCast(obj, ComboBox).Items.Add(str)
        Next
    End Sub
#End Region

#Region "comPort_DataReceived"
    ''' <summary>
    ''' method that will be called when theres data waiting in the buffer
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub comPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs)
        'determine the mode the user selected (binary/string)
        Select Case CurrentTransmissionType
            'user chose string
            Case TransmissionType.Text
                'read data waiting in the buffer
                Dim msg As String = comPort.ReadExisting()
                'display the data to the user
                DisplayData(MessageType.Incoming, msg)
                ' + "\n");  **************
                Exit Select
                'user chose binary
            Case TransmissionType.Hex
                'retrieve number of bytes in the buffer
                Dim bytes As Integer = comPort.BytesToRead
                'create a byte array to hold the awaiting data
                Dim comBuffer As Byte() = New Byte(bytes - 1) {}
                'read the data and store it
                comPort.Read(comBuffer, 0, bytes)
                'display the data to the user
                DisplayData(MessageType.Incoming, ByteToHex(comBuffer))
                ' + "\n");
                Exit Select
            Case Else
                'read data waiting in the buffer
                Dim str As String = comPort.ReadExisting()
                'display the data to the user
                DisplayData(MessageType.Incoming, str)
                ' + "\n");
                Exit Select
        End Select
    End Sub
#End Region
End Class

I guess you are using the DataReceived event, if so, you can just take the data and split it by the lastIndexOf(Enviroment.NewLine). 我猜您正在使用DataReceived事件,如果是这样,则可以只获取数据并按lastIndexOf(Enviroment.NewLine)进行拆分。 you will have two part the first one is a string with some amount of lines and the second one is a string that contain no more lines. 您将分为两部分,第一个是包含一些行的字符串,第二个是不包含更多行的字符串。 You can take the first part and split it by new line and even create a new event (LineReceived). 您可以采用第一部分并用新行将其拆分,甚至可以创建一个新事件(LineReceived)。 for the second part(the part after the lastIndexOf(Enviroment.NewLine)) of the data just concatenate it to the beginning of the data that will arrive the next time. 对于数据的第二部分(lastIndexOf(Enviroment.NewLine)之后的部分),只需将其连接到下次将到达的数据的开头即可。

Try setting comm.Newline . 尝试设置comm.Newline Probably should be vbCR. 可能应该是vbCR。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM