J1939 Transport Protocol Reference Example (2025)

J1939 is a set of SAE standards that is built on top of CAN (Controller Area Network). Part of the standard defines how to deconstruct, transfer and reassemble CAN messages larger than 8 bytes. The J1939 standard calls this process Transport Protocol. This example shows how to implement this using LabVIEW and NI-CAN products.

1. J1939 Overview

J1939 is set of SAE standards commonly used in diesel-powered applications for communication and diagnostics between application components. The J1939 standard is defined in multiple documents corresponding to five of the seven OSI layers. J1939-11 defines the physical layer, J1939-21 defines the data link and transport layer, J1939-31 defines the network layer, and J1939-71/73 defines the application layer. J1939-81 describes network management.

The goal of this document is not to explain all these standards in detail. For this, please consult the SAE standards. Instead, we will look at the construction and transmission of messages as defined by J1939-21 using NI-CANand supported hardware.

2. J1939 Message Construction

J1939 messages are built on top of CAN 2.0b and make specific use of extended frames. Extended frames use a 29-bit identifier instead of the common 11-bit identifier. J1939-21 defines fields within this 29-bit identifier as shown below.

J1939 Transport Protocol Reference Example (1)Figure 1. J1939 29-bit Identifier Fields

The first three bits are the priority field. This field sets the message’s priority on the network and helps ensure messages with higher importance are sent/received before lower priority messages. Zero is the highest priority.

The next bit is reserved for future use. This field should be set to zero.

The next bit is the Data Page field. This is used to expand the maximum number of possible messages.

The next eight bits make up the Protocol Data Unit Format (PDU F) field. This is used to determine if the message is intended for a specific device on the network or if the message is intended for the entire network. If the value of PDU F is less than 240, the message is meant for a specific device. If the value is 240 or greater, the message is intended for all devices.

The next eight bits make up the Protocol Data Unit Specific (PDU S) field. The definition of this field is based on value of the PDU F field. If PDU F is intended for a specific device (less than 239), PDU S is interpreted as the address of that specific device. In this case, the PDU S field is referred to as the Destination Address field. This format is referred to as PDU 1. If PDU F is intended for all devices (greater than or equal to 240), PDU S is interpreted as a Group Extension field. This group extension is used to increase the number of possible broadcast messages. This format is referred to as a PDU 2.

Both formats are described below in picture form.

J1939 Transport Protocol Reference Example (2)Figure 2. PDU 1 Format

J1939 Transport Protocol Reference Example (3)Figure 3. PDU 2 Format

The last eight bits identify the address of the device that transmitted the current message. This is known as the Source Address Field.

On standard CAN networks, identifiers are used to uniquely define each message. This concept exists within J1939 as well. Because the priority and source address fields can change, they are not used for this purpose. This leaves the reserve, data page, PDU F and PDU S fields. This new combination of fields is referred to as the Parameter Group Number (PGN). Each message in J1939 must have its own unique PGN. The J1939-71 standard is responsible for assigning these unique PGNs to standard messages.

3. Addressing

Each device on the network has to have a unique address ranging from 0 to 254. These addresses are mainly used for PDU 1 messages and requests. In most cases, these addresses are static and pre-defined by the user. However, the J1939-81 standard does define a method of dynamic addressing.

4. Special Messages

Although J1939 uses the PDU F field mainly to specify if the message is PDU 1 or PDU 2, there are a few special values set aside for features like requests, dynamic addressing, and transport protocol. These values override the greater than/less than rules for PDU 1 and PDU 2 formats. Requests are used as an example below.

J1939 Transport Protocol Reference Example (4)Figure 4. Request PGN

Notice in this example that PDU Format is set to 234. Normally, this would be handled as a PDU 1. However, because this is a special message, the device knows to handle the message differently. In this specific case, it knows it has to respond to the originator of the request in a particular format as defined by the J1939-21 standard.

5. Transport Protocol

