Skip to main content

RS485

The RS485 interface provides differential serial communication with the standard baud rates from 300 to 4,000,000 bps. Supports optional termination resistors for proper bus termination.

TIP

As described in pin alternate functions, industrial communication interfaces share GPIOs, meaning only one feature can be enabled at a given time: Either regular GPIOs, or one of the industrial communication interfaces.

RS485_0 shares pins with CAN

The CAN bus and RS485_0 share the same GPIO pins for communication. Therefore, only one of these interfaces can be enabled at a time.

Enabling RS485_0 while CAN is enabled, or CAN while RS485_0 is enabled, fails with 409 CONFIGURATION_CONFLICT ("Cannot enable RS485_0 while CAN_0 is enabled"). Disable the other interface first.

Quick Start​

The RS485 bus supports enabling/disabling, termination resistance, transmitting, and receiving data.

import { AT1000 } from '@ikalogic/at1000';
let devices = await AT1000.findDevices(); // Find devices (returns host strings)
let tester = await AT1000.open(devices[0]); // Open the first detected device
await tester.reset(); // Reset the device to a known state
let rs485 = tester.com.rs485(1); // Access RS485_1 bus on AT1000

await rs485.configure({
baud_rate: 9600,
termination_resistors: true,
enabled: true
});

// Start receiving RS485 messages
await rs485.start_rx();

// Transmit a message over RS485
await rs485.tx([0xDE, 0xAD, 0xBE, 0xEF]);

// Receive data (returns an array of bytes)
let data_rx = await rs485.rx();

// Print received bytes
console.log("RS485 Data Received:", data_rx);

// Disable RS485_1 bus
await rs485.stop_rx();

API Reference​

Accessing RS485​

const rs485 = tester.com.rs485(id);

Parameters:

  • id (number / int / usize): The RS485 interface identifier (0-based index)

Returns: Rs485 instance / Result<Rs485, At1000Error> in Rust


Methods​

configure(config)​

Configures the RS485 interface parameters without changing the enabled state.

await rs485.configure({
baud_rate: 115200,
termination_resistors: true
});

Parameters:

  • config (Rs485ConfigPatch): Configuration object with optional properties:
    • enabled (boolean / bool / Option<bool>, optional): Enable or disable the interface
    • baud_rate (number / int / Option<u32>, optional): Baud rate, one of the standard rates listed below (300 to 4000000)
    • data_bits (number / int / Option<DataBits>, optional): Data bits per character (7 or 8; DataBits::Seven or DataBits::Eight in Rust)
    • parity (string / str / Option<SerialParity>, optional): Parity mode - 'none', 'odd', or 'even'. Mark and space parity are UART-only and rejected on RS485
    • stop_bits (string / str / Option<SerialStopBits>, optional): Stop bits - '1' or '2'. 1.5 stop bits are UART-only and rejected on RS485
    • termination_resistors (boolean / bool / Option<bool>, optional): Enable/disable 120Ω termination resistors

Valid baud rates: 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000

Default configuration (after tester.reset()): disabled, baud_rate 9600, 8 data bits, no parity, 1 stop bit (8N1), termination resistors off.

Returns: Promise<Rs485Config> / Rs485Config / Result<Rs485Config, At1000Error> - The updated configuration

Exceptions:

  • Throws validation error if baud_rate is outside the range [300, 20000000] (SDK check)
  • Throws error 400 INVALID_VALUE if baud_rate is not one of the valid baud rates
  • Throws validation error if parameters don't match expected types
  • Throws error 409 CONFIGURATION_CONFLICT when enabling RS485_0 while CAN is enabled

enable([config])​

Enables the RS485 interface and optionally applies configuration.

await rs485.enable({
baud_rate: 9600,
termination_resistors: false
});

