Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 05-05-2008
vejerf vejerf is offline
Miembro
 
Registrado: ene 2007
Posts: 206
Poder: 18
vejerf Va por buen camino
Lectura de tramas: <SYN><DLE><STX> ... <DLE><ETX>

Hola,
Estoy realizando una aplicación que lee datos del puerto serie. Los datos que me llegan los almaceno en un buffer de recepción de bytes. Este buffer tiene la siguiente estructura:
Código Delphi [-]
 
TBUFFER_ENTRADA = record
    Numero_Datos     : integer;
    Puntero_Entrada  : integer;
    Puntero_Salida   : integer;
    Datos            : array [1..LONGITUD_BUFFERS] of Byte;
  end;

Las tramas que me llegan tienen el siguiente formato:
<SYN><DLE><STX> ... <DLE><ETX>

Mi problema es que soy capaz de leer tramas, pero con mi forma de hacerlo parece ser que alguna se me escapa. Tiene alguien algún método para leer tramas de ese tipo???

Muchas gracias...
Responder Con Cita
  #2  
Antiguo 05-05-2008
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Question

Cita:
Empezado por vejerf Ver Mensaje
...Mi problema es que soy capaz de leer tramas, pero con mi forma de hacerlo parece ser que alguna se me escapa...
Bueno, creo que sería necesario que nos dijeras cuál es esa forma de hacerlo y, ya encarrerado el ratón, el componente, biblioteca o grupo de funciones que estás utilizando.

Esperamos tu retroalimentación.

Saludos.

Al.
Responder Con Cita
  #3  
Antiguo 06-05-2008
vejerf vejerf is offline
Miembro
 
Registrado: ene 2007
Posts: 206
Poder: 18
vejerf Va por buen camino
A continuación pongo el código con el que leo las tramas. El buffer que utilizo es un buffer circular. Uso un componente llamado TVaComm para usar el puerto serie. Cuando recibo un carácter por el puerto serie se produce el evento en el que compruebo si tengo una trama completa. El código es el siguiente:

Código Delphi [-]
procedure TSimuladorThorcomForm.PuertoSerieRxChar(Sender: TObject;
  Count: Integer);
var
  Estado      : integer;
  CONTADOR    : integer;
  NumeroBytes : integer;
  FinalTrama : boolean;
  FlagLongitud : boolean;
  NBytes : Integer;
  I : Integer;
  NumeroDatos : integer;
  Datos : Byte;
  DatoHx : String;
  PunteroAux1 : Integer;
  PunteroAux2 : Integer;
