Foros del Web » Programación para mayores de 30 ;) » Programación General » Visual Basic clásico »

Concatenar dos bytes

Estas en el tema de Concatenar dos bytes en el foro de Visual Basic clásico en Foros del Web. Epales gente necesito ayuda, estoy recibiendo datos a traves del puerto serial, estos datos vienen de un microcontrolador pic, que solo los envia por bytes, ...
  #1 (permalink)  
Antiguo 13/11/2005, 10:00
 
Fecha de Ingreso: noviembre-2005
Mensajes: 2
Antigüedad: 18 años, 4 meses
Puntos: 0
Concatenar dos bytes

Epales gente necesito ayuda, estoy recibiendo datos a traves del puerto serial, estos datos vienen de un microcontrolador pic, que solo los envia por bytes, pero cada dos bytes corresponde a un dato entero para el programa en vB, como hago para que esos dos bytes el prog los concatene y los convierta en un solo dato de 16bits?
  #2 (permalink)  
Antiguo 13/11/2005, 13:21
Avatar de Beakdan  
Fecha de Ingreso: diciembre-2001
Ubicación: Monterrey, Nuevo León
Mensajes: 433
Antigüedad: 22 años, 2 meses
Puntos: 7
Microcontroladores PIC... :-p sólo tú puedes solucionar ese problema.
Pero tu problema del lado de la PC con VB, tiene varias soluciones:
Puedes declarar dos tipos de datos, uno que contenga un integer, y otro con contenga dos bytes. De este modo, usas LSet para embutir un tipo de dato en el otro, y ya tienes tu dato de 16bits. Otra opción es usar la API, para acomodar byte a byte sobre el integer. El siguiente code te puede servir...

Código:
Option Explicit

Private Declare Sub RtlMoveMemory Lib "kernel32" ( _
    ByRef Destination As Any, _
    ByRef Source As Any, _
    ByVal Length As Long)
    
Private Type WORD_BYTE
    ByteLo As Byte
    ByteHi As Byte
End Type

Private Type WORD_INT
    IntFull As Integer
End Type


Private Sub Form_Load()
Dim tmpInt As Integer
Dim tmpWrdInt As WORD_INT
Dim tmpWrdByt As WORD_BYTE
Dim tmpBytArr(1) As Byte

    '*******************************************
    'Usand LSet y definiciones de tipos de datos
    'Fácil de usar, pero hay que definir dos
    'tipos de datos para simular algo que se
    'puede hacer en C con uniones
    '*******************************************
    
    'Asignar el byte bajo
    tmpWrdByt.ByteLo = 0
    'Asignar el byte alto
    tmpWrdByt.ByteHi = 4
    '&H0400
    'Embutirlo en la variable int
    LSet tmpWrdInt = tmpWrdByt
    Debug.Print tmpWrdInt.IntFull
    
    
    '*******************************************
    'Usando la API
    'Hay que declarar la llamada a la función
    'RtlMoveMemory y tener cuidado al
    'utilizarla o puedes causar un
    'error grave en el programa.
    '*******************************************
    
    tmpBytArr(0) = 0
    tmpBytArr(1) = 4
    '&H0400
    'Acomodar el primer byte en el byte bajo del int
    RtlMoveMemory tmpInt, tmpBytArr(0), 1&
    'Acomodar el segundo byte en el byte alto del int
    RtlMoveMemory ByVal VarPtr(tmpInt) + 1, tmpBytArr(1), 1&
    Debug.Print tmpInt

End Sub
  #3 (permalink)  
Antiguo 14/11/2005, 18:40
Avatar de Jad-Neo  
Fecha de Ingreso: octubre-2004
Mensajes: 344
Antigüedad: 19 años, 4 meses
Puntos: 0
O tambien:

Código:
Dim WORD As Integer 'Tu valor Integer de dos bytes
WORD=Val("&H" & Hex(Byte2) & Hex(Byte1)) 'Concatenar los bytes
y listo, un tanto más fácil.
__________________
Nunca seas sabio en tu propia opinión.
  #4 (permalink)  
Antiguo 14/11/2005, 19:47
Avatar de Beakdan  
Fecha de Ingreso: diciembre-2001
Ubicación: Monterrey, Nuevo León
Mensajes: 433
Antigüedad: 22 años, 2 meses
Puntos: 7
Por supuesto, es muy simple. Pero, imagina que debes procesar datos a una gran velocidad. Convertir a string, concatenar y luego volver a convertir a un valor númerico, podría ser relativamente lento.
  #5 (permalink)  
Antiguo 18/11/2005, 19:23
Avatar de Jad-Neo  
Fecha de Ingreso: octubre-2004
Mensajes: 344
Antigüedad: 19 años, 4 meses
Puntos: 0
Pués lamentablemente yo así lo hago. No conosco una forma binaria de hacerlo, sería bueno que pongas ese procedimiento en las FAQs, ayudarías a muchos con ese problema. En eso tienes razon.

Por cierto, ¿como se le haría alrevez? que quieras extraer 1 byte de una collección que esté como valor hexadecimal. Por ej. &HABDCEF00 extraer el 2do. byte (&HEF) pero como tu dices, de manera binaria.
__________________
Nunca seas sabio en tu propia opinión.

Última edición por Jad-Neo; 18/11/2005 a las 19:30
  #6 (permalink)  
