[fpc-pascal] Reading Serial Hex Data

James Richters james.richters at productionautomation.net
Sun Dec 27 16:47:59 CET 2020


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.
The packet ends when there is just no more data to read.

I have something that is working that I wrote using SerRead from the Serial
unit in FPC, and it works at 9600bps,
but the method I am using will not work well at anything higher unless I can
figure out how to a very accurate very short delay.
At 9600, I need a delay just a little less than 1ms, so I use Sleep(1) for
my delay, but since 1ms is the minimum for sleep, and sleep 
itself is not really that accurate, I am doing a lot more delay than I need
to in order to make sure it works.

The procedure is:
Check the serial port for a byte in a loop until you either get a byte or
you get a timeout
Then once you have one byte, you delay enough time for few bytes to be in
the buffer
Next read one byte at time, Delay at the correct rate for the baudrate until
you run out of bytes or hit a maximum number of bytes.

What is needed is to stop at a timeout in case there is nothing to read, OR
to stop when maximum bytes are read OR stop when 2 bytes are missed meaning
you ran out of data to read.
But once you read one byte, you abandon the timeout.
SerReadTimeout has a timeout, but it seems to be a timeout for the whole
operation.. what I need is the first timeout to be a long timeout to wait
for the device to respond,
but once you get one byte, you cancel the timeout and never use it again..
now you read as many bytes as you can until you miss two in a row... then
you stop. 
Either that or have two timeouts, one timeout to delay for receiving the
first byte and the second timeout a way to tell when you have no more bytes
left to read.

It Seems like lots of people would want to read serial ports in this way,
because you never know how many bytes are coming, and you don't want to
always wait the entire timeout, 
that is just there to stop it in case there is no data.  Then again, I guess
most applications can read until they get a linefeed or carriage return,
which I will not be.
I'm thinking this has already been done somewhere and maybe there is already
a solution that is tested and works, but I don't know where it is or what
it's called.
I could not even find any documentation of SerReadTimout.

Here is pseudocode of the procedure that would be needed... the only thing I
am really lacking is the accurate time delay. 
So if there is not already a function somewhere that works this way, then a
recommendation on very fast and accurate timing delays would be helpful.

repeat
   Read the serial port and check for a byte
   Delay the amount of time one byte should take
   Inc(Timeout);
Until (Timeout=Max_Allowed) or Byte_ is_received
If Byte is received
   Begin
      Count:=-0;
      String:=String+ByteRead;
      Inc(Bytes_Read);
   End;
Delay enough time for a few more bytes to get in the buffer
Repeat
   Read serial port
   Delay the amount of time one byte should take
   If Byte is received
      Begin
         Count:=-0;
         String:=String+ByteRead;
         Inc(Bytes_Read);
      End
   Else
      Inc(Count);
Until MaxBytesRead Or (Count=2) 


 
James



More information about the fpc-pascal mailing list