Parameters:

  • config (Rs485EnableConfig, optional / Rs485ConfigPatch in Rust, required): Configuration to apply. In Rust, pass Rs485ConfigPatch::default() to keep the current settings; enable ignores the patch's enabled field and always enables the interface:
    • baud_rate (number / int / Option<u32>, optional): Baud rate, one of the standard rates listed above (300 to 4000000)
    • data_bits (number / int / Option<DataBits>, optional): Data bits per character (7 or 8; DataBits::Seven or DataBits::Eight in Rust)
    • parity (string / str / Option<SerialParity>, optional): Parity mode - 'none', 'odd', or 'even'. Mark and space parity are UART-only and rejected on RS485
    • stop_bits (string / str / Option<SerialStopBits>, optional): Stop bits - '1' or '2'. 1.5 stop bits are UART-only and rejected on RS485
    • termination_resistors (boolean / bool / Option<bool>, optional): Enable/disable termination resistors

Returns: Promise<Rs485Config> / Rs485Config / Result<Rs485Config, At1000Error> - The updated configuration with enabled: true

Exceptions:

  • Throws validation error if baud_rate is outside the range [300, 20000000] (SDK check)
  • Throws error 400 INVALID_VALUE if baud_rate is not one of the valid baud rates
  • Throws error 409 CONFIGURATION_CONFLICT when enabling RS485_0 while CAN is enabled

disable()​

Disables the RS485 interface.

await rs485.disable();

Returns: Promise<Rs485Config> / Rs485Config / Result<Rs485Config, At1000Error> - The updated configuration with enabled: false


tx(data)​

Transmits data over the RS485 interface.

// Send string
await rs485.tx("Hello, World!");

// Send byte array
await rs485.tx([0x48, 0x65, 0x6C, 0x6C, 0x6F]);

Parameters:

  • data (SerialDataInput / &[u8] in Rust): Data to transmit, either:
    • string: Text data (max 65536 characters)
    • number[]: Byte array (each byte 0-255, max 65536 bytes)
    • &[u8] (Rust): byte slice - write text as b"..." or text.as_bytes()

Returns: Promise<SerialData> / SerialData / Result<Vec<u8>, At1000Error> - The transmitted data as byte array (number[], Vec<u8> in Rust)

Exceptions:

  • Throws validation error if string exceeds 65536 characters
  • Throws validation error if array exceeds 65536 elements
  • Throws validation error if any byte value is outside the range [0, 255]
  • Throws error 400 INVALID_CONFIGURATION if the interface is disabled

start_rx()​

Starts buffering received data from the RS485 interface.

await rs485.start_rx();

Returns: Promise<void> / None / Result<(), At1000Error>

Note: start_rx() discards any data still pending on the port and switches the transceiver to receive. Data received after calling this method will be buffered and can be retrieved using rx().


stop_rx()​

Stops buffering received data from the RS485 interface.

await rs485.stop_rx();

Returns: Promise<void> / None / Result<(), At1000Error>


rx()​

Reads all buffered data received since the last start_rx() or rx() call. Call start_rx() first: unlike RS232, RS485 refuses rx() while reception is not started.

const receivedData = await rs485.rx();
console.log(receivedData); // number[]

Returns: Promise<SerialData> / SerialData / Result<Vec<u8>, At1000Error> - Received data as byte array (number[], Vec<u8> in Rust). The device buffers up to 65536 received bytes per interface; bytes received while the buffer is full are dropped until rx() empties it.

Note: This method returns all data accumulated since the last start_rx() or rx() call and clears the buffer.

Exceptions:

  • Throws error 400 INVALID_CONFIGURATION if the interface is disabled, or if start_rx() has not been called (or stop_rx() was called since)

Types​

Rs485Config​

Complete configuration object returned by configuration methods.

{
enabled: boolean,
baud_rate: number, // standard rate, 300 to 4000000
data_bits: number, // 7 or 8
parity: 'none' | 'odd' | 'even',
stop_bits: '1' | '2',
termination_resistors: boolean
}

Rust: ikalogic_at1000::Rs485Config

pub struct Rs485Config {
pub enabled: bool,
pub baud_rate: u32,
pub data_bits: DataBits,
pub stop_bits: SerialStopBits,
pub parity: SerialParity,
pub termination_resistors: bool,
}

pub enum DataBits {
Seven,
Eight,
}

#[non_exhaustive]
pub enum SerialStopBits {
One,
OnePointFive,
Two,
Unknown(String),
}

#[non_exhaustive]
pub enum SerialParity {
None,
Odd,
Even,
Mark,
Space,
Unknown(String),
}