begin
  NumeroBytes := (Sender as TVaComm).ReadBufUsed;
  CONTADOR := 1;
  Datos := 0;
  //Se leen los bytes que estén en la cola de recepción a la espera de ser leídos y se meten en el buffer circular
  for CONTADOR := 1 to NumeroBytes do
  begin
    Estado := (Sender as TVaComm).ReadBuf(BUFFER_RX.Datos[BUFFER_RX.Puntero_Entrada],1);
    Datos :=  BUFFER_RX.Datos[BUFFER_RX.Puntero_Entrada];
    if ( (Datos < 32) or (Datos > 122) ) then
      DatoHx := IntToHex(Byte(BUFFER_RX.Datos[BUFFER_RX.Puntero_Entrada]),2)
    else
      DatoHx := Char(BUFFER_RX.Datos[BUFFER_RX.Puntero_Entrada]);
    CuadroTX.Lines.Text := CuadroTX.Lines.Text +' '+ DatoHx;
    inc(BUFFER_RX.Puntero_Entrada);
    if BUFFER_RX.Puntero_Entrada > Longitud_Buffers then
      BUFFER_RX.Puntero_Entrada := 1;
    inc(BUFFER_RX.Numero_Datos);
    if BUFFER_RX.Numero_Datos > Longitud_Buffers then
      BUFFER_RX.Numero_Datos := 1;
  end;
  //Buscamos el comienzo de trama 
  while ( (BUFFER_RX.Datos[BUFFER_RX.Puntero_Salida] <> SYN) and (BUFFER_RX.Numero_Datos <> 0) ) do
  begin
    inc(BUFFER_RX.Puntero_Salida);
    if BUFFER_RX.Puntero_Salida > Longitud_Buffers then
      BUFFER_RX.Puntero_Salida := 1;
      dec(BUFFER_RX.Numero_Datos);
  end;
  if BUFFER_RX.Puntero_Salida = Longitud_Buffers then
  begin
    PunteroAux1 := 1;
    if PunteroAux1 = Longitud_Buffers then
      PunteroAux2 := 1
    else
      PunteroAux2 := PunteroAux1 + 1;
  end
  else
  begin
    PunteroAux1 := BUFFER_RX.Puntero_Salida + 1;
    if PunteroAux1 = Longitud_Buffers then
      PunteroAux2 := 1
    else
      PunteroAux2 := PunteroAux1 + 1;
  end;
  FinalTrama := false;
  while ( ( (BUFFER_RX.Datos[BUFFER_RX.Puntero_Salida] <> SYN) or (BUFFER_RX.Datos[PunteroAux1] <> DLE)
            or (BUFFER_RX.Datos[PunteroAux2] <> STX) ) and (BUFFER_RX.Numero_Datos >0) ) do
  begin
    inc(BUFFER_RX.Puntero_Salida);
    if BUFFER_RX.Puntero_Salida > Longitud_Buffers then
      BUFFER_RX.Puntero_Salida := 1;
    dec(BUFFER_RX.Numero_Datos);
    if BUFFER_RX.Puntero_Salida = Longitud_Buffers then
    begin
      PunteroAux1 := 1;
      if PunteroAux1 = Longitud_Buffers then
        PunteroAux2 := 1
      else
        PunteroAux2 := PunteroAux1 + 1;
    end
    else
    begin
      PunteroAux1 := BUFFER_RX.Puntero_Salida + 1;
      if PunteroAux1 = Longitud_Buffers then
        PunteroAux2 := 1
      else
        PunteroAux2 := PunteroAux1 + 1;
    end;
  end;
  //Buscamos el final de trama
  while ( ( (BUFFER_RX.Datos[PunteroAux2] <> ETX) or (BUFFER_RX.Datos[PunteroAux1] <> DLE) )
            and (PunteroAux1 <> BUFFER_RX.Puntero_Entrada) ) do
  begin
    inc(PunteroAux1);
    if PunteroAux1 > Longitud_Buffers then
      PUnteroAux1 := 1;
    inc(PunteroAux2);
    if PunteroAux2 > Longitud_Buffers then
      PunteroAux2 := 1;
    if ( (BUFFER_RX.Datos[PunteroAux1] = DLE) and (BUFFER_RX.Datos[PunteroAux2] = ETX) ) then
      FinalTrama := true;
  end;
  //Si hay una trama completa en el BUFFER_RX la extraemos para procesarla
  if FinalTrama = true then
  begin
    FinalTrama := false;
    NBytes := 0;
    for I := 1 to Longitud_Buffers do
      TRAMA[i] := 0;
    I := 1;
    while ( (BUFFER_RX.Puntero_Salida <> PunteroAux2) and (BUFFER_RX.Numero_Datos <> 0) ) do
    begin
      TRAMA[i] := BUFFER_RX.Datos[BUFFER_RX.Puntero_Salida];
      inc(NBytes);
      inc(I);
      inc(BUFFER_RX.Puntero_Salida);
      if BUFFER_RX.Puntero_Salida > Longitud_Buffers then
        BUFFER_RX.Puntero_Salida := 1;
      dec(BUFFER_RX.Numero_Datos);
    end;
    inc(NBytes);
    TRAMA[NBytes] := ETX;
    DesempaquetarTrama(NBytes);
  end;
end;

Lo que hago primero es tomar los bytes del puerto serie y meterlos en el buffer de recepción. A continuación compruebo si hay una trama completa y si la hay la desempaqueto.

Quizás no sea la forma más práctica ni ortodoxa, pero más o menos me funciona jeje

Muchas gracias...
Responder Con Cita
  #4  
Antiguo 06-05-2008
[egostar] egostar is offline
Registrado
 
Registrado: feb 2006
Posts: 6.557
Poder: 25
egostar Va camino a la fama
Cita:
Empezado por vejerf Ver Mensaje
Quizás no sea la forma más práctica ni ortodoxa, pero más o menos me funciona
Hola vejerf

Para este tipo de menesteres y desde mi experiencia con la recepción de paquetes de datos a través de puerto serial, te recomiendo que uses el componente TurboPower Async Professional (gracias amigo Al por recomendarmelo hace ya unos años ), el cual tiene dentro de sus particularidades un objeto de nombre ApdDataPacket, a este objeto le asignas una cadena de inicio y una cadena de final por ejemplo:

En las propiedades del Objeto ApdDataPacket

StartString = #22 [SYN] (Aunque yo usaria solo #2 [STX], a menos que requieras por fuerza el [SYN])
EndString = #3 [ETX];

y en código solo requieres hacer esto:

Código Delphi [-]
procedure TLector.ApdDataPacket1StringPacket(Sender: TObject; Data: string);
begin
  ProcesaInformacion(Data); //Data ya tiene todo el paquete de datos que esperas.
end;

Al final, te olvidas de codificar y validar cada vez que recibes un caracter.

