不确定是否正确使用串行端口数据接收事件

Unsure on proper use of Serial Port Data Received Event

我正在 VB.NET 为 Excel 2013 开发一个 VSTO 插件,它将帮助我通过串行连接与仪器进行交互。我目前已正确设置 COM 连接,它允许我一次发送和接收一个命令。我想对其进行设置,以便按下一个按钮并让它在不同的工作表单元格中收集两个单独的读数。使用下面的代码,这些工具可以很好地收集单个读数,但是当我启用代码以向仪器发送第二个命令时,Data Received 事件完全停止工作,直到我发送另一个单个读取命令。我知道仪器接收并处理了第二个命令,但它从未出现在 excel 中。谁能帮忙修改这段代码?

Private Sub mySerialPort_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
    'Handles serial port data received events
    UpdateFormDeligate1 = New UpdateFormDeligate(AddressOf UpdateDisplay)

    Dim n As Integer = mySerialPort.BytesToRead 'find number of bytes in buff
    comBuffer = New Byte(n - 1) {} 're-dimension storage buffer (n - 1)
    mySerialPort.Read(comBuffer, 0, n) 'read data from the buffer

    comBuffer2 = mySerialPort.ReadTo(vbCr)

    Me.Invoke(UpdateFormDeligate1) 'call the deligate
    mySerialPort.Close()
End Sub


Private Sub Invoke(updateFormDeligate1 As UpdateFormDeligate)
    lblReading.Label = processReading() 'write to a Current Reading lable on the ribbon

    Dim myApp As Excel.Application = Globals.ThisAddIn.Application
    Dim currentCell = myApp.ActiveCell
    currentCell.Value = processReading() 'write data in the excel active cell

    Try
        advanceCell()
    Catch ex As Exception
        System.Windows.Forms.MessageBox.Show(ex.Message)
    End Try
    If measureNo = 2 Then 'this case is selected when I want to read 2 measurements with a single button push
        cmdSent = 2
        sendCommand(measureCmd)

    End If
End Sub

Private Sub UpdateDisplay()

End Sub

请注意,我没有包括我的 sendCommand sub,因为这是一个简单的 .write 命令,对仪器来说似乎在所有情况下都能正常工作。我非常感谢任何人可以提供的任何帮助,因为我对使用数据接收事件还很陌生。

好的,我尝试仅隔离脚本中出现问题的相关部分,并创建了一个全新的工具栏进行测试。下面是这个新工具栏的完整代码,其中包含一个 connect/measure 按钮和一个显示 status/result 的标签。我试图注释代码以使其可读,希望这会有所帮助。

这个新工具栏似乎工作正常。我仍然有点不确定是否正确使用 DataReceived 事件处理程序与 Invoke 方法(Visual Studio 略微更改以用于 Excel2013)。任何人都可以就我是否仍在以不清楚的方式使用这些事件发表评论,并就如何改进它提出建议吗?

再次感谢您的帮助。非常感谢。

Imports Microsoft.Office.Tools.Ribbon
Imports System.IO.Ports

Public Class Measure2x_COM
Dim mySerialPort As New SerialPort
Dim CMD As String = "M" & vbCr 'statement telling instrument to measure
Dim measureNo As Integer = 0 'counts the number of measure commands sent to the instrument

Private Delegate Sub UpdateFormDeligate()
Private UpdateFormDeligate1 As UpdateFormDeligate

Dim sngReading As Single 'this is the reading received from the instrument as a single data type

Private Sub setupConnectCOM()
    'Open COM and send measure command - this part works correctly
    'first, check if serial port is open
    If mySerialPort.IsOpen Then 'send measure command
        mySerialPort.Write(CMD) 'the instrument will generally take 15.1 sec to perform a measurement before sending the result back
    Else
        'if serial port is not open, set it up, then open, then send command
        'Setup COM --this part works correctly
        With mySerialPort
            .PortName = "COM3"
            .BaudRate = 1200
            .DataBits = 7
            .Parity = Parity.None
            .StopBits = StopBits.Two
            .Handshake = Handshake.None
            .ReadTimeout = 16000
        End With

        Try
            mySerialPort.Open()
        Catch ex As Exception
            System.Windows.Forms.MessageBox.Show(ex.Message)
            Exit Sub 'exit sub if the connection fails
        End Try
        Threading.Thread.Sleep(200) 'wait 0.2 sec for port to open

        mySerialPort.Write(CMD) 'send measure command after serial port is open

    End If
    measureNo = 1
    lblResult.Label = "Measuring"
End Sub

Private Sub Measure2x_COM_Load(ByVal sender As System.Object, ByVal e As RibbonUIEventArgs) Handles MyBase.Load
    AddHandler mySerialPort.DataReceived, AddressOf mySerialPort_DataReceived

End Sub

Private Sub mySerialPort_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
    'Handles serial port data received events
    UpdateFormDeligate1 = New UpdateFormDeligate(AddressOf UpdateDisplay)

    'Read data as it comes back from serial port
    'I had to do this in two steps because it, for some reason needs to read
    'the +/- symbol as a Byte, then needs to read the ASCII measurement number
    'the third part concatenates the data and converts it to a single type

    'part 1 - read +/- symbol
    Dim comBuffer As Byte()
    Dim n As Integer = mySerialPort.BytesToRead 'find number of bytes in buff
    comBuffer = New Byte(n - 1) {} 're-dimension storage buffer (n - 1)
    mySerialPort.Read(comBuffer, 0, n) 'read data from the buffer

    'part 2 - read ASCII measurement number
    Dim comBuffer2 As String
    comBuffer2 = mySerialPort.ReadTo(vbCr)

    'part 3 - concatenate read data and convert to single type
    Dim txtReading As String = Nothing
    txtReading = System.Text.ASCIIEncoding.ASCII.GetString(comBuffer) & CStr(CInt(comBuffer2) / 10)
    sngReading = CSng(txtReading)

    'Call the update form deligate
    'Visual Studio slightly changed this from the example on Microsoft's website that used a Windows Form
    'I tried the code in a windows form and I get the same results
    Me.Invoke(UpdateFormDeligate1) 'call the deligate
End Sub

Private Sub Invoke(updateFormDeligate1 As UpdateFormDeligate)
    lblResult.Label = sngReading 'set the Result label in the ribbon to equal the received data value

    'now place the data received in the active cell in the worksheet
    Dim myApp As Excel.Application = Globals.ThisAddIn.Application
    Dim currentCell = myApp.ActiveCell
    currentCell.Value = sngReading

    'advance cell to the next cell
    Dim newCell = currentCell
    newCell = myApp.ActiveCell.Offset(1, 0)
    newCell.Select()
    currentCell = newCell

    'check if this was the first reading from the instrument
    'if it was the first reading, then send a second read command
    If measureNo = 1 Then
        measureNo = 2 'make sure to change measurement number to 2 to avoid infinite loop
        mySerialPort.Write(CMD) 'send command to measure to instrument
    End If
End Sub

'the usage of this section changed from the Microsoft Windows Form example
'in function, the mySerialPort_DataREceived(), Invoke(), and UpdateDisplay() functions do appear to be
'working with the same results and same hangups
Private Sub UpdateDisplay()

End Sub

Private Sub btnMeasure_Click(sender As Object, e As RibbonControlEventArgs) Handles btnMeasure.Click
    setupConnectCOM() 'connect to COM and send first measure command
End Sub
End Class