Unknown(String) keeps a value reported by a newer firmware that this SDK version does not know, so a match on SerialStopBits or SerialParity needs a _ arm. The enums are shared with the UART: RS485 rejects Mark, Space and OnePointFive (InvalidInput in Rust, 400 INVALID_VALUE from the device).

Rs485ConfigPatch​

Partial configuration for the configure() method. All properties are optional.

{
enabled?: boolean,
baud_rate?: number, // standard rate, 300 to 4000000
data_bits?: number, // 7 or 8
parity?: 'none' | 'odd' | 'even',
stop_bits?: '1' | '2',
termination_resistors?: boolean
}

Rust: ikalogic_at1000::Rs485ConfigPatch (derives Default, so unset fields stay None)

pub struct Rs485ConfigPatch {
pub enabled: Option<bool>,
pub baud_rate: Option<u32>,
pub data_bits: Option<DataBits>,
pub stop_bits: Option<SerialStopBits>,
pub parity: Option<SerialParity>,
pub termination_resistors: Option<bool>,
}

Rs485EnableConfig​

Optional configuration for the enable() method.

{
baud_rate?: number, // standard rate, 300 to 4000000
data_bits?: number, // 7 or 8
parity?: 'none' | 'odd' | 'even',
stop_bits?: '1' | '2',
termination_resistors?: boolean
}

Rust has no separate enable type: enable() takes a Rs485ConfigPatch and sets enabled: true itself.

SerialDataInput​

Input data type for transmission.

string | number[]
  • string: Maximum 65536 characters
  • number[]: Maximum 65536 elements, each byte in range [0, 255]

Rust: &[u8] - the Rust SDK accepts bytes only. Write text as b"..." or text.as_bytes().

SerialData​

Output data type, always returned as a byte array.

number[] // Array of bytes (0-255)

Rust: Vec<u8>.


Usage Example​

import { AT1000 } from '@ikalogic/at1000';

// Find and connect to device
const devices = await AT1000.findDevices();
const tester = await AT1000.open(devices[0]);
await tester.reset(); // Reset the device to a known state

// Access RS485 interface 0
const rs485 = tester.com.rs485(0);

// Enable with 115200 baud rate and termination resistors
await rs485.enable({
baud_rate: 115200,
termination_resistors: true
});

// Start receiving data
await rs485.start_rx();

// Transmit data
await rs485.tx([0x01, 0x03, 0x00, 0x00, 0x00, 0x0A]);

// Wait for response
await new Promise(resolve => setTimeout(resolve, 100));

// Read received data
const response = await rs485.rx();
console.log("Received:", response);

// Stop receiving
await rs485.stop_rx();

// Disable interface
await rs485.disable();

Common Patterns​

Modbus RTU Communication​

// Configure for Modbus (typically 9600, 19200, or 115200)
await rs485.enable({
baud_rate: 9600,
termination_resistors: true
});

// Function to calculate CRC16 (Modbus)
function crc16(buffer) {
let crc = 0xFFFF;
for (let byte of buffer) {
crc ^= byte;
for (let i = 0; i < 8; i++) {
if (crc & 0x0001) {
crc = (crc >> 1) ^ 0xA001;
} else {
crc >>= 1;
}
}
}
return [crc & 0xFF, (crc >> 8) & 0xFF];
}

// Send Modbus request
const frame = [0x01, 0x03, 0x00, 0x00, 0x00, 0x0A];
const crc = crc16(frame);
await rs485.tx([...frame, ...crc]);

Half-Duplex Communication​

// RS485 is half-duplex - send then receive
await rs485.start_rx();

// Send query
await rs485.tx("QUERY\r\n");

// Wait for device to respond
await new Promise(resolve => setTimeout(resolve, 50));

// Read response
const response = await rs485.rx();

await rs485.stop_rx();

Multi-Drop Network​

// Configure with termination resistors only on end nodes
const isEndNode = true;
await rs485.enable({
baud_rate: 115200,
termination_resistors: isEndNode
});

// Address specific devices on the bus
const deviceAddress = 0x05;
await rs485.tx([deviceAddress, 0x10, 0x00, 0x01]);