Working with RS232 in CAPL: Open, Configure, Send, Receive, and Close
This guide summarizes the CAPL RS232 API used for serial communication and shows how to open, confiugre, transmit, receive, and close a serial connection.
Key functions:
- RS232Open(port)
- RS232Configure(port, baudrate, dataBits, stopBits, parity)
- RS232Send(port, buffer[], count)
- RS232Receive(port, buffer[], size)
- RS232Close(port)
- RS232SetHandshake(port, hendshake, XonLimit, XoffLimit, XonChar, XoffChar)
If you need local testing without hardware, create a virtual COM-port pair in your OS or with a third-party tool (e.g., COM5 <-> COM6), then bind CAPL to one side.
Opening a serial port
Returns 1 on success and 0 on failure (e.g., port does not exist or is in use).
on key 'o' // Open COM6
{
dword com = 6;
if (RS232Open(com))
{
write("COM%u opened", com);
}
else
{
write("Failed to open COM%u (busy or not present)", com);
}
}
Configuring the port
Set baud rate, data bits, stop bits, and parity. Default is (9600, 8, 1, 0).
on key 'c' // Configure COM6: 9600-8N1
{
dword com = 6;
if (!RS232Open(com))
{
write("Open failed for COM%u", com);
return;
}
if (RS232Configure(com, 9600, 8, 1, 0))
{
write("COM%u configured: 9600-8N1", com);
}
else
{
write("COM%u configuration failed", com);
}
}
Sending data (with send/error callbacks)
RS232Send returns 1 on success. On completion, RS232OnSend is called. On failure, RS232OnError is invoked.
/*@!Encoding:ASCII*/
on key 's' // Open, configure, and send a message
{
dword com = 6;
dword ok;
ok = RS232Open(com);
if (!ok)
{
write("Open failed for COM%u", com);
return;
}
ok = RS232Configure(com, 9600, 8, 1, 0);
if (!ok)
{
write("Configure failed for COM%u", com);
return;
}
// Prepare payload (do not send the terminating NUL)
char msg[] = "Hello, World!";
dword n = (dword)strlen(msg);
byte out[32];
int i;
for (i = 0; i < n; i++)
{
out[i] = (byte)msg[i];
}
ok = RS232Send(com, out, n);
if (ok)
{
write("Queued %u bytes on COM%u", n, com);
}
else
{
write("Send failed on COM%u", com);
}
}
RS232OnSend(dword port, byte data[], dword len)
{
// Log transmitted bytes in hex with a timestamp
char ts[32];
char line[128];
int i;
line[0] = 0;
for (i = 0; i < len; i++)
{
char tmp[8];
snprintf(tmp, elCount(tmp), "%02X ", data[i]);
snprintf(line, elCount(line), "%s%s", line, tmp);
}
getLocalTimeString(ts);
write("%s COM%u TX: %s", ts, port, line);
}
RS232OnError(dword port, dword flags)
{
if (flags & 1)
{
writeLineEx(0, 3, "COM%u transmit error", port);
}
if (flags & 2)
{
writeLineEx(0, 3, "COM%u receive error", port);
}
}
Receiving data (arming receive and receive callback)
RS232Receive returns 1 when arming succeeds. On data arrival, RS232OnReceive is invoked. Re-arm as needed if your environment requires it.
/* Arm receive and log incoming data */
on key 'r'
{
dword com = 6;
byte rx[64];
if (!RS232Open(com))
{
write("Open failed for COM%u", com);
return;
}
if (!RS232Configure(com, 9600, 8, 1, 0))
{
write("Configure failed for COM%u", com);
return;
}
if (RS232Receive(com, rx, elCount(rx)))
{
write("COM%u receive armed for %u bytes", com, elCount(rx));
}
else
{
write("COM%u receive arm failed", com);
}
}
RS232OnReceive(dword port, byte data[], dword len)
{
// Render both a text preview and a hex dump
int i;
char text[128];
char hex[256];
text[0] = 0;
hex[0] = 0;
// Copy as printable string (truncate and NUL-terminate)
for (i = 0; i < len && i < (elCount(text) - 1); i++)
{
text[i] = (char)data[i];
}
text[i < elCount(text) ? i : elCount(text) - 1] = '\0';
// Hex dump
for (i = 0; i < len; i++)
{
char tmp[8];
snprintf(tmp, elCount(tmp), "%02X ", data[i]);
snprintf(hex, elCount(hex), "%s%s", hex, tmp);
}
write("COM%u RX (%u bytes): '%s' | %s", port, len, text, hex);
}
Closing the port
Always release the port when your measurement stops.
on preStop
{
dword com = 6;
RS232Close(com);
}
Handshake configuration
Use RS232SetHandshake to configure flow control. The handshake parameter is implementation-specific (for example: 0=None, 1=RTS/CTS, 2=DSR/DTR, 3=XON/XOFF). Xon/Xoff characters typically use 0x11/0x13.
on key 'h'
{
dword com = 6;
dword handshake = 3; // Example: XON/XOFF (check your documentation)
dword xonLimit = 100; // Resume when buffer below this threshold
dword xoffLimit = 10; // Pause when buffer above this threshold
dword xonChar = 0x11; // XON
dword xoffChar = 0x13; // XOFF
if (RS232SetHandshake(com, handshake, xonLimit, xoffLimit, xonChar, xoffChar))
{
write("COM%u handshake configured", com);
}
else
{
write("COM%u handshake configuration failed", com);
}
}