📄 j1939.c
字号:
/******************************************************************************
*
* File Name: j1939.c
*
* Description: Main part of the J1939 protocol stack
*
*
* Comments:
*
*
* Version Date Author Comments
* ------- ---------- -------------- ------------------------------
* 0.9 18.12.98 Ft Create
* 1.0 29.04.99 Ft C167CR and Tasking compiler
* 1.1 24.08.00 Ft Ack handling
* 1.2 31.05.2001 Ma merge Stack with CANopen Driver
* 1.3 11.06.2001 Ma add new statemachine fpr TX PG's
* 2.0 18.06.2001 Ma Version 2.0 new buffer concept and
* documented for doxygen
* 2.1 31.02.2002 Ma get CAN controller status at end of fct.
* 2.2 03.06.2002 Ma changed ADC handling in offline state
* 2.4 08.06.2004 For Bugfix 1350
*
* Copyright (c) 1998 - 2004 Vector Informatik GmbH
*****************************************************************************/
#include "Includes.h"
#include "PortAB.h"
#include "Types.h"
#include "J1939.h"
#include "J1939CFG.h"
#include "J1939PGN.h"
#include "J1939TRA.h"
#define NOEXTERNALS
#include "J1939EXT.h"
#undef NOEXTERNALS
#include "JCanCntrl.h"
/*!
\brief This Function is the main loop of the J1939 protocol stack
Function should be called as often as possible from the application.
This function is the main function for the J1939 protocol stack.
The function processes all receiving and transmitting PGs, the
Address claiming, BAM and CMDT protocols, the request and the CmdAddress
PGs
\param -
\retval -
*/
void J1939Stack(void)
{
unsigned char i; /* Counter variable */
unsigned char retVal;
gCB_DequeueElm();
/* Check for transport protocoll PGs */
if (gRxPGTable[RX_PGN_TPCM].mPGState == PG_RX_FULL) /* Transport protocoll command */
{
HandleRxTransportCmdPG();
gRxPGTable[RX_PGN_TPCM].mPGState = PG_RX_FREE; /* free buffer */
}
else if (gRxPGTable[RX_PGN_TPDT].mPGState == PG_RX_FULL) /* Transport protocoll */
{
HandleRxTransportDataPG();
gRxPGTable[RX_PGN_TPDT].mPGState = PG_RX_FREE; /* free buffer */
}
/* Check for address claiming PG */
else if (gRxPGTable[RX_PGN_ADDRESS_CLAIMED].mPGState == PG_RX_FULL)
{
CheckRxAddressClaimed(); /* Address claimed received */
gRxPGTable[RX_PGN_ADDRESS_CLAIMED].mPGState = PG_RX_FREE; /* Free buffer */
}
/* Commanded address PGN */
else if (gRxPGTable[RX_PGN_COMMAND_ADDRESS].mPGState == PG_RX_FULL)
{
if (CompareJ1939Name(&((struct VJ1939PGN_DATA_FED8*)gRxPGTable[RX_PGN_COMMAND_ADDRESS].mData)->mName) < 0) /* compare names, must be equal */
{
/* handle commanded address */
gAddressClaimed = 0; /* remove address */
J1939AppCmdAddrIndication(&gRxPGTable[RX_PGN_COMMAND_ADDRESS]); /* Inform Application */
}
gRxPGTable[RX_PGN_COMMAND_ADDRESS].mPGState = PG_RX_FREE; /* Free buffer */
}
/* First check special system PGs (not user/profile defined) */
/* Request PG */
if ((gRxPGTable[RX_PGN_REQ].mPGState == PG_RX_FULL) &&
(gRxPGTable[RX_PGN_REQ].mPDUS == J1939GLOBALADDRESS) &&
(((((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGNlsb)==0x00) &&
((((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGN)==0xEE)) &&
(gOnlineMarker == 1))
{
if(!gAddressClaimed)
{
SendCannotClaimAddress();
gRxPGTable[RX_PGN_REQ].mPGState = PG_RX_FREE;
}
}
/* Now handle the user and some system PGs */
if (gAddressClaimed) /* Check if device has an address */
{
/* First check special system PGs (not user/profile defined) */
/* Request PG */
if (gRxPGTable[RX_PGN_REQ].mPGState == PG_RX_FULL)
{
/* handle this request PG */
if ((gRxPGTable[RX_PGN_REQ].mPDUS == gDeviceAddress) || /* specific or */
(gRxPGTable[RX_PGN_REQ].mPDUS == J1939GLOBALADDRESS)) /* global request */
{
/* search if PGN is available */
for (i=TX_PGN_USER; i<NR_OF_TX_PG; i++)
{
if (gTxPGTable[i].mPDUF == ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGN)
{
if (((gTxPGTable[i].mPDUF > 239) &&
(((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGNlsb)==gTxPGTable[i].mPDUS) ||
(gTxPGTable[i].mPDUF < 240))
{
retVal = J1939AppRequestIndication(&gTxPGTable[i]);
switch (retVal)
{
case REQ_SENDPGN:
gTxPGTable[i].mPGState = PG_TX_REQ; /* send requested pgn */
break;
case REQ_SENDNOTHING:
gTxPGTable[i].mPGState = PG_TX_FREE; /* do not send requested pgn */
break;
case REQ_SENDNACK:
/* send negative acknowledgment */
if (gTxPGTable[TX_PGN_ACK].mPGState == PG_TX_FREE)
{
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mAcknowledge = 1; /* set negative ACK */
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mPGNlsb = ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGNlsb;
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mPGN = ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGN;
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mPGNmsb = ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGNmsb;
gTxPGTable[TX_PGN_ACK].mSource = gDeviceAddress; /* source addr. */
gTxPGTable[TX_PGN_ACK].mPGState = PG_TX_REQ; /* send Acknowledge */
}
else
{
gCANOverrun = TRUE;
}
gTxPGTable[i].mPGState = PG_TX_FREE; /* do not send requested pgn */
break;
case REQ_SENDPACK:
/* send positive acknowledgment */
if (gTxPGTable[TX_PGN_ACK].mPGState == PG_TX_FREE)
{
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mAcknowledge = 0; /* set positive ACK */
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mPGNlsb = ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGNlsb;
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mPGN = ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGN;
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mPGNmsb = ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGNmsb;
gTxPGTable[TX_PGN_ACK].mSource = gDeviceAddress; /* source addr. */
gTxPGTable[TX_PGN_ACK].mPGState = PG_TX_REQ; /* send Acknowledge */
}
else
{
gCANOverrun = TRUE;
}
gTxPGTable[i].mPGState = PG_TX_FREE; /* do not send requested pgn */
break;
} /* switch */
break; /* leave for loop */
} /* if */
} /* if */
} /* for */
if (((gRxPGTable[RX_PGN_REQ].mPDUS == gDeviceAddress)||(gRxPGTable[RX_PGN_REQ].mPDUS == J1939GLOBALADDRESS)) && /* check if this request is for this device */
(i == NR_OF_TX_PG)) /* and the PGN is not available. Then send NACK. */
{
if (((((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGNlsb) == 0x00) &&
((((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGN == 0xEE)))
{
if(gAddressClaimed)
SendAddressClaimed();
else
SendCannotClaimAddress();
}
else if (gTxPGTable[TX_PGN_ACK].mPGState == PG_TX_FREE)
{
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mAcknowledge = 1; /* set negative ACK */
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mPGNlsb = ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGNlsb;
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mPGN = ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGN;
((struct VJ1939PGN_DATA_E800*)gTxPGTable[TX_PGN_ACK].mData)->mPGNmsb = ((struct VJ1939PGN_DATA_EA00*)gRxPGTable[RX_PGN_REQ].mData)->mPGNmsb;
gTxPGTable[TX_PGN_ACK].mSource = gDeviceAddress; /* source addr. */
gTxPGTable[TX_PGN_ACK].mPGState = PG_TX_REQ; /* send Acknowledge */
}
else
{
gCANOverrun = TRUE;
}
} /* if */
} /* if */
gRxPGTable[RX_PGN_REQ].mPGState = PG_RX_FREE; /* Free buffer */
} /* Request PG */
/* Check if data is to be send by a BAM or CMDT connection */
if (gTxPGTable[TX_PGN_TPDT].mPGState == PG_TX_FREE)
{
if (gTPTxCnxn.mState==CMDT_TX_STATE_DATA)
{
gTxPGTable[TX_PGN_TPDT].mPGState = PG_TX_REQ;
gTxPGTable[TX_PGN_TPDT].mPDUS = gTPTxCnxn.mSource;
gTxPGTable[TX_PGN_TPDT].mSource = gDeviceAddress;
((struct VJ1939PGN_DATA_EB00*)gTxPGTable[TX_PGN_TPDT].mData)->mSequence = gTPTxCnxn.mSequence; /* sequence number */
for (i=0;i<7;i++)
{
((struct VJ1939PGN_DATA_EB00*)gTxPGTable[TX_PGN_TPDT].mData)->mData[i] =
*((unsigned char*)gTxPGTable[gTPTxCnxn.mRxPGTable].mData+i+(7*(gTPTxCnxn.mSequence-1)));
}
if (gTPTxCnxn.mSequence==gTPTxCnxn.mPackets) /* last packet */
{
for (i=(gTPTxCnxn.mBytes%7);(i<7)&&(i>0);i++)
{
((struct VJ1939PGN_DATA_EB00*)gTxPGTable[TX_PGN_TPDT].mData)->mData[i] = 0xFF; /* fill reserved */
}
}
gTPTxCnxn.mPToSend--;
if (gTPTxCnxn.mPToSend) /* more packets in this sequence */
{
gTPTxCnxn.mSequence++;
}
else
{
gTPTxCnxn.mState = CMDT_TX_STATE_OPEN;
}
gTPTxCnxn.mTimer = Tim_GetCurrentTime();
}
else if (gTPTxCnxn.mState==BAM_TX_STATE_DATA)
{
gTxPGTable[TX_PGN_TPDT].mPGState = PG_TX_REQ;
gTxPGTable[TX_PGN_TPDT].mPDUS = gTPTxCnxn.mSource;
gTxPGTable[TX_PGN_TPDT].mSource = gDeviceAddress;
((struct VJ1939PGN_DATA_EB00*)gTxPGTable[TX_PGN_TPDT].mData)->mSequence = gTPTxCnxn.mSequence; /* sequence number */
for (i=0;i<7;i++)
{
((struct VJ1939PGN_DATA_EB00*)gTxPGTable[TX_PGN_TPDT].mData)->mData[i] =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -