<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>