Search code examples
delphidelphi-xe7tcomport

Cant seem to recive a reply vir com port


Im trying to send a command to a dev. board and then receive a reply

E.G

(me) set attrib=yes

(Dev. Board) O.K

or

(Dev. Board) E.R.R

But it doesn't bounce back anything ... not an O.K or an E.R.R

while the board is booting echo is on .. so if I send the commands while the board is booting it it will bounce back an 'set attrib=yes' and once booted an 'E.R.R' because you cant send commands while booting.

my best guess is that it isn't reading the reply in time or trying to read it too soon.

procedure TReaderProgrammer.Button2Click(Sender: TObject);
Var 
  Buffer: AnsiString; 
  RxData: string; 
  Count : integer;
begin
  if ComPort1.Connected then
  begin
    ComPort1.WriteStr(edtSendText.Text+#13);
    comport1.ReadStr(RxData,Count);
    Buffer := Buffer + Rxdata;
    memoRxData.Text := memoRxData.Text+Buffer+#13+#10;
  end;
end;

Solution

  • Here are several open questions in the air, so I have to make some assumptions that might be wrong, but let's see.

    I don't know what comm port library you are using, so I'm assuming it is the CPort library from SourceForge. I have never used it myself, but I have read that it is made Unicode aware, such that you can call the write methods with a unicodestring parameter which will be converted by the library to ansistring before sending. Similarily when receiving ansistring from the outer world, the library will convert to unicodestring for the Read methods.

    Due to the asynchronous nature of serial communication, it is important to understand that when you send something using the write method, the method returns immediately while the library and OS spit out the characters one at at time at a pace defined by the baud rate. As a result your first code never received anything, because you were already attempting to read from the comm port before the external device even received the first character. It is good to see that you have now taken the first step to success by implementing an event handler for (presumably library event) OnRxChar.

    The OnRxChar probably fires for each character (or couple of characters). You need to have a buffer that is persistent between these events. A local var (as you have it now and which is allocated on the stack) in the event handler is not persistent, it is lost every time the event handler exits. You should declare the Buffer variable as a field of TReaderProgrammer. I don't know why you defined the buffer to be AnsiString, but I suggest you try with string (ref discussion above regarding Unicode awareness).

    type
      TReaderProgrammer = class
        ..
        RxBuffer: string;
        ..
      end;
    

    The buffer needs to be cleared when you send a new command to the external device in order for it to be ready to receive new data as a response to your command.

    EDIT: Alternatively you can clear the RxBuffer immediately when you have received and processed a full response.

    The TReaderProgrammer.ComPort1RxChar should look like this sofar:

    procedure TReaderProgrammer.ComPort1RxChar(Sender: TObject; Count: Integer);
    var
      RxData : string;
    begin
      (Sender as TComPort).ReadStr(RxData,Count);
      RxBuffer := RxBuffer + Rxdata;
      ...
    end;
    

    The rest of the event handler is, I guess, probably just to see progress of reception, so nothing more about that.