[fpc-pascal] Reading Serial Hex Data

Bo Berglund bo.berglund at gmail.com
Mon Dec 28 13:16:48 CET 2020


On Sun, 27 Dec 2020 18:20:32 -0500, James Richters via fpc-pascal
<fpc-pascal at lists.freepascal.org> wrote:
>>On Sun, 27 Dec 2020 10:47:59 -0500, James Richters via fpc-pascal <fpc-pascal at lists.freepascal.org> wrote:
>>
>>>I'm trying to figure out how to read a packet of HEX Bytes of an 
>>>unknown length that have no specific termination character over a 
>>>serial port as efficiently as practical.
>>
>>What exactly do you mean by HEX Bytes?
>>Hex transfers using two characters for each byte? like 1F A4 etc?
>
>What I meant by 'Hex Data'  is that I am reading data in the form of bytes but they do not represent ASCII characters.  
>So if I read a $0D,  it's just a byte $0D, it doesn't represent a carriage return.  There is no specific code for end of line, 
>the last two bytes are a checksum, but I won't know they are the last ones until I'm done reading.  
>I'm reading all the data available, then analyzing it.
>

This is NOT wahat is generally meant by hex data, hex data means bytes
are encoded using the ASCII characters 0..9, A..F thus expanding data
size by x2 while making it possible to send over channels that use
control characters to handle transfer details such as line feeds,
start of text and end of text etc.
What you have is straight binary data....

>>
>>Is your program a console or GUI program?
>
>This is a console application.

I suspected as much. Many of the serial components available are
geared towards GUI apps and so for instance LazSerial links in stuff
like Forms and menus and the like, which causes exceptrions when
running in a straight GUI-less environment like a Linux server.

So I created a class named fpserial where I packaged the functions I
needed and used the built-in Serial unit as the basic execution
handler.

This class uses an event model to supply incoming data, which are
received inside a thread and supplied via a synchronized call to the
event function in the main thread of the program.
Being a console program it has a loop which includes CheckSynchronize
to handle this.

After I did that I have had no problems talking to external hardware
sending and receiving data in binary streams.

But there is a "protocol" for the transfers implemented to allow some
control. It looks something like this:
<length><messageID><message><checksum>
Where length is a 4-byte integer containing the length of the transfer
body and checksum is a 16 bit sum over all of the bytes inside the
body (excluding the checksum).

The messages are sent following a handshake between the two sides.

My thread code looks like this:

  { TComPortReadThread }

  TComPortReadThread=class(TThread)
  private
    FBuffer: TBytes;
    FReadPacketSize: integer;
    FReadTimeout: integer;
  public
    MustDie: boolean;
    Owner: TFpSerialPort;
    property ReadPacketSize: integer read FReadPacketSize write
FReadPacketSize; //How many bytes to read in each operation
    property ReadTimeout: integer read FReadTimeout write
FReadTimeout;    //Max time to wait for data in thread
  protected
    procedure CallEvent;
    procedure Execute; override;
  published
    property Terminated;
  end;

implementation

{ TComPortReadThread }

procedure TComPortReadThread.CallEvent;
begin
  if Assigned(Owner.FOnRxData) then
  begin
    Owner.FOnRxData(Owner, FBuffer);
  end;
end;

procedure TComPortReadThread.Execute;
var
  Cnt: integer;
begin
  try
    SetLength(FBuffer, BUFFERSIZE); //Set buffer size to 8192 bytes.
    while not MustDie do
    begin
      cnt := SerReadTimeout(Owner.FHandle, FBuffer[0],
FReadPacketSize, FReadTimeout); //Read FReadPacketSize bytes with
timeout of FReadTimeout ms
      if  cnt > 0 then
      begin
        SetLength(FBuffer, cnt); //Reduce size to fit received data
        Synchronize(CallEvent); //Supply received data in FBuffer to
caller
        SetLength(FBuffer, BUFFERSIZE); //Reset buffer size to 8192
bytes.
      end;
    end;
  finally
    Terminate;
  end;
end;


HTH

-- 
Bo Berglund
Developer in Sweden



More information about the fpc-pascal mailing list