The J1939 standard allows single messages to have more than eight bytes of data, however, the CAN specification only supports eight byte data transfers. Therefore, the message must be sent in multiple packets. J1939-21 defines how to package, send and reassemble these messages within the constraints of the CAN specification. J1939-21 calls this transport protocol and specifies two types The first is Broadcast Announcement Message (BAM) which is similar to PDU 2 in that it is intended for the entire network. The second is called Connection Mode and is similar to PDU 1 in that it is intended for a specific device.

Both transports protocols work in a similar fashion. They use two special messages to facilitate these multi-packet transfers. The first is known as a Transport Protocol Connection Management message (TP.CM). The data in a TP.CM message contains connection commands (also called Control Byte), the PGN identifier of the multi-packet message and information about how to reconstruct the message. The second is called a Transport Protocol Data Transfer message (TP.DT). The data of a TP.DT message contains a sequence number in the first byte and uses the remaining seven bytes for the data of the multi-packet message.

6. BAM Messages

As mentioned above, Broadcast Announcement Messages are intended for the entire network. Therefore, no handshaking with other devices is required. The originating device first sends a TP.CM message with a control byte BAM (32). Next the originator starts sending all the data through the TP.DT messages until all the data has been sent. Below is an example to show the flow of a BAM message. Here, PGN 65260 is 20 bytes and is being transferred via BAM in 3 TP.DT packets.

J1939 Transport Protocol Reference Example (5)Figure 5. BAMData Transfer Example

7. Connection Mode Messages

Connection Mode is a peer to peer transfer. Therefore, handshaking and message acknowledgements are used to guarantee successful data transfer. First, the originating devices sends a TP.CM message with a control byte Request to Send (16). This is the originator asking the receiver if it is capable of receiving data. The receiver can then respond in various ways but normally it is with a TP.CM message containing control byte Clear to Send (17). The data of the TP.CM Clear to Send message contains the current sequence number to transfer as well as the number of TP.DTpackets allowed. The originator then sends TP.DT messages starting at the sequence requested and stops after reaching the number of TP.DT messages allowed. This process continues until all the data is transferred. The receiving device then has to send a TP.CM message with control byte EndofMsgACK (19) confirming that all the data was successfully received. Here is an example to illustrate a typical Connection Mode message. Here PGN 65259 is a 27 byte message requiring 4 TP.DT messages.

J1939 Transport Protocol Reference Example (6)Figure 6. Connection Mode Data Transfer Example

Note: It is acceptable to send a TP.CMClear to Send message indicating that zero packets can be transferred. This doesn’t mean the connection is invalid. Instead it means the receiving device isn’t ready for the data.It is also acceptable to send a TP.CMClear to Send message with a sequence number that has already been sent. This is often used when the receiver thinks the previous TP.DT messages were corrupt.

8. NI-CAN Reference Example Overview

This example is named J1939 NI CAN Frame Example.vi and it is located in the Examples\NI CAN Frame Example folder. It uses NI PCI/PXICANhardware and the NICANFrame API to show an implementation of reading and writing transport protocolmessages. The example code abstracts the packetization, transmission and reconstruction of these messages from the user such that there is no difference in the reading/writing of messages greater than eight bytes and messages of eight bytes or less.

9. NI-CAN Reference Example Front Panel

The front panel of this example contains four sections and is pictured below.

J1939 Transport Protocol Reference Example (7)Figure 7. J1939 NI CAN Frame Example Front Panel

The first is labeled Setup. In this section, the user can select the NI-CANport, set the baud rate (J1939 is typically 250k) and set the device address. These setting need to be entered before running the example.

The next section is labeled Control and Monitoring. This section is used for stopping the VI and viewing any errors that occur.

To the right of these sections is the Output section. Once the program is running, this section is used to send messages. The user enters the appropriate information into the Data to Send cluster and selects Send Message?. The Data array can be more than eight bytes. If it is, the VI will automatically transfer the message over the network using the correct transport protocol type, abstracting any difference between eight byte (or less) messages and messages greater than eight bytes. This will be discussed in more detail below.

