<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">Il 09/09/2018 13:33, Bo Berglund via
      Lazarus ha scritto:<br>
    </div>
    <blockquote type="cite"
      cite="mid:p20apdh6bddjfk79rcbd016hk5i40jd975@4ax.com">
      <pre wrap="">I am writing a testing application for checking out a TCP to Serial
bridge component. I am using Lazarus 1.8.0 and fpc 3.0.4 on Windows 7

For the serial port handling I found the "built-in" Serial unit
described here:
<a class="moz-txt-link-freetext" href="http://wiki.freepascal.org/Hardware_Access#FPC_built_in_Serial_unit">http://wiki.freepascal.org/Hardware_Access#FPC_built_in_Serial_unit</a>

Now I have a few questions about its usage:

1) Serial port name
-------------------
When opening the port the example does this:

str(ComPortNr,tmpstr);
ComPortName:= 'COM'+tmpstr+':';
serialhandle := SerOpen(ComPortName);

So for say port 29 this results in ComPortName 'COM29:'
Is this always the case? I have a hunch that for port numbers 1..9 the
Windows port naming is different than for higher port numbers...

And if I want to port this to Linux, I guess thta the name is
completely different, but no hint is given.
</pre>
    </blockquote>
    Here is the procedure I'm using to fill up a combo box with the
    names of the existing serial devices on the platform. Please note
    the different naming conventions in Linux and Windows. Also note
    that to report a serial port as existing a test is made to open it
    (using the fpc serial function), and avoid "phantom" ports.<br>
    <pre><blockquote type="cite">procedure TForm1.btnScanPortClick(Sender: TObject);
var
 PortNr: Integer;
 PortName: String;
 PortHandle: TSerialHandle;
begin
  cbSelPort.Items.Clear;
  cbSelPort.Text:= '';
{$IFDEF MSWINDOWS}
  for PortNr := 1 to 9 do begin
    PortName := 'COM' + IntToStr(PortNr);
    PortHandle := SerOpen('\\.\'+PortName);
    if PortHandle > 0 then begin
      cbSelPort.Items.Add(PortName);
      SerClose(PortHandle);
      if cbSelPort.Text = '' then begin
        cbSelPort.Text:=PortName;
        PortSel.Caption:= PortName;
        end;
      end;
    end;
{$ELSE}
  for PortNr := 0 to 9 do begin
    PortName := '/dev/ttyS' + IntToStr(PortNr);
    PortHandle := SerOpen(PortName);
    if PortHandle > 0 then begin
      if cbSelPort.Text = '' then begin
        cbSelPort.Text:=PortName;
        PortSel.Caption:= PortName;
        end;
      cbSelPort.Items.Add(PortName);
      SerClose(PortHandle);
      end;
    end;
  for PortNr := 0 to 9 do begin
    PortName := '/dev/ttyUSB' + IntToStr(PortNr);
    PortHandle := SerOpen(PortName);
    if PortHandle > 0 then begin
      if cbSelPort.Text = '' then begin
        cbSelPort.Text:=PortName;
        PortSel.Caption:= PortName;
        end;
      cbSelPort.Items.Add(PortName);
      SerClose(PortHandle);
      end;
    end;
{$ENDIF}
end;
</blockquote></pre>
    <br>
    <blockquote type="cite"
      cite="mid:p20apdh6bddjfk79rcbd016hk5i40jd975@4ax.com">
      <pre wrap="">
2) Blocking send?
------------------
Is this port blocking for sending?

The example has this:

status := SerWrite(serialhandle, s[1], writecount );

where s is a string holding the text to send (I will actually need to
use a TBytes array instead) and writecount returns the bytes actually
sent.

If I want to send an array of say 100 kbytes at 9600 baud, will the
call return only when the data have been completely sent or earlier?
It will take about 100 seconds to send that array...
</pre>
    </blockquote>
    Yes, SerWrite is blocking. I hope you don't plan to send 100 kbytes
    in a single write on a serial line. The probability of an error in
    between is near to 100%!<br>
    What I'm doing in such cases is to create a dedicated thread to
    handle send and receive, without blocking the main thread, which
    remains responsive, and split the send in many small blocks (and
    getting some sort of ACK/NAK from remote receiver), which makes it
    possible to show a progress bar or whatever visual feedback you
    like.<br>
    <blockquote type="cite"
      cite="mid:p20apdh6bddjfk79rcbd016hk5i40jd975@4ax.com">
      <pre wrap="">
3) Receiving data
----------------
For data reception I see this:

s:='';
ComIn:='';
while (Length(Comin)<10) and (status>=0) and not keypressed do 
begin
   status:= SerRead(serialhandle, s[1], 10);
   ...

Since the call parameters are the receive buffer and the count to read
I do not understand how this can work. s has been emptied (length = 0)
just before the call so how can SerRead stuff any data into the buffer
starting at s[1], which should not even exist???

I would like to have a way to read incoming data asynchronously so I
also could handle the user feedback and the TCP connection which is
sending the data that ultimately will arrive on the serial line...

Any suggestions on how to do this?


</pre>
    </blockquote>
    <p>I never use SerRead, but rather SerReadTimeout (from the same
      unit) which gives a much better control of what is going on. Of
      course in that case your receiving buffer must be large enough to
      accommodate the largest block you expect. (This replies also to
      your further questions).<br>
    </p>
    <p><br>
    </p>
    <p>I hope that it helps.</p>
    <p><br>
    </p>
    <p>Giuliano<br>
    </p>
    <pre class="moz-signature" cols="72">-- 
Do not do to others as you would have them do to you.They might have different tastes.
</pre>
  </body>
</html>