What is libserialport?
libserialport is a minimal, cross-platform C library created by the sigrok project — the same team behind PulseView and sigrok-cli. It provides a single, clean API for serial port communication that works on all major platforms without any platform-specific code in your application.
Under the hood it uses the Win32 API on Windows, termios on Linux, and IOKit on macOS. You write your code once and it runs everywhere.
Ubuntu/Debian: sudo apt install libserialport-dev • macOS: brew install libserialport • Windows: download from sigrok.org or use vcpkg.
Common Serial Port Settings
Every serial connection is defined by five parameters. Both ends must use identical settings or communication will fail.
| Parameter | Typical values | Notes |
|---|---|---|
| Baud rate | 9600, 115200, 921600 | 9600 is universal default; 115200 for most modern devices; 921600 for high-throughput sensors |
| Data bits | 8 (almost always) | 5, 6, 7 exist for legacy equipment; 8 is the standard for modern use |
| Parity | None (most common) | Odd/Even add a parity bit for error detection; None is standard for USB-serial adapters |
| Stop bits | 1 (most common) | 2 stop bits used with slow baud rates or older hardware; 1.5 is rare |
| Flow control | None or RTS/CTS | None for simple adapters; RTS/CTS (hardware) for reliable high-speed transfers; XON/XOFF (software) for text-based protocols |
Use Cases
Microcontrollers — Arduino, ESP32, STM32 via USB-serial adapters (CP2102, CH340, FTDI FT232).
Industrial protocols — Modbus RTU over RS-485 two-wire buses; SCADA field devices.
GPS receivers — NMEA 0183 sentences at 4800 or 9600 baud; u-blox modules at 115200.
Legacy lab instruments — oscilloscopes, signal generators, multimeters with RS-232 ports.
Industrial sensors — barcode scanners, weight scales, temperature controllers, PLCs.
Types
type
TSPPort = Integer; { serial port handle }
TSPConfig = Integer; { port configuration handle }
TSPParity = (
spParNone = 0, { no parity (most common) }
spParOdd = 1, { odd parity }
spParEven = 2, { even parity }
spParMark = 3, { mark parity }
spParSpace = 4 { space parity }
);
TSPFlow = (
spFlowNone = 0, { no flow control }
spFlowXonXoff = 1, { software: XON/XOFF }
spFlowRtsCts = 2, { hardware: RTS/CTS }
spFlowDtrDsr = 3 { hardware: DTR/DSR }
);
TSPMode = (
spRead = 1,
spWrite = 2,
spReadWrite = 3
);
TSPSignal = (
spCTS = 1, { Clear To Send }
spDSR = 2, { Data Set Ready }
spDCD = 4, { Data Carrier Detect }
spRI = 8 { Ring Indicator }
);
TSPPortInfo = record
Name : string; { e.g. '/dev/ttyUSB0', 'COM3' }
Description : string; { human-readable device description }
Transport : string; { 'native', 'usb', 'bluetooth' }
USBVendorID : Integer;
USBProductID : Integer;
USBSerial : string;
USBBus : Integer;
USBAddress : Integer;
end;
API Reference
Enumeration
{ List all available serial port names. }
function ListPorts: array of string;
{ List ports with full info (description, USB IDs, transport). }
function ListPortsInfo: array of TSPPortInfo;
Open / Close
{ Open a serial port by name. Mode: spRead, spWrite, spReadWrite. }
function OpenPort(const Name: string; Mode: TSPMode): TSPPort;
{ Close port and release all resources. }
procedure ClosePort(Port: TSPPort);
{ Get port info (description, USB IDs) for an open port. }
function GetPortInfo(Port: TSPPort): TSPPortInfo;
Configuration
{ Configure port with all settings at once (most common approach). }
procedure Configure(Port: TSPPort; BaudRate, DataBits: Integer;
Parity: TSPParity; StopBits: Integer; Flow: TSPFlow);
{ Set individual parameters. }
procedure SetBaudRate(Port: TSPPort; BaudRate: Integer);
procedure SetDataBits(Port: TSPPort; Bits: Integer);
procedure SetParity(Port: TSPPort; Parity: TSPParity);
procedure SetStopBits(Port: TSPPort; Bits: Integer);
procedure SetFlowControl(Port: TSPPort; Flow: TSPFlow);
{ Get current configuration as human-readable string. }
function GetConfig(Port: TSPPort): string;
I/O
{ Write data to port. Returns bytes written. }
function WritePort(Port: TSPPort; const Data: string): Integer;
{ Write with timeout in ms. 0 = non-blocking. }
function WriteTimeout(Port: TSPPort; const Data: string; TimeoutMs: Integer): Integer;
{ Read up to MaxBytes. Returns data read (may be less than MaxBytes). }
function ReadPort(Port: TSPPort; MaxBytes: Integer): string;
{ Read with timeout in ms. -1 = block until data available. }
function ReadTimeout(Port: TSPPort; MaxBytes, TimeoutMs: Integer): string;
{ Read a newline-terminated line. TimeoutMs: max wait in ms. }
function ReadLine(Port: TSPPort; TimeoutMs: Integer): string;
{ Number of bytes waiting in input buffer. }
function InputWaiting(Port: TSPPort): Integer;
{ Number of bytes in output buffer not yet sent. }
function OutputWaiting(Port: TSPPort): Integer;
{ Discard all pending input and output buffers. }
procedure Flush(Port: TSPPort);
{ Drain — block until all output bytes have been transmitted. }
procedure Drain(Port: TSPPort);
Control Lines
{ Set RTS (Request To Send) line state. }
procedure SetRTS(Port: TSPPort; Value: Boolean);
{ Set DTR (Data Terminal Ready) line state. }
procedure SetDTR(Port: TSPPort; Value: Boolean);
{ Read CTS/DSR/DCD/RI signal states as a bitmask (use TSPSignal enum). }
function GetSignals(Port: TSPPort): Integer;
{ Send a break signal for DurationMs milliseconds. }
procedure SendBreak(Port: TSPPort; DurationMs: Integer);
Error Handling
{ Get last error message from the library. }
function GetLastError: string;
{ Get the underlying libserialport version string. }
function LibSerialPortVersion: string;
Code Example — Arduino Communication
uses libserialport;
var
Port : TSPPort;
Resp : string;
Ports : array of string;
I : Integer;
begin
{ List available ports }
Ports := ListPorts;
WriteLn('Available serial ports:');
for I := 0 to High(Ports) do
WriteLn(' ', Ports[I]);
{ Open and configure for Arduino at 9600 baud }
Port := OpenPort('/dev/ttyUSB0', spReadWrite);
Configure(Port, 9600, 8, spParNone, 1, spFlowNone);
WriteLn('Config: ', GetConfig(Port));
{ Send command to Arduino }
WritePort(Port, 'LED_ON' + #13 + #10);
{ Wait for response, 2 second timeout }
Resp := ReadLine(Port, 2000);
WriteLn('Arduino says: ', Resp);
ClosePort(Port);
end.
Port Name Reference
Linux: /dev/ttyUSB0 (USB-serial adapter: CP2102, CH340, FTDI), /dev/ttyACM0 (Arduino CDC / composite), /dev/ttyS0 (hardware RS-232 COM port).
Windows: COM3, COM4, etc. Check Device Manager under “Ports (COM & LPT)”. High-numbered COM ports (COM10+) also work.
macOS: /dev/tty.usbserial-* (FTDI / prolific adapters), /dev/tty.usbmodem* (Arduino CDC). Use ls /dev/tty.* to list.
Tip: call ListPorts at runtime to enumerate all ports without hardcoding a name.
Package Info
Install
ppm install libserialport
Note
By the sigrok project — same team as PulseView logic analyzer and sigrok-cli.
Functions
- ListPorts
- ListPortsInfo
- OpenPort
- ClosePort
- GetPortInfo
- Configure
- SetBaudRate
- SetDataBits
- SetParity
- SetStopBits
- SetFlowControl
- GetConfig
- WritePort
- WriteTimeout
- ReadPort
- ReadTimeout
- ReadLine
- InputWaiting
- OutputWaiting
- Flush / Drain
- SetRTS / SetDTR
- GetSignals
- SendBreak
- GetLastError
- LibSerialPortVersion