Supported platforms: CODESYS 2.3, CODESYS 3.5

 

J1939 (FB)

Description

J1939 FB is the main function block of the library. Other main functions of the library are called by instance of function block J1939.  The receiving of J1939 messages is handled with callback programs. J1939 handles receiving and sending of both short and multi packet PGN messages.

Initialization

This function block initializes itself during the first call of J1939 instance.  On initialization the J1939_InitVXD is called, which initializes the received PGN messages for the CAN bus. All J1939 application variables and structures must be built up before calling an instance of J1939.   

Initialization of J1939 variables

J1939 Configuration is done via PGN and SPN structures, which are connected via pointers to each other and to the actual data (Picture 1). Both received and transmitted  PGNs are initialized in the same manner.  The PGNs are built by reserving data areas for the received SPN data. This means, declaring a variable for the SPN data (e.g.  DslEng1_EngRqedSpeed_SpeedLimit) . Then an array for SPNs must be declared (e.g. DslEng1_PGN_TSC1_SPNs). The size of the  array is the number of SPNs in the PGN.  The SPN data pointer is set to the SPN array (6).  The pointer of the SPN array is given to the PGN (4). Also, the correct size of the SPN must be set to the PGN (5).  

 

Combining of all PGN's for one CAN bus is done after all PGNs and SPN's are initialized.  It is suggested that one physical CAN bus uses only one instance of J1939, even though several instances can be used.  All PGN's are combined together by an array of PGN pointers, which have all the RX or TX PGN pointers for one physical CAN bus. The PGN structures have the destination and source addressed for all devices used in the J1939.  The array of  PGN pointers have the pointers to all the PGN's (3). TX and RX PGN's have their own arrays. Both received and transmitted PGNs are connected to instance of J1939 by PGN array pointer (1) and the number of PGNs(2).

 

Codesys 2.3Codesys 2.3

It is also possible to add new transmit or receive PGNs after J1939 has been initialized. This is done by using function J1939_AddPgn. In this case only the array of PGN pointers is required and it needs to have empty slots where new PGN pointer can be added.

 

Codesys 3.5Codesys 3.5

It is also possible to add new transmit or receive PGNs after J1939 has been initialized. This is done by using J1939 function block's method AddPgn. In this case only the array of PGN pointers is required and it needs to have empty slots where new PGN pointer can be added.

 

Picture 1. Configuration of received PGNs.

Error codes during initialization

Name of error

Description

J1939_ERR_pRxPGNNULL

i_pRxPGNs pointer null, when number of Rx PGNs > 0

J1939_ERR_pSPNNULL

SPN pointer not initialized.

J1939_ERR_pRxPGNNULL

pRxPGN pointer null in pointer array

J1939_ERR_pSPNDataNULL

SPN data pointer null.

 

Using J1939

CODESYS 2.3CODESYS 2.3

J1939 function block calls two functions, J1939_MonitorMessages and J1939_SendHandler, directly every time it is called.  All data variables are in the same format as in J1939 SPNs, so no conversion is done in J1939. Only little/big endianness is handled by J1939.  The diagnosed result of the target device endian type can be read via boolean variable G_BigEndian.  The G_BigEndian variable is true, when the target device is big endian type.

 

The validity of received data can be checked from the DataValid member of the J1939_PGN structure. If the received message is long (multi packet), the Status member of the J1939_PGN can also be used to diagnose the data transmission.

 

Receiving of J1939 messages can be monitored via Status and DataValid members of J1939_PGN structure.  If there is an error, DataValid is false and Status is negative.  When the message is received successfully, Status is J1939_PGN_DataReady and DataValid is true.  Receiving of a message sets NewData to true for one program cycle.  This can be used for triggering the data conversion from J1939 format to your own value format. On every program cycle, the library checks the timeout of all J1939 received PGNs.  If no new PGN message is received after 3 * J1939_PGN.CycleTime is elapsed, the PGN validity for the specific PGN is set as false.

 

Sending of J1939 messages is done automatically by setting the CycleTime variable, which is the period for sending a new message.  Data validity of a sent message is not checked.  Sending of messages can also be done "manually" by SendTrigger when CycleTime is set  to zero ( 0 ).

Only one type of sending method is possible at a time.    

Limitations

J1939 transport protocol (TP):

It is possible to send one broadcast transfer per source address.

