J1939 Documentation
Version 4.16.00
Loading...
Searching...
No Matches
PGN Handling

The J1939 Protocol Stack keeps all PGNs which are handled by the device in a list. The list is added to the J1939 Protocol Stack by the function J1939_PgnAddList(). The elements inside this list are administrated by the user.

PGN Reception

A PGN which shall be received by the J1939 Protocol Stack has to be marked with the symbol J1939_MSG_RCV inside the control field of the structure J1939_PGN_Entry_ts (J1939_PGN_Entry_s::uwControl).

The following example shows the setup of a PGN with a value of 0 which is received by the ECU.

// Torque/Speed Control 1 (TSC1)
//
{ J1939_PRIORITY_INFO | J1939_MSG_RCV, // PDU Control
(uint32_t) 0, // PGN value
(uint16_t) 2000, // Reception timeout value
(uint16_t) 0, // Counter
(uint8_t) 0, // DA
(uint8_t) 0, // reserved
(uint16_t) 8, // Data size
ECU_Pgn00000 // PGN handler
},
#define J1939_PRIORITY_INFO
Definition j1939_defs.h:231
#define J1939_MSG_RCV
Definition j1939_defs.h:248

Upon reception of the TSC1 PDU the function ECU_Pgn00000() is called.

static int16_t ECU_Pgn00000(uint8_t * pubDataV, uint16_t uwSizeV, uint8_t ubSrcAddrV, uint8_t ubNetV)
{
J1939_Payload_ts *ptsPayloadT = (J1939_Payload_ts *) pubDataV;
uint16_t uwSpeedT;
//---------------------------------------------------------------------------------------------------
// silence warning for unused parameters
//
(void) uwSizeV;
(void) ubSrcAddrV;
(void) ubNetV;
//---------------------------------------------------------------------------------------------------
// copy received data
//
uwSpeedT = ptsPayloadT->aubByte[2];
uwSpeedT <<= 8;
uwSpeedT += ptsPayloadT->aubByte[1];
tsECU_ControlS.ubDevice = ubSrcAddrV;
tsECU_ControlS.ubMode = ptsPayloadT->aubByte[0];
tsECU_ControlS.uwSpeed = uwSpeedT;
tsECU_ControlS.ubTorque = ptsPayloadT->aubByte[3];
return ((int16_t) eJ1939_HANDLER_RESULT_OK);
}

PGN Transmission

A PGN which shall be transmitted by the J1939 Protocol Stack has to be marked with the symbol J1939_MSG_TRM inside the control field of the structure J1939_PGN_Entry_ts (J1939_PGN_Entry_s::uwControl). For a cyclic PGN transmission, the cycle time field (J1939_PGN_Entry_s::uwCycle) is set to a value unequal to zero.

The following example shows the setup of a PGN with a value of 61444 which is transmitted by ECU with a cycle time of 10 ms.

// Electronic Engine Controller 1 (EEC1)
//
{ J1939_PRIORITY_CTRL | J1939_MSG_TRM, // PDU Control
(uint32_t) 61444, // PGN value
(uint16_t) (PGN_TRANSMISSION_RATE), // Transmission rate
(uint16_t) 0, // Counter
(uint8_t) 0, // DA
(uint8_t) 0, // reserved
(uint16_t) 8, // Data size
ECU_Pgn61444 // PGN handler
},
#define J1939_MSG_TRM
Definition j1939_defs.h:257
#define J1939_PRIORITY_CTRL
Definition j1939_defs.h:222

After the cycle timer has elapsed, the function ECU_Pgn61444() is called, which is the interface to the application. The following example shows the implementation of the function ECU_Pgn61444().

static int16_t ECU_Pgn61444(uint8_t * pubDataV, uint16_t uwSizeV, uint8_t ubSrcAddrV, uint8_t ubNetV)
{
J1939_Payload_ts *ptsPayloadT = (J1939_Payload_ts *) pubDataV;
static uint16_t uwSpeedS = 200 * 8; // 1 Bit = 0.125rpm
static uint8_t ubTorqueS = (uint8_t) 125; // 1 Bit = 1%, -125% Offset
static uint8_t ubSimDirS = 1; // direction of simulation
//---------------------------------------------------------------------------------------------------
// silence warning for unused parameters
//
(void) uwSizeV;
(void) ubSrcAddrV;
(void) ubNetV;
//---------------------------------------------------------------------------------------------------
// simulate torque
//
ubTorqueS += (uint8_t) 1;
if (ubTorqueS > ((uint8_t) 200))
{
ubTorqueS = (uint8_t) 125;
}
//---------------------------------------------------------------------------------------------------
// simulate engine speed in rpm between 200 and 2200
//
if (tsECU_ControlS.uwSpeed == (uint16_t) 0)
{
if (ubSimDirS == (uint8_t) 1)
{
uwSpeedS = uwSpeedS + (uint16_t) 8;
if (uwSpeedS / (uint16_t) 8 > (uint16_t) 2200)
{
ubSimDirS = 0;
}
}
else
{
uwSpeedS = uwSpeedS - (uint16_t) 8;
if (uwSpeedS / (uint16_t) 8 < (uint16_t) 200)
{
ubSimDirS = 1;
}
}
}
//---------------------------------------------------------------------------------------------------
// set engine speed to the requested value
//
else
{
//-------------------------------------------------------------------------------------------
// requested value is greater
//
if (tsECU_ControlS.uwSpeed > uwSpeedS)
{
uwSpeedS = uwSpeedS + (uint16_t) 8;
}
//-------------------------------------------------------------------------------------------
// requested value is smaller
//
if (tsECU_ControlS.uwSpeed < uwSpeedS)
{
uwSpeedS = uwSpeedS - (uint16_t) 8;
}
}
ptsPayloadT->aubByte[0] = 0x01;
ptsPayloadT->aubByte[1] = ubTorqueS; // SPN 512
ptsPayloadT->aubByte[2] = ubTorqueS; // SPN 513
ptsPayloadT->aubByte[3] = (uint8_t) uwSpeedS; // SPN 190
ptsPayloadT->aubByte[4] = (uint8_t) (uwSpeedS >> 8);
ptsPayloadT->aubByte[5] = tsECU_ControlS.ubDevice; // Controlling device
ptsPayloadT->aubByte[6] = J1939_UNUSED_UINT8;
ptsPayloadT->aubByte[7] = J1939_UNUSED_UINT8;
return ((int16_t) eJ1939_HANDLER_RESULT_OK);
}