Ver Mensaje Individual
  #3  
Antiguo 06-05-2008
vejerf vejerf is offline
Miembro
 
Registrado: ene 2007
Posts: 206
Reputación: 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