从 VBA 访问串行端口的最佳方法是啥?
Posted
技术标签:
【中文标题】从 VBA 访问串行端口的最佳方法是啥?【英文标题】:What is the best way to access a serial port from VBA?从 VBA 访问串行端口的最佳方法是什么? 【发布时间】:2010-10-08 20:31:08 【问题描述】:从 VBA 访问串行端口的最佳方法是什么?
我需要我们的一些销售代表能够从 PowerPoint 中的操作按钮通过串行端口发送一个简单的字符串。我不常用 VBA,尤其是像这样的东西。通常我会把它变成某种应用程序,但我实际上并不认为这个想法那么糟糕。这将是他们在投影仪上演示此设备并与其他销售人员和非技术人员交谈时的便捷工具。此外,这个销售人员对 VBA 或 PowerPoint 演示文稿进行小幅修改也没有问题,但在重新编译 .NET 应用程序时就不行了。
我知道我们可以通过从动作演示文稿中运行的批处理文件来做到这一点,但这并不让我很高兴。我想我们可能可以访问一个 COM 对象并从那里运行,但我对在 VBA 中使用的最新和最棒的库并不了解,如果快速了解如何轻松打开它也很不错,发送并关闭连接。
因为这需要在多人的计算机上运行,所以如果它可以很容易地传输到其他机器上就更好了。我应该可以说它必须在 Office 2007 和 Windows XP 上运行。不过,与其他任何东西的兼容性将是一个不错的奖励。
我应该如何处理这个问题?有什么好的提示或技巧吗?图书馆推荐?
【问题讨论】:
【参考方案1】:Win32 API 将串行端口作为文件处理。您可以通过从 VBA 中调用这些 API 函数直接访问串行端口。我必须为旧的 .NET 应用程序执行此操作,但 VBA 也不例外。
我没有在这个网站上为你散布它,而是多年来我一直坚持的参考。 How to perform serial port communications in VBA
【讨论】:
自引用的链接发布(1999)以来,计算机硬件发生了一些变化,我尝试了代码,它不喜欢 COM9。【参考方案2】:Sub Stinky()
Dim COM_Byte As Byte
Dim Received_Lines As Long
Dim Input_Buffer As String
Dim Output_Buffer As String
Dim Chars2Send As Long
Dim CharsRemaining As Long
Dim lfsr As Long
Open "COM7:9600,N,8,1" For Random As #1 Len = 1
Input_Buffer = ""
CharsRemaining = 0
Do
Get #1, , COM_Byte
If COM_Byte Then
If COM_Byte = 13 Then ' look for CR line termination
Debug.Print Input_Buffer, Now ' print it
Input_Buffer = "" ' and clear input buffer
' generate some output (9 characters)
lfsr = &H3FFFFFFF - 2 ^ (Received_Lines And 15)
Output_Buffer = "?@@@@@@@@"
Chars2Send = 9
CharsRemaining = 9
For j = 0 To 2
Mid(Output_Buffer, 2 + j, 1) = Chr(Asc(Mid(Output_Buffer, 2 + j, 1)) + (31 And Int(lfsr / 32 ^ (2 - j))))
Next j
Debug.Print Output_Buffer
' show what I generated
Received_Lines = Received_Lines + 1 ' keep track of received line count
Else
Input_Buffer = Input_Buffer & Chr(COM_Byte) ' assemble output buffer
' process any characters to send
If CharsRemaining Then
CharsRemaining = CharsRemaining - 1
COM_Byte = Asc(Mid(Output_Buffer, Chars2Send - CharsRemaining, 1))
Put #1, , COM_Byte
End If
End If
End If
DoEvents
Loop
Close
End Sub
这对我有用。我不确定 OPEN 是否真的设置了波特率,因为我第一次使用 TeraTerm。 我的 COM 端口是与 BASYS3 原型开发套件的 USB 连接。它在 9600 处喷出字符,以 CR 结尾的 36 个字符的记录。我可以随机发送 9 个字符的命令。在上面的代码中,我每次收到新行时都会生成这些命令字符串。 我选择发送哪个字符的方式有点笨拙:也许更好的方法是拥有一个字符指针和多个字符,当它们相等时将它们都设置为零。
【讨论】:
如果 COM 端口以随机方式打开,EOF 似乎会告诉您何时需要接收字符。这意味着一个人可能会收到一个空字符。 EOF 说没有字符在等待。 在 OPEN 中设置波特率似乎不起作用。但是 Shell "mode.com com7:9600,n,8,1" 确实有效,如果您在执行 OPEN "COM7:" 之前稍等片刻,这就是 Excel 2010。 在 EOF 上更新 COM 端口为随机:看起来 EOF 不会随着接收到的字符而改变,但反映了 GET 的状态。所以在 GET #1,, vByte 之后,当 vByte 有效时,EOF 将为 FALSE。【参考方案3】:这是一个简短的 VBA 代码模块,可以在 PC 串行端口上发送和接收消息。这不是很优雅,但很简单,应该适用于现代版本的 Excel 和 Windows。
您可以自行扩展功能并存储或解析消息。这只是显示处理串行端口的低级内容。
前 5 行声明毫秒“睡眠”库函数(基于 Excel 版本)。
SerialPort() 子程序概述了打开端口、传输一些数据、接收一些数据、再次尝试接收一些数据的步骤(以表明它确实没有与“文件结束”错误发生冲突),并关闭端口。
#If VBA7 Then ' Excel 2010 or later
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal Milliseconds As LongPtr)
#Else ' Excel 2007 or earlier
Public Declare Sub Sleep Lib "kernel32" (ByVal Milliseconds As Long)
#End If
Public Sub SerialPort()
' open a COM port, transmit a message, gather results, close the port.
' open the COM port as file #1
Debug.Print "Open COM port 4"
Open "COM4:115200,N,8,1" For Binary Access Read Write As #1
transmit$ = Chr(2) + "Hello, World." + Chr(13)
receiveDummy$ = "~~~"
' transmit a message
Put #1, , transmit$
Debug.Print "Message sent."
' wait a bit for a response
Sleep 100
' check for received message
Debug.Print "Look for incoming message."
On Error Resume Next
Do While True
receive$ = receiveDummy$ 'dummy value
Input #1, receive$
If receive$ = receiveDummy$ Then Exit Do 'the string didn't change, so move on
Debug.Print receive$
Loop
On Error GoTo 0
' do it again to show that the empty input queue doesn't stop the flow
Debug.Print "Look again for incoming message (should not stop on error)."
On Error Resume Next
Do While True
receive$ = receiveDummy$ 'dummy value
Input #1, receive$
If receive$ = receiveDummy$ Then Exit Do 'the string didn't change, so move on
Debug.Print receive$
Loop
On Error GoTo 0
' close the serial port
Debug.Print "Close COM port."
Close #1
Debug.Print "Done."
End Sub
【讨论】:
以上是关于从 VBA 访问串行端口的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章