Kvaser J1939 Library
Send and Receive J1939 Messages

Sending J1939 Messages

Sending J1939 messages is done using the function j1939_write. It takes a channel handle and a J1939WriteParams struct containing the message ID and payload. The function places the message in the transmission queue and returns immediately.

The J1939WriteParams struct also contains a request handle that can be used to get a callback notification when the message has been sent, see J1939TxCallback. If request_handle is 0 or if no transmit ack callback has been registered then no callback will be generated.

Example. Sending a J1939 message.

// Prepare payload and header
uint8_t data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
const J1939WriteParams message = {
.id = {
.pgn = 0x004400,
.priority = 6,
.src_addr = 0xAA,
.dest_addr = 0xBB,
},
.payload = data,
.payload_length = 8,
.request_handle = 55,
};
// Send the message
int status = j1939_write(channel_handle, message);
if (status != J1939_STATUS_OK) {
// Handle error
}
J1939Result j1939_write(J1939ChannelHandle hnd, const J1939WriteParams message)
Send a J1939 message.
@ J1939_STATUS_OK
Operation completed successfully.
Definition: kvj1939lib_types.h:18
uint32_t pgn
The message PGN. The lower byte is 0 for PDU1 messages.
Definition: kvj1939lib_types.h:103
A struct that holds the parameters for a J1939 write request.
Definition: kvj1939lib_types.h:115
struct J1939Identifier id
The J1939 identifier of the message to be sent.
Definition: kvj1939lib_types.h:117

Sending multi-frame messages

Multi-frame messages are J1939 messages with a payload larger than 8 bytes, up to 1785 bytes. They are sent using the Transport Protocol (TP) defined in the J1939 standard and can be either directed to a single destination address (using RTS/CTS) or broadcast (using BAM).

In order to send multi-frame messages using TP, an address must be claimed, see Address Claiming. The Kvaser J1939 library allows the application to send both BAM and RTS/CTS messages from any source address but it will only receive RTS/CTS messages directed to the claimed address.

Note
When sending multi-frame messages from a source address that has not been claimed, the application must ensure that no other node on the network is using the same source address. Otherwise, message collisions may occur.

Sending multi-frame messages is done in the same way as single-frame messages, using j1939_write. The library will automatically handle the Transport Protocol (TP) for messages longer than 8 bytes, up to 1785 bytes.

Selecting BAM or RTS/CTS transport mode

The J1939 standard allows for sending PDU1 (destination-specific) messages using either RTS/CTS or BAM, as well as sending PDU2 (broadcast) messages using either BAM or RTS/CTS.

The transport mode is determined by the dest_addr field in the message ID.

  • To send using RTS/CTS, set dest_addr to the desired destination address (0x00 - 0xFD).
  • To send using BAM, set dest_addr to 0xFF (global address).

Receiving J1939 Messages

Messages can be received either by registering a receive callback function using j1939_register_callbacks or by reading messages using j1939_read.

Messages sent from the same channel, or by another channel using the same CAN hardware channel, will by default be echoed back and received by the channel. To stop echoing messages, use j1939_set_channel_option to disable J1939_OPTION_TX_ECHO.

Receive callback

When a receive callback function is registered, it will be called by the library in a separate thread whenever a new J1939 message is received on the channel, see J1939RxCallback. The application can supply a user-defined context pointer that will be passed to the callback function along with the channel handle and the received message. Registering callbacks must be done before the channel is opened.

Example. Registering a callback for receiving messages.

// Rx callback function
void my_rx_callback(uint32_t channel, void* context, J1939Identifier id, uint64_t timestamp,
const uint8_t* payload, uint32_t payload_length, bool error) {
if (!error) {
// Handle received message
handleMessage(id, payload, payload_length);
}
}
A struct that represents a J1939 identifier.
Definition: kvj1939lib_types.h:101
// Register Rx callback function
int status = j1939_register_callbacks(channel_handle, my_context_ptr, my_rx_callback, NULL, NULL);
if (status != J1939_STATUS_OK) {
// Handle error
}
J1939Result j1939_register_callbacks(J1939ChannelHandle hnd, void *context, J1939RxCallback rx_callback, J1939TxCallback tx_callback, J1939AcCallback ac_callback)
Set callbacks for a J1939 channel.

Reading messages

The j1939_read function can be used to read messages in either blocking or non-blocking mode. The timeout parameter specifies the maximum time to wait for a message. If timeout is set to 0, the function will return immediately if no message is available (non-blocking).

Upon successful read, the function returns a J1939ReadResult struct containing the received message header and the message payload is copied into the provided buffer.

Example. Receive messages using j1939_read.

// Allocate buffer for received message
uint8_t data[1785];
// Receive messages, blocking with 1000 ms timeout
J1939ReadResult read_result = j1939_read(channel_handle, buffer, sizeof(buffer), 1000);
if (read_result.result == J1939_STATUS_OK) {
// Message received successfully
handleMessage(read_result.id, data, read_result.payload_length);
} else if (read_result.result == J1939_STATUS_TIMEOUT) {
// Reading timed out
} else {
// Handle other errors
}
J1939ReadResult j1939_read(J1939ChannelHandle hnd, uint8_t *buffer, uint32_t buffer_len, int32_t timeout_ms)
Read a J1939 message.
@ J1939_STATUS_TIMEOUT
The operation timed out.
Definition: kvj1939lib_types.h:28
A struct that holds the result and header information for a J1939 read operation.
Definition: kvj1939lib_types.h:131
J1939Identifier id
The J1939 identifier of the message, if successful.
Definition: kvj1939lib_types.h:135
J1939Result result
The result of the operation.
Definition: kvj1939lib_types.h:133
uint32_t payload_length
The length of the message data, if successful.
Definition: kvj1939lib_types.h:139