The last section is labeled Input. This contains the CANFrame cluster. This cluster is where new incoming messages are displayed. This does not include messages like requests, address claims, and transport protocol messages. It only includes data messages. If a data message is greater than eight bytes and is transferred over transport protocol, it will be reconstructed in software (discussed below). Once this reconstruction occurs, the message will be displayed like any other standard message.

10. NI-CAN Reference Example Block Diagram

The block diagram of this example can be broken into four sections. These sections are Initialization, Writing Messages, Reading Messages, and Code Cleanup.

Initialization

Initialization in this example consists of configuring the CANport, opening the CANport, and initializing our J1939 code. For the J1939 specific code, this means creating multiple queue references, clearing any previously used memory and setting the current device address.

J1939 Transport Protocol Reference Example (8)

Figure 8. J1939 NI CAN Frame Example Initialization

Writing Messages

The writing messages section contains three loops. These loops are discussed below.

Cmd Loop

The first loop is the Cmd Loop and it is pictured below.

J1939 Transport Protocol Reference Example (9)

Figure 9. CmdLoop

This loop is controlled from the front panel. When the button Send Message? is selected, Data to Send is placed on the Process Outgoing queue to be read in the second loop (discussed below). To the user, this is all you have to do to output a message. The example will automatically use the correct transport protocol if a message over eight bytes is sent. If you want to output messages from anywhere else in the program, the process is the same. Simply queue that message on Process Outgoing and the example program will take care of the rest.

Process Outgoing Messages Loop

The second loop is called Process Outgoing Messages and is picture below.

J1939 Transport Protocol Reference Example (10)

Figure 10. Process Outgoing Messages Loop

This loop contains two J1939 VIs. The first is called J1939 Process Outgoing Messages. This VI first reads all messages off the Process Outgoing queue. Then, it determines if the message is eight bytes or less. If it is, it queues the message to the third loop (discussed below). However, if the message is greater than eight bytes, the VIdetermines if the message requires BAM or Connection Mode to transfer. It then opens the appropriate transport protocol connection locally and queues the messages necessaryto open that connection on the network to the third loop.

The second VI is called J1939 Check Outgoing TPTimeouts. It is responsible for checking if any of the open transport protocol connections are able to transfer data packets (TP.DTmessages). If any of these packets can be transferred, they are queued to the third loop.

Output Processed Outgoing Messages Loop

The third loop is named Output Processed Outgoing Messages and is pictured below.

J1939 Transport Protocol Reference Example (11)Figure 11. Output Processed Outgoing Messages Loop

This loop simply reads any messages on the queue from the second loop and outputs them on the CANport. This queue is named Processed Outgoing.

Reading Messages

The reading messages section contains two loops. These loops are discussed below.

Process Incoming Messages Loop

The first loop is called Process Incoming Messages and is pictured below.

J1939 Transport Protocol Reference Example (12)Figure 12. Process Incoming Messages Loop

This loop first checks if there are any messages on the CAN port. If messages exist, those messages are read and passed to a VI called J1939 Process Incoming Messages. This VI processes one CAN Frame at a time. It first filters out any messages that aren't intended for the device. Then, if the message is intended for the device, it determines the message type. If the message is a standard PDU 1 or PDU 2 message, it is queued to the second loop (discussed below).

In the case that the message is a transport protocol message, it determines if the message is for a message being generated or received by the device and handles it appropriately. It also waits until all messages are received and reassembled for a specific PGN before queuing the completed message to the second loop. The user will never see any of the transport protocol messages, just the finished message.

For other special messages, like requests, address claiming, etc. there are just stubs that don't currently do anything. These stubs could be implemented such that more J1939 features are available but that will be the responsibility of the user and outside of the scope of this example.

Read Processed Incoming Messages

The second loop is called Read Processed Incoming Messages and is pictured below.

J1939 Transport Protocol Reference Example (13)

Figure 13. Read Processed Incoming Messages Loop

The loop returns completed messages. Every message will be in the same format, even if the message was received via a form of transport protocol. The only difference is the data will be over eight bytes. From here, you can process the message.

