Serial unit

From Free Pascal wiki
Jump to navigationJump to search

Unit Serial in FPC supports work with serial port. It provides many Ser* functions.

Example of usage

    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;
  serial, crt;

  serialhandle : LongInt;
  ComPortName  : String;
  s,tmpstr,txt : String;
  ComIn        : String;
  ComPortNr    : Integer;
  writecount   : Integer;
  status       : LongInt;
  Flags        : TSerialFlags; { set of (RtsCtsFlowControl); }
  ErrorCode    : Integer;

  ComPortNr:= 1;
  tmpstr:= '';
  txt:= '';

  writeln('Parameters: ', ParamCount);
  if (ParamCount>0) then
    tmpstr:= ParamStr(1);
    val(tmpstr, ComPortNr, ErrorCode);

    if (ParamCount>1) then
      txt:= ParamStr(2);

  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
    writeln('Waiting for answer');
    s:= '';
    ComIn:= '';
    while (Length(ComIn)<10) and (status>=0) and not KeyPressed do 
      status:= SerRead(serialhandle, s[1], 10);
      if (s[1]=#13) then 
        status:= -1; // CR => end serial read

      if (status>0) then
        ComIn:= ComIn+s[1];
        writeln('Status: ', status, ', Len: ', length(ComIn), ', ASCII: ', ord(s[1]), ', Input: ', ComIn);
    writeln('Error: unable to send');

  SerSync(serialhandle); // flush out any remaining before closure

  SerFlushOutput(serialhandle); // discard any remaining output


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.