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