Code Cleanup

In this example, the last thing we do is close the NI-CAN reference. No clean up is necessary for the J1939 code. This section is pictured below.

J1939 Transport Protocol Reference Example (14)

Figure 14 J1939 NI CAN Frame Example Code Clean Up

11. cRIO Reference Example Overview

This example is named J1939 cRIOExample.vi. It shows how to implement the reading and writing of transport protocolmessages on CompactRIO. This example functions in the same way as the NI-CANexample discussed above. There are no difference in terms of the J1939 specific code. However, there are some differences between the examples at the top level due to the different platforms being used. These differences are discussed below.

Note: To open this VI, first open the project named J1939 cRIO Example Project.lvproj that resides in the Examples\cRIO FPGA Example folder. Once the project is open, expand the RTCompactRIOTarget inside and double click on the J1939 cRIOExample VI.

12. cRIOReference Example Project

The targeting of a CompactRIO requires the use of the LabVIEWProject. Our project is called J1939 cRIOExample Project and is pictured below.

J1939 Transport Protocol Reference Example (15)

Figure 15. J1939 cRIO Example Project

The project contains configuration information about our CompactRIO. This includes information like IPaddress, FPGAtarget type and IO modules. Note the NI 9853 High Speed CANmodule in slot 1 of our FPGATarget. This is what we are using to read and write our CANMessages.

Also, notice that there are two VIs in this project. One is under the RTCompactRIOTarget and is called J1939 cRIOExample.vi. This is our top level VI. The other VI is under FPGATarget and is called J1939 cRIOExample_FPGA Main. This VI is responsible for reading and writing CANmessages. It is started and controlled by our top level VI.

Last, take notice of the two DMAchannels named CANOutgoing and CANIncoming. These two channels are used to transfer CANmessages between the cRIO and FPGA programs.

13. cRIO Reference Example Front Panel

The front panel of the cRIO reference example is the same in function as the NI-CANexample above. The only difference is that the baud rate and CAN Port aren't available as setup parameters. These parameters have to be set using the LabVIEW project. By default, this example uses port 0 of a NI9853 in slot 1 with a 250k baud rate. Please consult your module documentation and LabVIEWhelp for more details on setting these parameters.

14. cRIO Reference Example Block Diagrams

The block diagram can be broken into the same four sections as the NI-CANexample. Only the differences will be discussed. For additional information, please review the sections above.

Initialization

The differences in the cRIOexample initialization section are hardware specific only. Instead of initializing our NI-CANhardware and Frame API, we initialize and start our FPGA VI (J1939 cRIOExample_FPGA Main). This is pictured below.

J1939 Transport Protocol Reference Example (16)

Figure 16 J1939 cRIO Example Initialization

Writing Messages

The writing of messages happens on the FPGATarget when using a CompactRIO. This requires two VIs, one running on the FPGA and one running on the CompactRIOcontroller. It also requires a mechanism for transferring data between these two VIs. These are discussed below.

CompactRIOCode

Writing messages on the CompactRIO has three loops just as the NICANexample above. The only loop that is different is the Output Processed Outgoing Messages Loop displayed below.

J1939 Transport Protocol Reference Example (17)Figure 17. Output Processed Outgoing Messages Loop

This loop still reads from the Processed Outgoing queue but instead of outputting a CANmessage to the NICANFrame driver, it writes it to a DMAFIFO called CANOutgoing. This DMAFIFO sends the data to the VIrunning on the FPGA.

FPGACode

In the FPGA code, there is a loop called Write to CANModule Loop, pictured below.

J1939 Transport Protocol Reference Example (18)Figure 18. Write to CANModule Loop

This loop reads from the DMAFIFOand constructs a CANMessage. It then sends this message to the CANPort.

Reading Messages

Reading messages with the CompactRIOexample are broken into two pieces. One piece runs on the CompactRIOcontroller and the other runs on the FPGATarget. These are discussed below.

FPGACode

