CAN is message based.  Essentially, a CAN message consists of two parts: a Message ID part and a Data Part.  In CAN Simple the Data Part is 8 bytes and can contain data in any format you like, for example:  8 chars, 4 int16s, 2 float32s, etc. 

In CAN Simple the Message ID part is 11 bits and consists of a Data Type and a unique origin Node ID.  The Node ID occupies the low 5 bits of the Message ID and the Data Type occupies the high 6 bits of the Message ID.  So we could construct a Message ID like this:

CAN_TxMessage.StdId = 
(DATA_TYPE<<5) + THIS_NODE_ID;

 The Node IDs range from 0 to 31d and are defined in common_can.h like this: 

// ================ NODE IDs ==================
//5 bits from 0 0000 to 1 1111 (31d)
enum Node_IDs{
  ID_NOT_USED  = 0, //0 0000 
  ID_AUTOPILOT = 1, //0 0001
  ID_BLUETOOTH = 2, //0 0010
  ID_EEPROM    = 5,
  ID_FTDI      = 6,

The Node IDs serve two purposes:  they allow receiving nodes to know about the origin of the message, and they ensure that there is never more than one message with the same Message ID starting on the bus at the same time. This is a requirement of CAN.

The Data Types range from 32d to 63d and are defined in common_can.h like this:  

// ================DATA TYPES ==============
//6 bits from 10 0000 (32d) to 11 1111 (63d)
enum Data_Types{
  DATA_NOT_USED     =  32, //0x20, 10 0000
  DATA_MOTOR_CONTROL,
  DATA_MOTOR_SENSORS,
    
  DATA_IMU_ANGLES,
  DATA_IMU_GYROS,
  DATA_IMU_ACCELS,

The Data Types serve two purposes:  they allow receiving nodes to filter out messages in which they have no interest, and they tell the receiving nodes how to render or otherwise deal with the data in the data part of the message.  

So if we wanted to send an error message to be picked up by any node that cares, we could construct a Message ID like this:

CAN_TxMessage.StdId = 
(DATA_ERROR_MSG<<5) + THIS_NODE_ID;

And the data part of the message might contain the chars  "Checksum".

Then the code on a receiving node might look like this:

if(data_type == DATA_ERROR_MSG)
sprintf(USART_Temp, "Error Message: %.8s\r\n", CAN_RxMessage.Data);

where the %.8s just tells sprintf not to read past 8 chars.

Now this is all well and good, and probably 99+% of your traffic is going to be of the above kind.  However.  Sometimes there is a need to talk to a node more directly. Suppose for example you want to turn on the LED on any one of the nodes remotely.  And you certainty don't want every node to have to read the LED control message to see if it applies to them. 

Turns out this is pretty easy. We just replace the Data Type part of the Message ID with the Node ID of the target node. 

So if we wanted to turn on the LED on the IMU node, we could construct a Message ID like this:

CAN_TxMessage.StdId = 
(ID_IMU<<5) + THIS_NODE_ID;

And the data part of the message might contain the chars  "L1".

Then the code on a receiving node might look like this:

if(data_type == THIS_NODE_ID)
{
  if(rx_message[0]=='L')
    led_control(rx_message[1]);
}

The can_config() function in common_can.c automatically sets filters to allow Data Types equal to THIS_NODE_ID and ID_ALL_NODES.

f