It is possible to receive one broadcast transfer per source address.

 

It is possible to send one destination specific transfer per SA-DA connection.

It is possible to receive one destination specific transfer per SA-DA connection.

 

ISO 11783-3 extended transport protocol (ETP):

 

It is possible to send one transfer per SA-DA connection.

 

 

All J1939 variables and structures must be properly initialized before calling J1939 FB.  All the used pointers in the structures must be initialized.  The given number of PGNs must match the size of array of PGN pointers.

 

SPN sizes of 17..32 bits must always have 4 bytes of data buffer. This limitation comes from little/big endian conversion.  

 

Send interval accuracy depends of the program cycle time. A shorter cycle time gives a more accurate interval to the message sending.  Interval accuracy is same as one program cycle time.  So, if the program cycle time is 10 ms, the maximum interval can be a  little less than 10 ms + CycleTime (Tx PGN transmit interval).    

 

J1939 handles little / big endianness of the target devices ( IO-module / display ), so the byte order is switched when needed.  The SPN size affects the conversion: Sizes of 9..16 bits swap two bytes and sizes of 17..32 bits swap four bytes. Although SPN size of 32 bits is not recommended, the SPN size can be set over 32 bits, but then little/big endian conversion is not done.  

 

If initialization fails, messages may either drop out completely or partially. Increasing of the values below may help the situation.  Default values can be overrun, if needed.  

G_J1939_MAX_SIZE_OF_LONG_TRANSFER

G_J1939_MAX_NUMBER_OF_LONG_TRANSFER

 

Value of the G_J1939_MAX_SIZE_OF_LONG_TRANSFER must be greater or equal to the longest DataLength of all J1939 PGN's.

 

Inputs and outputs

CODESYS 2.3CODESYS 2.3

Inputs

Input variable name

Data type

Range

Description

i_DrvNbr

BYTE

0..G_NUMBER_OF_LAST_CAN_BUS

Number of CAN bus to monitor/manage.

i_pRxPGNs

POINTER TO J1939_pPGN

-

Pointer to the list of PGNs (pointers) to receive.

i_NumberOfRxPGNs

WORD

0...65535

Max number of PGNs in the list of PGNs to receive

i_pTxPGNs

POINTER TO J1939_pPGN

-

Pointer to the list of PGNs (pointers) to transmit.

i_NumberOfTxPGNs

WORD

0...65535

Max number of PGNs in the list of PGNs to transmit

Outputs

Output variable name

Data type

Range

Description

Status

INT

-32768..0

0 = OK,  negative = error.

o_TxPgnCount

INT

0.. i_NumberOfTxPGNs

Amount of defined Tx PGNs

o_RxPgnCount

INT

0.. i_NumberOfRxPGNs

Amount of defined Rx PGNs

o_InitReady

BOOL

TRUE/FALSE

J1939 initialized flag

 

CODESYS 3.5CODESYS 3.5

Inputs

Input variable name

Data type

Range

Description

i_CANChannel

CANVXD_API.ICANVXD

 

CAN channel interface.

i_pRxPGNs

POINTER TO J1939_pPGN

 

Pointer to the list of PGNs (pointers) to receive.

i_NumberOfRxPGNs

WORD

0...65535

Number of PGNs in the list of PGNs to receive.

i_pTxPGNs

POINTER TO J1939_pPGN

 

Pointer to the list of PGNs (pointers) to transmit.

i_NumberOfTxPGNs

WORD

0...65535

Number of PGNs in the list of PGNs to transmit.

Outputs

Output variable name

Data type

Range

Description

o_Status

INT

-32768..0

See J1939_ReturnCodes

0 = OK,  negative = error.

o_TxPGNCount

WORD

 

Amount of defined Tx PGNs

o_RxPGNCount

WORD

 

Amount of defined Rx PGNs

 

Methods (CODESYS 3.5)

EnableRequestPGNsEnableRequestPGNs

EnableRequestPGNs (Method)

Description

This method enables the receiving of RQST PGNs. To enable RQST PGNs, the method must be called in initialization before calling the main J1939 function block.

 

Limitations

The method must be called in init before calling the main J1939 function block.

Inputs

No inputs

Outputs

No return value or outputs

 

Example code

Definitions:

 

VAR

     

J1939_CAN1: J1939;

 

