Serial unit
Unit Serial in FPC supports work with serial port. It provides many Ser* functions.
Example of usage
Note that this uses Windows-style device names, unix systems (Linux, SunOS etc.) have their own conventions.
{
Usage:
TestSerialPortCom
Uses default port COM1.
TestSerialPortCom 8 'Hello'
Uses COM8 and outputs 'Hello' before waiting for an answer.
The program will open a serial port and output 'Hello', after that the code will wait until
a CR (#13) is received, or a key is pressed.
}
program TestSerialPortCom;
uses
serial, crt;
var
serialhandle : LongInt;
ComPortName : String;
s,tmpstr,txt : String;
ComIn : String;
ComPortNr : Integer;
writecount : Integer;
status : LongInt;
Flags : TSerialFlags; { set of (RtsCtsFlowControl); }
ErrorCode : Integer;
begin
ComPortNr:= 1;
tmpstr:= '';
txt:= '';
writeln('Parameters: ', ParamCount);
if (ParamCount>0) then
begin
tmpstr:= ParamStr(1);
val(tmpstr, ComPortNr, ErrorCode);
if (ParamCount>1) then
txt:= ParamStr(2);
end;
str(ComPortNr, tmpstr);
ComPortName:= 'COM'+tmpstr+':';
writeln('Using: '+ComPortname);
serialhandle := SerOpen(ComPortName);
Flags:= []; // none
SerSetParams(serialhandle, 9600, 8, NoneParity, 1, Flags);
s:= txt; // use the input text
writeln('Output: '+s);
s:= s+#13+#10; // CR + LF
writecount:= length(s);
status:= SerWrite(serialhandle, s[1], writecount);
// for debugging only
writeln('Status: ', status, ', WriteCount: ', writecount);
if status > 0 then
begin
writeln('Waiting for answer');
s:= '';
ComIn:= '';
while (Length(ComIn)<10) and (status>=0) and not KeyPressed do
begin
status:= SerRead(serialhandle, s[1], 10);
if (s[1]=#13) then
status:= -1; // CR => end serial read
if (status>0) then
begin
ComIn:= ComIn+s[1];
writeln('Status: ', status, ', Len: ', length(ComIn), ', ASCII: ', ord(s[1]), ', Input: ', ComIn);
end;
end;
end
else
writeln('Error: unable to send');
SerSync(serialhandle); // flush out any remaining before closure
SerFlushOutput(serialhandle); // discard any remaining output
SerClose(serialhandle);
end.Timeout values
Q: I'm trying to figure out when the timeout timer in SerRead/SerReadTimeout starts.
A (by FPC developer Christo Crause): FPC uses the OS provided functionality to interact with the serial port. On Windows the timeout seems to start when the read request is made - [https://learn.microsoft.com/en-us/previous-versions/ff547486(v=vs.85) Link]. On POSIX (at least Linux) it depends on the specific set of flags specified , scroll down to the discussion on canonical/noncanonical mode for the details - Link.
A bit more information after peeking into the source code: on Win32 the timeout information can be read or set using Get/SetCommTimeouts. The COMMTIMEOUTS structure contains a read interval timeout and total timeouts for read & write operations. SerReadTimeout sets the ReadTotalTimeoutConstant value, so basically the total timeout duration.
On Linux SerReadTimeout uses a fpSelect on the handle with the specified timeout, so in principle it is the same behaviour as on Windows, i.e. a total timeout.
While both OSs provide some functionality to specify inter character timeouts, FPC does not directly expose this functionality in the Serial unit.
Note from last maintainer: SerReadTimeout() explicitly says "https://github.com/MarkMLl/serialcomms" i.e. the intention is that timing starts when the function is called. Different lineages of unix handle fpSelect() differently, while not tested it's reasonable to assume that the Mac's OS-X behaves like SunOS/Solaris. See https://github.com/MarkMLl/serialcomms for examples, comments on known issues etc.
From the Free Pascal wiki, page "Serial unit", as it stood on 2023-04-25 after a change by MarkMLl, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.
Talk about this page
Nobody has opened a bench for this page yet. Sign in to open one.
