Saltar al contenido

¿Cuál es la mejor manera de acceder a un puerto serie desde VBA?

Luego de tanto luchar ya dimos con la respuesta de este atolladero que algunos los lectores de nuestro sitio web presentan. Si tienes algo que compartir no dejes de dejar tu información.

Solución:

La API de Win32 maneja el puerto serie como un archivo. Puede acceder a los puertos serie directamente llamando a estas funciones API desde dentro de VBA. Tuve que hacer esto para una aplicación .NET antigua, pero VBA no es diferente.

En lugar de discutirlo en este sitio, aquí hay una referencia que he guardado a lo largo de los años. Cómo realizar comunicaciones de puerto serie en VBA

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 = "[email protected]@@@@@@@"
            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

Esto funciona para mí. No estoy seguro de si OPEN realmente establece la tasa de baudios, ya que usé TeraTerm por primera vez. Mi puerto COM es una conexión USB a un kit de creación de prototipos BASYS3. Está arrojando caracteres en 9600, registros de 36 caracteres que terminan en CR. Puedo enviar aleatoriamente comandos de 9 caracteres. En el código anterior, genero estas cadenas de comando cada vez que recibo una nueva línea. La forma en que elegí qué carácter enviar es un poco torpe: tal vez una mejor manera es tener un puntero de carácter y una cantidad de caracteres, y cuando sean iguales, establecerlos en cero.

Aquí hay un breve módulo de código VBA que puede enviar y recibir mensajes en un puerto serie de PC. Esto no es muy elegante, pero es simple y debería funcionar en versiones modernas de Excel y Windows.

Usted se queda solo para expandir la funcionalidad y almacenar o analizar los mensajes. Esto solo muestra las cosas de bajo nivel para tratar con el puerto serie.

Las primeras 5 líneas declaran la función de biblioteca “Sleep” de milisegundos (basada en la versión de Excel).

La subrutina SerialPort() describe los pasos para abrir el puerto, transmitir algunos datos, recibir algunos datos, volver a intentar recibir algunos datos (para demostrar que realmente no se ejecuta en conflicto con el error de “fin de archivo”) y cerrar el Puerto.


#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

Te invitamos a corroborar nuestra ocupación poniendo un comentario y dejando una valoración te damos las gracias.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *