There are a few problems here.
First, your custom data packet handler is re-entrant. This is bad. Calling Application.ProcessMessages
inside the packet handler will break out of the handler and start running through the function from the start if a new data packet is received in the same time, only to continue from where it left off after the subsequent package has been fully processed (unless another packet comes in during that time in which case it will restart again). This is not the behaviour you want since it will lead to out-of-order packet processing and is probably related to your need for sleep
.
What I might suggest is to configure separate data packets for each command being sent from the instrument - ie :
- Data Packet 1 : Start String
ENQ
, End String #13#10
{CRLF}
- Data Packet 2 : Start String
STX
, End String #13#10
{CRLF}
- Data Packet 3 : Start String
EOT
, End String #13#10
{CRLF}
You will need either some class variables, a record, an object, etc, to track the progress of the packet. Something like this, as an example :
TASTMPkt = record
Started : boolean;
Complete : boolean;
Data : TStringList;
end;
In the ENQ
packet handler you would do something like :
if FASTMPkt.Data = nil then FASTMPkt.Data := TStringList.Create();
FASTMData.Clear();
FASTMPkt.Started := true;
FASTMPkt.Complete := false;
cpCom.WriteStr(cACK);
in the STX
handler :
if (not FASTMPkt.Started) or (FASTMPkt.Complete) then begin
// Raise exception, etc
end else begin
FASTMPkt.Data.Add(Str);
cpCom.WriteStr(cACK);
end;
in the EOT
handler :
if (not FASTMPkt.Started) or (FASTMPkt.Complete) then begin
// Raise exception, etc
end else begin
cpCom.WriteStr(cACK);
FASTMPacket.Complete := true;
ProcessPacket;
end;
Where ProcessPacket
could then work through the string list data and do whatever. This avoids clogging up the UI thread waiting for possibly incoming packets, allows you to use timers to check for FASTMPkt
completion in a timely manner (you could start a timeout timer in the ENQ
packet handler, reset it in the STX
handler, and stop it in the EOT
handler, for example). It also avoids sleep and ProcessMessages, and generally gives you ways to handle errors and ensure proper process flow.
As an aside, I've never used TComPort or TDataPacket but I highly recommend AsyncPro (TApdComPort, TApdDataPacket, etc) - these are great components that can be configured as visual or non-visual components and I've found them to be very competent and reliable. My answer here assumes that these two components work in generally the same way (which I think they do).
http://sourceforge.net/projects/tpapro/