END_VAR

 

 

Init:

 

 

J1939_CAN1.EnableRequestPGNs();

 

 

 

 

Separate functions are changed to J1939 FB public methods in CODESYS 3.5:

 

AddPGNAddPGN

AddPgn (Method)

Description

This method is used to add PGNs on runtime. If PGN is set as received, the method adds COB-ID to CANVXD callback list.

 

Limitations

J1939 server must have free PGN slots, otherwise it is not possible to add PGN and method returns error code.

 

Return values

Inputs

Input variable name

Data type

Range

Description

i_RxPGN

BOOL

TRUE/FALSE

Defines if PGN is RX or TX PGN

(TRUE = RX , FALSE = TX)

i_pPGN

POINTER TO J1939_PGN

≠ 0

Pointer to PGN definition structure.

Outputs

Data type

Range

Description

INT

J1939_ReturnCodes

Negative number --> error

 

Example code

Definitions:

 

VAR

     

J1939_CAN1: J1939;

Tx_PGN: J1939_PGN;

Tx_SPNs: ARRAY[1..2] OF J1939_SPN;

Tx_Data1: WORD;

Tx_Data2: WORD;

END_VAR

 

 

Init:

 

Tx_PGN.pSPNs:=ADR(Tx_SPNs);

Tx_PGN.PGN_Number:=16#FF00;

Tx_PGN.SourceAddress:=1;

Tx_PGN.Destination:=255;

Tx_PGN.CycleTime:=0;

Tx_PGN.DataPage:=0;

Tx_PGN.NumberOfSPNs:=2;

Tx_PGN.Priority:=6;

Tx_PGN.DataLength:=4;

 

Tx_SPNs[1].Size:=16;

Tx_SPNs[1].pData:=ADR(Tx_Data1);

Tx_SPNs[2].Size:=16;

Tx_SPNs[2].pData:=ADR(Tx_Data2);

 

J1939_CAN1.AddPgn(

i_RxPGN := FALSE,

i_pPGN := ADR(Tx_PGN)

);

 

.

AddRequestPGNCallbackAddRequestPGNCallback

AddRequestPGNCallback (Method)

Description

This method adds callback for received EA00h requests. Requested PGN value is compared against EA00h message's data and callback is triggered when PGN is found. Callback is implemented with IRequestPGNCallbackHandler interface.

 

Pointers to PGN data structure and user specific data can be given as parameters to callback. Callback data is accessed through  callback's HandlePGN method.

 

Limitations

Amount of callbacks are limited by parameter G_J1939_MAX_NBR_OF_RQST_CALLBACKS.

 

 

It is required to execute EnableRequestPGNs method to J1939 function block before J1939 initialization. Then J1939 function block will handle the received request PGNs (EA00h).

 

 

Inputs

Input variable name

Data type

Range

Description

i_RequestedPGN

WORD

0…65535

PGN value which is compared to EA00 data

i_itfCallback

IRequestPGNCallbackHandler

 

Interface to request callback handler

i_pPGNData

DWORD

≠ 0

Callback parameter: Pointer to PGN data structure.

i_pUserData

DWORD

≠ 0

Callback parameter: Pointer to user specific data

Outputs

Data type

Range

Description

INT

J1939_ReturnCodes

Negative number --> error

 

 

Example code

The following example shows how to add request callback to transmit PGN.

 

The following shows callback POU that implements IRequestPGNCallbackHandler.

 

Callback function block

 

 

FUNCTION_BLOCK RequestPGNCallback IMPLEMENTS IRequestPGNCallbackHandler

 

 

HandlePGN method

 

 

METHOD HandlePGN

VAR_INPUT

  (* Callback data pointer *)

  i_pData : POINTER TO EPEC_J1939.J1939_RequestedPGNData;

END_VAR

VAR

  pPGN:POINTER TO J1939_PGN;

  pCallbackData:POINTER TO DWORD;

  DA:BYTE;

  SA:BYTE;

END_VAR

 

 

Code in HandlePGN

 

 

IF i_pData <> 0 THEN

  pPGN := i_pData^.pPGNData;

  pCallbackData := i_pData^.pUserData;

  DA := i_pData^.DA;

  SA := i_pData^.SA;

 

  IF 0 <> pPGN AND 0 <> pCallbackData THEN

(*do something*)

  END_IF