When we read a CANmessage on CompactRIO, we actually need to start with the FPGA code. The FPGA VI contains a second loop called Read CANModule Loop and it is pictured below.

J1939 Transport Protocol Reference Example (19)

Figure 19. Read CANModule Loop

In this loop, we check for any new messages. If none are available, we timeout and do nothing. If messages are available, we send the data into the DMAFIFO named CANIncoming. This sends the message up to the host.

CompactRIOCode

On the CompactRIOside, we read any new messages sent on CANIncoming in the Process Incoming Messages Loop, shown below.

J1939 Transport Protocol Reference Example (20)Figure 20. Process Incoming Messages Loop

When a message is received, we format it to a standard CANcluster and pass it to the J1939 Process Incoming Messages.vi. At this point, this loop is exactly the same as the NICANFrame example above.

The rest of the code for reading messages is the same as described above.

Code Cleanup

The only difference is the code cleanup section is that we close the FPGA reference instead of the NI-CANreference.

J1939 Transport Protocol Reference Example (21)

Figure 21. J1939 cRIO Example Code Clean Up

15. NI-XNET Example Overview

This example is named J1939 NI-XNET Frame Example.vi and it is located at Examples\NI-XNET Frame Example folder. It uses NI-XNET PCI/PXICANhardware and the NI-XNET API to show an implementation of reading and writing transport protocolmessages. The example code abstracts the packetization, transmission and reconstruction of these messages from the user such that there is no difference in the reading/writing of messages greater than eight bytes and messages of eight bytes or less.

16. NI-XNET Example Front Panel

The front panel of the NI-XNET reference example is the same in function as the NI-CANexample above. The only difference is the frame cluster uses the NI-XNETCANframe cluster instead of the NI-CANframe cluster. The other difference is that the CANport can be selected with an IO Control. The IO control automatically detects which CANports are available on your system.

17. NI-XNETExample Block Diagram

The NI-XNETexample is very similar to the NI-CANexample, so we will only show the main differences here.

Initialization

Initialization in this example consists of creating an NI-XNETinput stream session using IO Control from the front panel to select the CANport. The input stream session will enable us to read every frame off the bus. We also need to set the baudrate for our session. We also initialize our J1939 code. For the J1939 specific code, this means creating multiple queue references, clearing any previously used memory and setting the current device address.

J1939 Transport Protocol Reference Example (22)

Figure 22. NI-XNETExample Initialization

Writing Messages

The only difference in the NI-XNETExample (from the NI-CANexample) is how we actually output the messages on the bus, using the Output Processed Outgoing Messages Loop.

Output Processed Outgoing Messages Loop

In this loop, we convert the frames from the J1939 format to the NI-XNETframe format and write them to the bus.

J1939 Transport Protocol Reference Example (23)

Figure 23. NI-XNETOutput Processed Outgoing Messages Loop

Reading Messages

Process Incoming Messages Loop

This loop first checks if there are any messages on the CAN port. If messages exist, those messages are read and passed to a VI called J1939 Process Incoming Messages. This is very similar to the NI-CANversion.

J1939 Transport Protocol Reference Example (24)

Figure 24. NI-XNET Process Incoming Messages Loop

If you are using NI-CANSeries 2 hardware or CompactRIO CANProducts (NI 9852 and NI-9853) modules:

J1939 Transport Protocol Reference Example (2025)
Top Articles
Latest Posts
Recommended Articles
Article information

Author: Dan Stracke

Last Updated:

Views: 5711

Rating: 4.2 / 5 (43 voted)

Reviews: 82% of readers found this page helpful

Author information

Name: Dan Stracke

Birthday: 1992-08-25

Address: 2253 Brown Springs, East Alla, OH 38634-0309

Phone: +398735162064

Job: Investor Government Associate

Hobby: Shopping, LARPing, Scrapbooking, Surfing, Slacklining, Dance, Glassblowing

Introduction: My name is Dan Stracke, I am a homely, gleaming, glamorous, inquisitive, homely, gorgeous, light person who loves writing and wants to share my knowledge and understanding with you.