171 lines
4.5 KiB
C++
171 lines
4.5 KiB
C++
// ------------------------------------------------------------------------
|
|
// J1939 CAN Connection
|
|
// ------------------------------------------------------------------------
|
|
#include "mcp_can.h"
|
|
|
|
#define CS_PIN 4 // Use pin 10 for Seeed Studio CAN Shield up to version 1.0
|
|
// Use pin 9 for Seeed Studion CAN shiled version 1.1 and higher
|
|
// Use pin 10 for SK Pang CAN shield
|
|
MCP_CAN CAN(CS_PIN);
|
|
|
|
// ------------------------------------------------------------------------
|
|
// CAN message ring buffer setup
|
|
// ------------------------------------------------------------------------
|
|
#define CANMSGBUFFERSIZE 10
|
|
struct CANMsg
|
|
{
|
|
long lID;
|
|
unsigned char pData[8];
|
|
int nDataLen;
|
|
};
|
|
CANMsg CANMsgBuffer[CANMSGBUFFERSIZE];
|
|
int nWritePointer;
|
|
int nReadPointer;
|
|
|
|
// ------------------------------------------------------------------------
|
|
// Initialize the CAN controller
|
|
// ------------------------------------------------------------------------
|
|
int canInitialize(int nBaudRate)
|
|
{
|
|
// Default settings
|
|
nReadPointer = 0;
|
|
nWritePointer = 0;
|
|
|
|
// Initialize the CAN controller
|
|
if (CAN.begin(nBaudRate) == 0)
|
|
return 0;
|
|
else
|
|
return 1;
|
|
|
|
} // end canInitialize
|
|
|
|
// ------------------------------------------------------------------------
|
|
// Transmit CAN message
|
|
// ------------------------------------------------------------------------
|
|
byte canTransmit(long lID, unsigned char *pData, int nDataLen)
|
|
{
|
|
|
|
if (CAN.sendMsgBuf(lID, CAN_EXTID, nDataLen, pData) == 0)
|
|
return 0;
|
|
else
|
|
return 1;
|
|
|
|
} // end canTransmit
|
|
|
|
// ------------------------------------------------------------------------
|
|
// Receive CAN message
|
|
// ------------------------------------------------------------------------
|
|
byte canReceive(long *lID, unsigned char *pData, int *nDataLen)
|
|
{
|
|
// Declarations
|
|
byte nCnt;
|
|
|
|
// In case there is a message, put it into the buffer
|
|
while (CAN.checkReceive() == CAN_MSGAVAIL)
|
|
{
|
|
// Read the message buffer
|
|
CAN.readMsgBuf(&nCnt, &CANMsgBuffer[nWritePointer].pData[0]);
|
|
CANMsgBuffer[nWritePointer].nDataLen = (int)nCnt;
|
|
CANMsgBuffer[nWritePointer].lID = CAN.getCanId();
|
|
|
|
if (++nWritePointer == CANMSGBUFFERSIZE)
|
|
nWritePointer = 0;
|
|
|
|
} // end while
|
|
|
|
// Check ring buffer for a message
|
|
if (nReadPointer != nWritePointer)
|
|
{
|
|
// Read the next message buffer entry
|
|
*nDataLen = CANMsgBuffer[nReadPointer].nDataLen;
|
|
*lID = CANMsgBuffer[nReadPointer].lID;
|
|
|
|
for (int nIdx = 0; nIdx < *nDataLen; nIdx++)
|
|
pData[nIdx] = CANMsgBuffer[nReadPointer].pData[nIdx];
|
|
|
|
if (++nReadPointer == CANMSGBUFFERSIZE)
|
|
nReadPointer = 0;
|
|
|
|
return 0;
|
|
|
|
} // end if
|
|
else
|
|
return 1;
|
|
|
|
} // end canReceive
|
|
|
|
// ------------------------------------------------------------------------
|
|
// J1939 Check Peer-to-Peer
|
|
// ------------------------------------------------------------------------
|
|
bool j1939PeerToPeer(long lPGN)
|
|
{
|
|
// Check the PGN
|
|
if (lPGN > 0 && lPGN <= 0xEFFF)
|
|
return true;
|
|
|
|
if (lPGN > 0x10000 && lPGN <= 0x1EFFF)
|
|
return true;
|
|
|
|
return false;
|
|
|
|
} // end j1939PeerToPeer
|
|
|
|
// ------------------------------------------------------------------------
|
|
// J1939 Transmit
|
|
// ------------------------------------------------------------------------
|
|
byte j1939Transmit(long lPGN, byte nPriority, byte nSrcAddr, byte nDestAddr, byte *nData, int nDataLen)
|
|
{
|
|
// Declarations
|
|
long lID = ((long)nPriority << 26) + (lPGN << 8) + (long)nSrcAddr;
|
|
|
|
// If PGN represents a peer-to-peer, add destination address to the ID
|
|
if (j1939PeerToPeer(lPGN) == true)
|
|
{
|
|
lID = lID & 0xFFFF00FF;
|
|
lID = lID | ((long)nDestAddr << 8);
|
|
|
|
} // end if
|
|
|
|
// Transmit the message
|
|
return canTransmit(lID, nData, nDataLen);
|
|
|
|
} // end j1939Transmit
|
|
|
|
// ------------------------------------------------------------------------
|
|
// J1939 Receive
|
|
// ------------------------------------------------------------------------
|
|
byte j1939Receive(long *lPGN, byte *nPriority, byte *nSrcAddr, byte *nDestAddr, byte *nData, int *nDataLen)
|
|
{
|
|
// Declarations
|
|
byte nRetCode = 1;
|
|
long lID;
|
|
|
|
// Default settings
|
|
*nSrcAddr = 255;
|
|
*nDestAddr = 255;
|
|
|
|
if (canReceive(&lID, nData, nDataLen) == 0)
|
|
{
|
|
long lPriority = lID & 0x1C000000;
|
|
*nPriority = (int)(lPriority >> 26);
|
|
|
|
*lPGN = lID & 0x00FFFF00;
|
|
*lPGN = *lPGN >> 8;
|
|
|
|
lID = lID & 0x000000FF;
|
|
*nSrcAddr = (int)lID;
|
|
|
|
if (j1939PeerToPeer(*lPGN) == true)
|
|
{
|
|
*nDestAddr = (int)(*lPGN & 0xFF);
|
|
*lPGN = *lPGN & 0x01FF00;
|
|
}
|
|
|
|
nRetCode = 0;
|
|
|
|
} // end if
|
|
|
|
return nRetCode;
|
|
|
|
} // end j1939Receive
|