Serial Ports
The runtime exposes its serial ports through the SysCom system library. Numbering starts at 1, as the CODESYS standard requires.
| Port | Peripheral | Pins | Available to the application |
|---|---|---|---|
| COM1 | USB-CDC | micro-USB | No — this is the CODESYS gateway (login, download, online) |
| COM2 | UART0 | GP12 TX / GP13 RX, direction on GP18 | Yes |
| COM3 | UART1 | GP4 TX / GP5 RX | Yes |
Both application ports are interrupt-driven. Opening a port configures its pins automatically — you do not need to touch them.
The format is currently fixed at 8N1 — 8 data bits, no parity, 1 stop bit: only the baud rate is selectable, and the parity and stop-bit fields of the settings are not applied.
Which port to use
Section titled “Which port to use”COM2 and the boot log. COM2’s peripheral, UART0, is also where the runtime’s boot log goes out (GP0). When your application opens COM2, the runtime detaches the log from UART0: COM2 carries only your application’s data, and the boot log on GP0 stops from the moment COM2 is opened until the next reboot. If you need that log while the application runs, use COM3, which has no such tenant.
COM2 does have one thing COM3 doesn’t: GP18 is driven as a direction (DE) pin — high while transmitting, low otherwise — for RS‑485 transceivers. COM3 has no direction pin.
Opening a port from ST
Section titled “Opening a port from ST”Add the SysCom library to your project (Library Manager → Add Library → SysCom), then:
PROGRAM PLC_PRGVAR hCom : RTS_IEC_HANDLE := RTS_INVALID_HANDLE; settings : SysCom.SysComSettings; result : SysTypes.RTS_IEC_RESULT; txFrame : ARRAY[0..5] OF BYTE := [16#02, 16#06, 16#01, 16#00, 16#00, 16#05]; rxBuf : ARRAY[0..63] OF BYTE; nRead : UDINT; nWritten : UDINT; xOpened : BOOL;END_VAR
IF NOT xOpened THEN settings.sPort := SysCom.PORTS.SYS_COM3; // COM3 = UART1, GP4/GP5 settings.ulBaudrate := SysCom.BAUDRATE.SYS_BR_115200; settings.byParity := SysCom.PARITY.SYS_NOPARITY; settings.byStopBits := SysCom.STOPBIT.SYS_ONESTOPBIT; settings.ulTimeout := 0; settings.ulBufferSize := 0;
hCom := SysCom.SysComOpen2(ADR(settings), 0, ADR(result)); xOpened := (hCom <> RTS_INVALID_HANDLE);END_IFBehind those enums are plain numbers: settings.sPort := 3 and settings.ulBaudrate := 115200 work just as well if your CODESYS version names the enums differently.
Writing and reading
Section titled “Writing and reading”// Send 6 bytes. SysComWrite blocks until they are out of the UART.nWritten := SysCom.SysComWrite(hCom, ADR(txFrame), SIZEOF(txFrame), 0, ADR(result));
// Read whatever has arrived so far. Timeout 0 returns immediately with// the bytes already in the buffer — which is what you want inside a PLC cycle.nRead := SysCom.SysComRead(hCom, ADR(rxBuf), SIZEOF(rxBuf), 0, ADR(result));
IF nRead > 0 THEN // process rxBuf[0..nRead-1]END_IFSysComRead returns the number of bytes actually copied, and sets the result to ERR_OK only when it could fill the whole requested size — a shorter read reports ERR_TIMEOUT and is perfectly normal.
Closing
Section titled “Closing”result := SysCom.SysComClose(hCom);hCom := RTS_INVALID_HANDLE;A port can only be opened once: a second SysComOpen2 on an already-open port returns an invalid handle.