Antiguo 19/11/2005, 02:59
Avatar de Beakdan  
Fecha de Ingreso: diciembre-2001
Ubicación: Monterrey, Nuevo León
Mensajes: 433
Antigüedad: 22 años, 2 meses
Puntos: 7
No entendí muy bien eso de "una colección que esté como valor hexadecimal". Si tu cifra está como un string con la representación hexadecimal del número, probablemente sea más fácil usar una de las funciones para strings como mid$, left$ o rigth$ para obtener los caracteres que interesan.
Pero, en el caso de variables numéricas, la operación inversa es algo usual sobretodo si trabajas con la API y subclassing. Pero en esos casos, interesa separar el word más significativo del menos significativo en un DWORD. Sin embargo, la mecánica es la misma. De hecho, es posible realizarla con operaciones básicas de VB, sólo que como los tipos de datos númericos mayores que un byte son valores con signo, se debe tener cuidado. Todo se simplificaría si VB contara con una operación de desplazamiento de bits.

Código:
Option Explicit

Private Declare Sub RtlMoveMemory Lib "kernel32" ( _
    ByRef Destination As Any, _
    ByRef Source As Any, _
    ByVal Length As Long)
   
Private Type DWORD_BYTE
    BYTES(3) As Byte
End Type

Private Type DWORD_LONG
    DWORD As Long
End Type

Private Sub Form_Load()
Dim tmpLng As Long
Dim tmpBytArr(3) As Byte
Dim tmpByt As Byte
Dim tmpDWrdLng As DWORD_LONG
Dim tmpDWrdByt As DWORD_BYTE
    
    'Con tipos de datos, indicas
    'el índice del byte que quieres
    tmpDWrdLng.DWORD = &HABDCEF00
    LSet tmpDWrdByt = tmpDWrdLng
    Debug.Print "Con Types: "
    Debug.Print "Byte 0:" & tmpDWrdByt.BYTES(0)
    Debug.Print "Byte 1:" & tmpDWrdByt.BYTES(1)
    Debug.Print "Byte 2:" & tmpDWrdByt.BYTES(2)
    Debug.Print "Byte 3:" & tmpDWrdByt.BYTES(3)
    
    'Con la API
    Debug.Print "Con la API: "
    tmpLng = &HABDCEF00
    RtlMoveMemory tmpBytArr(0), tmpLng, 4&
    
    Debug.Print "Byte 0: " & tmpBytArr(0)
    Debug.Print "Byte 1: " & tmpBytArr(1)
    Debug.Print "Byte 2: " & tmpBytArr(2)
    Debug.Print "Byte 3: " & tmpBytArr(3)
    
    'Con métodos comunes de VB se usa una combinación
    'de máscaras de bits con divisiones
    Debug.Print "Con Métodos de VB: "
    'LSB
    tmpByt = tmpLng And &HFF&
    Debug.Print "Byte 0: " & tmpByt
    
    'Byte 1
    tmpByt = (tmpLng And &HFF00&) \ &H100
    Debug.Print "Byte 1: " & tmpByt
    
    'Byte 2
    tmpByt = (tmpLng And &HFF0000) \ &H10000
    Debug.Print "Byte 2: " & tmpByt

    'MSB: tendrás problemas para obtenerlo si
    'el número que "separas" es negativo. Por lo
    'tanto, se requiere un paso extra de enmascaramiento
    tmpByt = ((tmpLng And &HFF000000) \ &H1000000) And &HFF&
    Debug.Print "Byte 3: " & tmpByt

End Sub
Por cierto, no te había comentado sobre un error en el código que habías puesto, ya que el usuario que comenzó este thread no respondió nada y consideré muerta la discusión. Imagina que tienes dos bytes, cada uno con un valor de 15. Al utilizar tu código, se obtendría el valor de la cadena &HFF, que no es lo correcto ya que debería ser el valor de &H0F0F. En el caso de concatenar sólo dos bytes, usando tu código, habría que corregir cómo se obtiene la cadena del byte menos significativo:
Código:
WORD = Val("&H" & Hex$(Byte2) & Right$("0" & Hex$(Byte1), 2))

Última edición por Beakdan; 19/11/2005 a las 15:25
  #7 (permalink)  
Antiguo 25/11/2005, 18:26
Avatar de Jad-Neo  
Fecha de Ingreso: octubre-2004
Mensajes: 344
Antigüedad: 19 años, 4 meses
Puntos: 0
Si, no fije de ese error; buena observación. Pero esa es la forma textual de hacerlo y como me dijiste si es muy lenta para un proceso.

De hecho en base a tu código se puede crear una función para descomponer un valor en sus respectivos bytes:

Código:
Option Explicit

Declare Sub RtlMoveMemory Lib "kernel32" (ByRef Destination As Any, _
    ByRef Source As Any, ByVal Length As Long)

Type DWORD_BYTE
      Byte(0 To 3) As Byte
End Type

Function UnlinkB(ByVal dwVal As Long) As DWORD_BYTE
Dim tmpDW As DWORD_BYTE

CopyMemory tmpDW, dwVal, 4

UnlinkB = tmpDW
End Function
Este era un problema del que no buscaba como safarme a la hora de los procesos, ¡¡gracias Beakdan!!
__________________
Nunca seas sabio en tu propia opinión.

Última edición por Jad-Neo; 27/11/2005 a las 18:42
  #8 (permalink)  
Antiguo 24/02/2010, 11:39
 
Fecha de Ingreso: febrero-2010
Mensajes: 8
Antigüedad: 14 años
Puntos: 0
Respuesta: Concatenar dos bytes

muy buenas respuestas todas
pero hablando de la misma como podria mandar yo una cadena de datos hexadecimal atraves del puerto ethernet por ejemplo:

00 00 00 00 00 08 01 03 16 42 00 02 60 57
recordando que esta cadena esta en hexadecimal de 8 bit, investigando me dicen que es con modbus tcp pero me gustaria saber si se puede unicamente manda esetipo de cadenas por el puerto ethernet con el winsock

de antemano agradecido
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 23:12.