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;
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;
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;
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;
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...