Salud OS
__________________
"La forma de empezar es dejar de hablar y empezar a hacerlo." - Walt Disney
Responder Con Cita
  #5  
Antiguo 07-05-2008
vejerf vejerf is offline
Miembro
 
Registrado: ene 2007
Posts: 206
Poder: 18
vejerf Va por buen camino
Gracias por tu ayuda Egostar... pero... pero...
El componente que uso es el TVaComm. Este viene junto con otra serie de componentes en un paquete llamado Async32 si no me equivoco. Otro de los componentes que trae es el TVaCapture que funciona como tu dices. Le indicas el comienzo y el fin de trama y cuando detecta ese comienzo y fin produce un evento que tiene como parámetro el contenido del paquete. El problema que me encontré es que el modem que uso devuelve los caracteres hexadecimales y el componente TVaCapture devuelve caracteres ASCII. En principio para algunas cosas me es igual, pero me he dado cuenta de un pequeño fallo. Resulta que el modem devuelve en muchas tramas el valor $00 (carácter NULL) y TVaCapture lo devuelve en el String de datos como un espacio en blanco ($20 si no me equivoco). Entonces esto a veces me lleva a error xq puede que alguna vez sí sea verdaderamente un espacio o a veces sea un NULL. Y estos valores puede que me sean necesarios saber el valor exacto.
No sé si después de todo este palabrerío se me habrá entendido jeje.

De todas formas... muchísimas gracias por el consejo!!!
Responder Con Cita
  #6  
Antiguo 07-05-2008
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por vejerf Ver Mensaje
...El componente que uso es el TVaComm. Este viene junto con otra serie de componentes en un paquete llamado Async32 si no me equivoco. Otro de los componentes que trae es el TVaCapture que funciona como tu dices. Le indicas el comienzo y el fin de trama y cuando detecta ese comienzo y fin produce un evento que tiene como parámetro el contenido del paquete...
Sólo como dato, te comento que usas los mismos componentes que yo utilizaba antes de descubrir los de TurboPower que te sugiere Eliseo, los cuales encontré más potentes y funcionales. Y es bastante problable que con ellos tengas menos problemas.

Saludos.

Al.
Responder Con Cita
  #7  
Antiguo 28-06-2008
Avatar de richy08
richy08 richy08 is offline
Miembro
 
Registrado: may 2007
Ubicación: Bucerias, Nayarit Mexico
Posts: 529
Poder: 17
richy08 Va por buen camino
Cita:
Empezado por egostar Ver Mensaje
Hola vejerf

Para este tipo de menesteres y desde mi experiencia con la recepción de paquetes de datos a través de puerto serial, te recomiendo que uses el componente TurboPower Async Professional (gracias amigo Al por recomendarmelo hace ya unos años ), el cual tiene dentro de sus particularidades un objeto de nombre ApdDataPacket, a este objeto le asignas una cadena de inicio y una cadena de final por ejemplo:

En las propiedades del Objeto ApdDataPacket

StartString = #22 [SYN] (Aunque yo usaria solo #2 [STX], a menos que requieras por fuerza el [SYN])
EndString = #3 [ETX];

y en código solo requieres hacer esto:


Código Delphi [-]
procedure TLector.ApdDataPacket1StringPacket(Sender: TObject; Data: string);
begin
ProcesaInformacion(Data); //Data ya tiene todo el paquete de datos que esperas.
end;





Al final, te olvidas de codificar y validar cada vez que recibes un caracter.

Salud OS
buenos dtardes egostar estoy leyendo el post y me baje el componenet que mencionas lo pienso usar para leer el puerto serial de un conmutador, me podrias proporcionar algun manual de como usarlo mil gracias.
Responder Con Cita
  #8  
Antiguo 29-06-2008
[egostar] egostar is offline
Registrado
 
Registrado: feb 2006
Posts: 6.557
Poder: 25
egostar Va camino a la fama
Cita:
Empezado por richy08 Ver Mensaje
buenos dtardes egostar estoy leyendo el post y me baje el componenet que mencionas lo pienso usar para leer el puerto serial de un conmutador, me podrias proporcionar algun manual de como usarlo mil gracias.
Hola richy08

Puedes bajar los archivos de ayuda que tienen disponibles. tpapro_docs

Salud OS
__________________
"La forma de empezar es dejar de hablar y empezar a hacerlo." - Walt Disney
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Lectura del USB por Interrupción cisco Varios 0 25-10-2007 18:13:29
Documentacion para Generar Tramas TCP bastardo10 Varios 0 07-06-2007 17:31:38
Lectura de un FTP con idHTTP gluglu Internet 2 05-05-2007 00:35:50
Problema de lectura de un cd dragondetierra Varios 0 18-02-2007 18:58:52


La franja horaria es GMT +2. Ahora son las 22:36:59.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi