Skip to content

Commit

Permalink
Moved all J1939 and CANOpen work into separate header files; perhaps …
Browse files Browse the repository at this point in the history
…better to spin off into separate classes?

Switched all mentions of baud instead to bitrate
Changed nearly all variables to use uint{8,16,32}_t
Removed some unused functions
  • Loading branch information
McNeight committed Jun 5, 2014
1 parent ea106bc commit 4363fb3
Show file tree
Hide file tree
Showing 8 changed files with 438 additions and 525 deletions.
34 changes: 25 additions & 9 deletions examples/SendCANMessages/SendCANMessages.ino
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
#define bitrate CAN_BPS_500K // define CAN speed (bitrate)

// data counter just to show a dynamic change in data messages
uint8_t extended_counter = 0;
uint8_t standard_counter = 0;
uint32_t extended_counter = 0;
uint16_t standard_counter = 0;

/*
Second we create CANbus object (CAN channel) and select SPI CS Pin. Do not use "CAN" by itself as it will cause compile errors.
Expand Down Expand Up @@ -68,13 +68,24 @@ void setup()
void extendedMessage()
{
CAN_FRAME extended_message; // Create message object to use CAN message structure

// There are at least two ways to put data into the message; memcpy() and individual arrays
uint8_t message_data[] = {0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, extended_counter}; // data message with an added counter
uint8_t message_data[8] = { 0 }; // data message with an added counter

extended_message.id = 0x02DACBF1; // Random Extended Message ID
extended_message.id = extended_counter + 0x800; // Random Extended Message ID
extended_message.valid = true;
extended_message.rtr = 0;
extended_message.extended = CAN_EXTENDED_FRAME;
// Serial.print("extended_message.extended:");
// Serial.println(extended_message.extended);

extended_message.length = 8; // Data length
uint32_t timehack = millis();
message_data[0] = 0x55;
message_data[4] = (timehack >> 24);
message_data[5] = (timehack >> 16);
message_data[6] = (timehack >> 8);
message_data[7] = (timehack & 0xF);
memcpy(extended_message.data, message_data, sizeof(extended_message.data));

CANbus.write(extended_message); // Load message and send
Expand All @@ -87,16 +98,21 @@ void standardMessage()
{
CAN_FRAME standard_message; // Create message object to use CAN message structure

standard_message.id = 0x555; // Random Standard Message ID
standard_message.id = standard_counter; // Random Standard Message ID
standard_message.valid = true;
standard_message.rtr = 0;
standard_message.extended = CAN_BASE_FRAME;
//Serial.print("standard_message.extended:");
//Serial.println(standard_message.extended);

standard_message.length = 5; // Data length in this case let's say 5
uint32_t timehack = millis();
// data message with an added counter
standard_message.data[0] = 0x55;
standard_message.data[1] = 0xAA;
standard_message.data[2] = 0x55;
standard_message.data[3] = 0xAA;
standard_message.data[4] = standard_counter;
standard_message.data[1] = (timehack >> 24);
standard_message.data[2] = (timehack >> 16);
standard_message.data[3] = (timehack >> 8);
standard_message.data[4] = (timehack & 0xF);

CANbus.write(standard_message); // Load message and send
standard_counter++; // increase count
Expand Down
105 changes: 10 additions & 95 deletions src/CAN.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,113 +59,28 @@ DATE VER WHO WHAT
#define CAN_BPS_125K 125000
#define CAN_BPS_100K 100000
#define CAN_BPS_50K 50000
#define CAN_BPS_33333 33333
#define CAN_BPS_33333 33333
#define CAN_BPS_25K 25000
#define CAN_BPS_20K 20000
#define CAN_BPS_10K 10000
#define CAN_BPS_5K 5000

// CAN Message Structures
// typedef struct
// {
// byte start_of_frame : 1;
// unsigned int identifier : 11;
// byte rtr : 1;
// byte dlc : 4;
// unsigned int crc : 15;
// byte ack : 2;
// byte eof : 7;
// } CAN_DATA_FRAME_COMPLETE;

// #if defined(ARDUINO_ARCH_SAM)
// //This is architecture specific. DO NOT USE THIS UNION ON ANYTHING OTHER THAN THE CORTEX M3 / Arduino Due
// //UNLESS YOU DOUBLE CHECK THINGS!
// typedef union {
// uint64_t value;
// struct {
// uint32_t low;
// uint32_t high;
// };
// struct {
// uint16_t s0;
// uint16_t s1;
// uint16_t s2;
// uint16_t s3;
// };
// uint8_t bytes[8];
// } BytesUnion;

// typedef struct
// {
// uint32_t id : 29; // EID if ide set, SID otherwise
// uint8_t valid : 1; // To avoid passing garbage frames around
// uint8_t rtr : 1; // Remote Transmission Request
// uint8_t extended : 1; // Extended ID flag
// uint32_t fid; // family ID
// uint8_t priority : 4; // Priority but only important for TX frames and then only for special uses.
// uint8_t length : 4; // Number of data bytes
// BytesUnion data; // 64 bits - lots of ways to access it.
// } CAN_FRAME;

// #elif defined(ARDUINO_ARCH_AVR)

typedef struct
{
uint32_t id : 29; // EID if ide set, SID otherwise
uint8_t valid : 1; // To avoid passing garbage frames around
uint8_t rtr : 1; // Remote Transmission Request
uint8_t extended : 1; // Extended ID flag
uint32_t fid; // family ID
uint8_t priority : 4; // Priority but only important for TX frames and then only for special uses.
uint8_t length : 4; // Data Length
uint8_t data[8]; // Message data
uint32_t id : 29; // if (ide == CAN_RECESSIVE) { extended ID } else { standard ID }
uint8_t valid : 1; // To avoid passing garbage frames around
uint8_t rtr : 1; // Remote Transmission Request Bit
uint8_t extended : 1; // Identifier Extension Bit
uint32_t fid; // family ID
uint8_t priority : 4; // Priority but only important for TX frames and then only for special uses.
uint8_t length : 4; // Data Length
uint8_t data[8]; // Message data
} CAN_FRAME;

//#endif // CAN_FRAME

// SAE J1939 Message Structures
// Also:
// ISO 11783 (ISOBUS or ISO Bus)
// NMEA 2000
typedef struct
{
uint32_t ID : 29; // Identifier
uint8_t PRIO : 3; // Message priority
uint16_t PGN; // Parameter Group Number
uint8_t SA; // Source Address
uint8_t DA; // Destination Address
uint8_t DLC : 4; // Data length code
uint8_t data[8]; // Message data
} CAN_DATA_FRAME_J1939;


// CANopen Message Structures
typedef struct
{
uint16_t COB_ID : 11; // Communication object identifier
uint8_t FC : 4; // Function Code
uint8_t NODE : 7; // Node
uint8_t rtr : 1; // Remote Transmission Request
uint8_t length : 4; // Data Length
uint8_t data[8]; // Message data
} CAN_DATA_FRAME_CANopen;


// CANaerospace Message Structures
typedef struct
{
uint16_t ID : 11;
uint8_t NODE;
uint8_t TYPE;
uint8_t SERVICE;
uint8_t MESSAGE;
uint8_t data[4];
} CAN_DATA_FRAME_CANaerospace;

class CANClass // Can't inherit from Stream
{
public:
virtual void begin(uint32_t baud);
virtual void begin(uint32_t bitrate);
virtual void end();
virtual uint8_t available();
virtual CAN_FRAME read();
Expand Down
48 changes: 48 additions & 0 deletions src/CANOpen.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// CANopen Message Structures
typedef struct
{
uint16_t COB_ID : 11; // Communication object identifier
uint8_t FC : 4; // Function Code
uint8_t NODE : 7; // Node
uint8_t rtr : 1; // Remote Transmission Request
uint8_t length : 4; // Data Length
uint8_t data[8]; // Message data
} CAN_DATA_FRAME_CANopen;

uint8_t read(CAN_DATA_FRAME_CANopen *message); //Receive and display CANopen message and allows use of the message structure for easier message handling

//Receive and display CANopen message. This allows use of the message structure for easier message handling if
//communication object identifier (COB_ID), Function Code and Nodes are needed. See link for more info http://en.wikipedia.org/wiki/CANopen
void CAN_MCP2515::read(CAN_DATA_FRAME_CANopen *message)
{
byte len, i, buffer, status;
unsigned short sid_h, sid_l, eid8, eid0, rxbDlc;
status = readStatus();
if ((status & 0x01) == 0x01)
{
buffer = 0x90;
}
else if ((status & 0x02) == 0x02)
{
buffer = 0x94;
}
digitalWrite(CS, LOW);
SPI.transfer(buffer);
sid_h = SPI.transfer(0xFF); //id high
sid_l = SPI.transfer(0xFF); //id low
eid8 = SPI.transfer(0xFF); //extended id high
eid0 = SPI.transfer(0xFF); //extended id low
rxbDlc = SPI.transfer(0xFF); // get bits and other data from MCP2515 RXB DLC buffer (it contains data and RTR)
len = ((rxbDlc) & 0x0F);
//len = (SPI.transfer(0xFF) & 0x0F); //data length
for (i = 0; i < len; i++)
{
message->data[i] = SPI.transfer(0xFF);
}
digitalWrite(CS, HIGH);
message->rtr = (bitRead(rxbDlc, 6));
message->length = len;
message->COB_ID = ((((unsigned short) sid_h) << 3) | ((sid_l & 0xE0) >> 5)); // Msg is standard frame. COB_ID
message->FC = (((unsigned short) sid_h) << 3);// Contains CAN open Function Code
message->NODE = ((sid_l & 0xE0) >> 5); // Contains CANopen Node
}
Loading

0 comments on commit 4363fb3

Please sign in to comment.