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

时间:2016-07-25 11:01:43

标签: vb.net excel serial-port vsto

我正在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命令,似乎在所有情况下都能正常工作。我非常感谢任何人提供的任何帮助,因为我对使用数据接收事件非常陌生。

1 个答案:

答案 0 :(得分:0)

好的,我试图仅隔离脚本中有问题的相关部分,并创建了一个全新的测试工具栏。下面是这个新工具栏的完整代码,其中包含一个连接/测量按钮和一个显示状态/结果的标签。我试图对代码进行评论以使其可读,希望这会有所帮助。

这个新工具栏确实可以正常工作。我仍然有点不确定我是否正确使用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