Difference between revisions of "Serial unit"

From Free Pascal wiki
Jump to navigationJump to search
(→‎Example of usage: Note on device names.)
(→‎Timeout values: Last maintainer's comment on timeouts etc.)
 
Line 107: Line 107:
  
 
While both OSs provide some functionality to specify inter character timeouts, FPC does not directly expose this functionality in the Serial unit.
 
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.

Latest revision as of 15:13, 25 April 2023

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