END_IF

 

The following shows how to initialize callback to transmit PGN.

 

Definitions:

 

VAR

  J1939_CAN1: J1939;

  Tx_PGN:J1939_PGN;

  Tx_SPNs:ARRAY[1..2] OF J1939_SPN;

  Tx_Data1: WORD;  

  Tx_Data2: WORD;

  

  CallbackData:DWORD;

  Callback: RequestPGNCallback;

END_VAR

 

 

Init:

 

Tx_PGN.pSPNs:=ADR(Tx_SPNs);

Tx_PGN.PGN_Number:=16#FF00;

Tx_PGN.SourceAddress:=1;

Tx_PGN.Destination:=255;

Tx_PGN.CycleTime:=0;

Tx_PGN.DataPage:=0;

Tx_PGN.NumberOfSPNs:=2;

Tx_PGN.Priority:=6;

Tx_PGN.DataLength:=4;

Tx_SPNs[1].Size:=16;

Tx_SPNs[1].pData:=ADR(Tx_Data1);

Tx_SPNs[2].Size:=16;

Tx_SPNs[2].pData:=ADR(Tx_Data2);

 

J1939_CAN1.AddPgn(

i_RxPGN := FALSE,

i_pPGN := ADR(Tx_PGN)

);

 

J1939_CAN1.AddRequestPGNCallback(

i_RequestedPGN := 16#FF00,

i_itfCallback  := Callback,

i_pPGNData := ADR(Tx_PGN),

i_pUserData := ADR(CallbackData)

);

 

 

 

 

 

ChangePGNConfigurationChangePGNConfiguration

J1939_ChangePGNConfiguration (Method)

Description

This method is used to change the PGN source or destination address (or both) on runtime.

If the PGN is set as received, the function also changes CANVXD callback COB-ID correctly. MASK is not changed.

 

Inputs

Input variable name

Data type

Range

Description

i_RxPGN

BOOL

TRUE/FALSE

Defines if PGN is RX or TX PGN (TRUE = RX , FALSE = TX)

i_pPGN

POINTER TO J1939_PGN

≠ 0

Pointer to PGN structure

i_NewSourceAddress

WORD

0…255, 65535

0 - 255 Value of the new source address, FFFFh source address is not changed.

i_NewDestinationAddress

WORD

0…255, 65535

0 - 255 Value of the new destination address, FFFFh destination address is not changed.

Outputs

Data type

Range

Description

INT

J1939_ReturnCodes

Negative number --> error

 

 

Example code

 

Definitions:

 

VAR

J1939_CAN1: J1939;

Rx_PGN:J1939_PGN;

Rx_SPNs:ARRAY[1..2] OF J1939_SPN;

Rx_Data1: WORD;

Rx_Data2: WORD;

address_changed:BOOL;

END_VAR

 

 

Init:

 

Rx_PGN.pSPNs:=ADR(Rx_SPNs);

Rx_PGN.PGN_Number:=16#FF00;

Rx_PGN.SourceAddress:=1;

Rx_PGN.Destination:=255;

Rx_PGN.CycleTime:=0;

Rx_PGN.DataPage:=0;

Rx_PGN.NumberOfSPNs:=2;

Rx_PGN.Priority:=6;

Rx_PGN.DataLength:=4;

 

Rx_SPNs[1].Size:=16;

Rx_SPNs[1].pData:=ADR(Rx_Data1);

Rx_SPNs[2].Size:=16;

Rx_SPNs[2].pData:=ADR(Rx_Data2);

 

J1939_CAN1.AddPgn(

i_RxPGN := TRUE,

i_pPGN := ADR(Rx_PGN)

);

 

 

The following changes the source address of PGN and leaves destination address unchanged.

 

Code:

 

IF address_changed THEN

J1939_CAN1.ChangePGNConfiguration(

i_RxPGN := TRUE,

i_pPGN := ADR(Rx_PGN),

i_NewSourceAddress := 2,

i_NewDestinationAddress := 16#FFFF

);

END_IF

 

 

 

 

Errors

Example code

J1939 is automatically initialized in MultiTool Creator code template. See Using J1939 topic for examples of code template structures.

 

See also

 

Data types:

 

Interfaces (CODESYS 3.5)

 

 

Source file Topic000442.htm

Last updated 13-Jun-2024