CAN Library
The mikroC PRO for AVR provides a library (driver) for working with the CAN module.
The CAN is a very robust protocol that has error detection and signalization, self–checking and fault confinement. Faulty CAN data and remote frames are re-transmitted automatically, similar to the Ethernet.
Data transfer rates depend on distance. For example, 1 Mbit/s can be achieved at network lengths below 40m while 250 Kbit/s can be achieved at network lengths below 250m. The greater distance the lower maximum bitrate that can be achieved. The lowest bitrate defined by the standard is 200Kbit/s. Cables used are shielded twisted pairs.
CAN supports two message formats:
- Standard format, with 11 identifier bits, and
 - Extended format, with 29 identifier bits.
 
  Important :
- CAN library routines are supported for these devices : AT90CAN32, AT90CAN64, AT90CAN128, ATMEGA16M1, ATMEGA32M1 and ATMEGA64M1.
 - Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.
 - Consult the CAN standard about CAN bus termination resistance.
 
Library Routines
- CANSetOperationMode
 - CANGetOperationMode
 - CANInitialize
 - CANSetBaudRate
 - CANSetMask
 - CANSetFilter
 - CANRead
 - CANWrite
 
CANSetOperationMode
| Prototype | 
 void CANSetOperationMode(unsigned short mode, unsigned short wait_flag);  | 
|---|---|
| Returns | 
 Nothing.  | 
| Description | 
 Sets CAN to requested mode, i.e. copies  Parameter  
  | 
| Requires | 
 CAN routines are currently supported only by AT90CANXXX and ATMEGAXXM1 MCUs. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.  | 
| Example | 
CANSetOperationMode(_CAN_MODE_CONFIG, 0xFF);  | 
CANGetOperationMode
| Prototype | 
 unsigned short CANGetOperationMode();  | 
|---|---|
| Returns | 
 Current opmode.  | 
| Description | 
 Function returns current operational mode of CAN module.  | 
| Requires | 
 CAN routines are currently supported only by AT90CANXXX and ATMEGAXXM1 MCUs. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.  | 
| Example | 
if (CANGetOperationMode() == _CAN_MODE_NORMAL) { ... };
 | 
CANInitialize
| Prototype | 
 void CANInitialize(char SJW, char BRP, char PHSEG1, char PHSEG2, char PROPSEG, char CAN_CONFIG_FLAGS);  | 
|---|---|
| Returns | 
 Nothing.  | 
| Description | 
 Initializes CAN. All pending transmissions are aborted. Sets all mask registers to 0 to allow all messages. The Config mode is internaly set by this function. Upon a execution of this function Normal mode is set. Filter registers are set according to flag value: if (CAN_CONFIG_FLAGS & _CAN_CONFIG_XTD_MSG != 0) // Set all filters to XTD_MSG else if (config & _CAN_CONFIG_STD_MSG != 0) // Set all filters to STD_MSG else // Set half of the filters to STD, and the rest to XTD_MSG. Parameters: 
  | 
| Requires | 
 CAN routines are currently supported only by AT90CANXXX and ATMEGAXXM1 MCUs. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.  | 
| Example | 
init = _CAN_CONFIG_SAMPLE_THRICE &
       _CAN_CONFIG_MSG_TYPE_BIT &
       _CAN_CONFIG_STD_MSG;
...
CANInitialize(1, 1, 3, 3, 1, init);   // initialize CAN
 | 
CANSetBaudRate
| Prototype | 
 void CANSetBaudRate(char SJW, char BRP, char PHSEG1, char PHSEG2, char PROPSEG, char CAN_CONFIG_FLAGS);  | 
|---|---|
| Returns | 
 Nothing.  | 
| Description | 
 Sets CAN baud rate. Due to complexity of CAN protocol, you cannot simply force a bps value. Instead, use this function when CAN is in Config mode. Refer to datasheet for details. Parameters: 
  | 
| Requires | 
 CAN must be in Config mode; otherwise the function will be ignored. CAN routines are currently supported only by AT90CANXXX and ATMEGAXXM1 MCUs. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.  | 
| Example | 
init = _CAN_CONFIG_SAMPLE_THRICE &
       _CAN_CONFIG_MSG_TYPE_BIT &
       _CAN_CONFIG_STD_MSG;
...
CANSetBaudRate(1, 1, 3, 3, 1, init);
 | 
CANSetMask
| Prototype | 
 void CANSetMask(char CAN_MASK, long value, char CAN_CONFIG_FLAGS);  | 
|---|---|
| Returns | 
 Nothing.  | 
| Description | 
 Function sets mask for advanced filtering of messages. Given  Parameters: 
  | 
| Requires | 
 CAN must be in Config mode; otherwise the function will be ignored. CAN routines are currently supported only by AT90CANXXX and ATMEGAXXM1 MCUs. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.  | 
| Example | 
// Set all mask bits to 1, i.e. all filtered bits are relevant: CANSetMask(_CAN_MASK_B1, -1, _CAN_CONFIG_XTD_MSG); // Note that -1 is just a cheaper way to write 0xFFFFFFFF. Complement will do the trick and fill it up with ones.  | 
CANSetFilter
| Prototype | 
 void CANSetFilter(char CAN_FILTER, long value, char CAN_CONFIG_FLAGS);  | 
|---|---|
| Returns | 
 Nothing.  | 
| Description | 
 Function sets message filter. Given  Parameters: 
  | 
| Requires | 
 CAN must be in Config mode; otherwise the function will be ignored. CAN routines are currently supported only by AT90CANXXX and ATMEGAXXM1 MCUs. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.  | 
| Example | 
// Set id of filter F1 to 3: CANSetFilter(CAN_RX_FILTER_1, 3, _CAN_CONFIG_XTD_MSG);  | 
CANRead
| Prototype | 
 char CANRead(long *id, char *data, char *datalen, char *CAN_RX_MSG_FLAGS);  | 
|---|---|
| Returns | 
 Message from receive buffer or zero if no message found.  | 
| Description | 
 Function reads message from receive buffer. If at least one full receive buffer is found, it is extracted and returned. If none found, function returns zero. Parameters: 
  | 
| Requires | 
 CAN must be in mode in which receiving is possible. CAN routines are currently supported only by AT90CANXXX and ATMEGAXXM1 MCUs. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.  | 
| Example | 
char rcv, rx, len, data[8]; long id; // ... rx = 0; // ... rcv = CANRead(id, data, len, rx);  | 
CANWrite
| Prototype | 
 unsigned short CANWrite(long id, char *data_, char datalen, char CAN_TX_MSG_FLAGS);  | 
|---|---|
| Returns | 
 Returns zero if message cannot be queued (buffer full).  | 
| Description | 
 If at least one empty transmit buffer is found, function sends message on queue for transmission. If buffer is full, function returns 0. Parameters: 
  | 
| Requires | 
 CAN must be in Normal mode. CAN routines are currently supported only by AT90CANXXX and ATMEGAXXM1 MCUs. Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.  | 
| Example | 
char tx, data;
long id;
// ...
tx = _CAN_TX_PRIORITY_0 &
     _CAN_TX_XTD_FRAME;
// ...
CANWrite(id, data, 2, tx);
 | 
CAN Constants
There is a number of constants predefined in CAN library. To be able to use the library effectively, you need to be familiar with these. You might want to check the example at the end of the chapter.
CAN_OP_MODE
CAN_OP_MODE constants define CAN operation mode. Function CANSetOperationMode expects one of these as its argument:
const char
    _CAN_MODE_BITS    = 0x0A,   // Use this to access opmode  bits
    _CAN_MODE_STANDBY = 0x00,
    _CAN_MODE_ENABLE  = 0x02,
    _CAN_MODE_LISTEN  = 0x08
CAN_CONFIG_FLAGS
CAN_CONFIG_FLAGS constants define flags related to CAN module configuration. Functions CANInitialize and CANSetBaudRate expect one of these (or a bitwise combination) as their argument:
const char
    _CAN_CONFIG_SAMPLE_BIT      = 0x01,
    _CAN_CONFIG_SAMPLE_ONCE     = 0xFE,   // XXXX XXX0
    _CAN_CONFIG_SAMPLE_THRICE   = 0xFF,   // XXXX XXX1
    _CAN_CONFIG_MSG_TYPE_BIT    = 0x10,
    _CAN_CONFIG_STD_MSG         = 0xEF,   // XXX0 XXXX
    _CAN_CONFIG_XTD_MSG         = 0xFF;   // XXX1 XXXX
You may use bitwise AND (&) to form config byte out of these values. For example:
init = _CAN_CONFIG_SAMPLE_THRICE &
       _CAN_CONFIG_STD_MSG       &
...
CANInitialize(1, 1, 3, 3, 1, init);   // initialize CAN
CAN_TX_MSG_FLAGS
CAN_TX_MSG_FLAGS are flags related to transmission of a CAN message:
const char
    _CAN_CONMOB_DIS        = 0x3F,   // 00XX XXXX   messsage objects work modes
    _CAN_CONMOB_EN_TX      = 0x7F,   // 01XX XXXX
    _CAN_CONMOB_EN_RX      = 0xBF,   // 10XX XXXX
    _CAN_CONMOB_EN_FRAME   = 0xFF,   // 11XX XXXX
    _CAN_IDE_FRAME_BIT     = 0x10,   // Identifier Extension
    _CAN_IDE_STD_FRAME     = 0xEF,   // XXX0 XXXX
    _CAN_IDE_XTD_FRAME     = 0xFF,   // XXX1 XXXX
    _CAN_RTR_BIT           = 0x20,
    _CAN_NO_RTR_FRAME      = 0xFF,   // XX1XXXXX
    _CAN_RTR_FRAME         = 0xDF,   // XX0XXXXX
    _CAN_TX                = 0x01,   // Transmitter Busy
    _CAN_TX_NO_BSY         = 0xFE,   // XXXX XXX0
    _CAN_TX_BSY            = 0xFF;   // XXXX XXX1
You may use bitwise AND (&) to adjust the appropriate flags. For example:
// form value to be used with CANSendMessage:
send_config = _CAN_CONMOB_DIS &
              _CAN_TX_XTD_FRAME  &
              _CAN_TX_NO_RTR_FRAME;
...
CANWrite(id, data, 1, send_config);
CAN_RX_MSG_FLAGS
CAN_RX_MSG_FLAGS are flags related to reception of CAN message. If a particular bit is set; corresponding meaning is TRUE or else it will be FALSE.
const char
    _CAN_RX                = 0x08,   // Receiver Busy
    _CAN_RX_NO_BSY         = 0xF7,   // XXXX 0XXX
    _CAN_RX_BSY            = 0xFF;   // XXXX 1XXX
You may use bitwise AND (&) to adjust the appropriate flags. For example:
if (MsgFlag & _CAN_RX_BSY != 0) {
  ...
  // Receiver is busy.
}
CAN_MASK
CAN_MASK constants define mask codes. Function CANSetMask expects one of these as its argument:
const char
    CAN_RX_MASK_0  = 0x00,
    CAN_RX_MASK_1  = 0x01,
    CAN_RX_MASK_2  = 0x02,
    CAN_RX_MASK_3  = 0x03,
    CAN_RX_MASK_4  = 0x04,
    CAN_RX_MASK_5  = 0x05,
    CAN_RX_MASK_6  = 0x06,
    CAN_RX_MASK_7  = 0x07,
    CAN_RX_MASK_8  = 0x08,
    CAN_RX_MASK_9  = 0x09,
    CAN_RX_MASK_10 = 0x0A,
    CAN_RX_MASK_11 = 0x0B,
    CAN_RX_MASK_12 = 0x0C,
    CAN_RX_MASK_13 = 0x0D,
    CAN_RX_MASK_14 = 0x0E;
CAN_FILTER
CAN_FILTER constants define filter codes. Function CANSetFilter expects one of these as its argument:
const char
    CAN_RX_FILTER_0  = 0x00,
    CAN_RX_FILTER_1  = 0x01,
    CAN_RX_FILTER_2  = 0x02,
    CAN_RX_FILTER_3  = 0x03,
    CAN_RX_FILTER_4  = 0x04,
    CAN_RX_FILTER_5  = 0x05,
    CAN_RX_FILTER_6  = 0x06,
    CAN_RX_FILTER_7  = 0x07,
    CAN_RX_FILTER_8  = 0x08,
    CAN_RX_FILTER_9  = 0x09,
    CAN_RX_FILTER_10 = 0x0A,
    CAN_RX_FILTER_11 = 0x0B,
    CAN_RX_FILTER_12 = 0x0C,
    CAN_RX_FILTER_13 = 0x0D,
    CAN_RX_FILTER_14 = 0x0E;
CAN_MOB
CAN_MOB constants define flags related to transmission of a CAN message :
 const char
    _CAN_EN_MOB0_BIT    = 0x0001, // Flags, set to 1 if the appropriate MOb is in use. When the appropriate operation ends, TXOK or RXOK are set to 1
    _CAN_EN_MOB1_BIT    = 0x0002,
    _CAN_EN_MOB2_BIT    = 0x0004,
    _CAN_EN_MOB3_BIT    = 0x0008,
    _CAN_EN_MOB4_BIT    = 0x0010,
    _CAN_EN_MOB5_BIT    = 0x0020,
    _CAN_EN_MOB6_BIT    = 0x0040,
    _CAN_EN_MOB7_BIT    = 0x0080,
    _CAN_EN_MOB8_BIT    = 0x0100,
    _CAN_EN_MOB9_BIT    = 0x0200,
    _CAN_EN_MOB10_BIT   = 0x0400,
    _CAN_EN_MOB11_BIT   = 0x0800,
    _CAN_EN_MOB12_BIT   = 0x1000,
    _CAN_EN_MOB13_BIT   = 0x2000,
    _CAN_EN_MOB14_BIT   = 0x4000,
    _CAN_CONFIG_STMOB_TXOK  = 0x40,   // X1XX XXXX  From the CAN MOb Status Register
    _CAN_CONFIG_STMOB_RXOK  = 0x20,   // XX1X XXXX  Receive OK
    _CAN_CONFIG_STMOB_BERR  = 0x10,   // XXX1 XXXX  Bit Error (Only in transmission)
    _CAN_CONFIG_STMOB_SERR  = 0x08,   // XXXX 1XXX  Stuff Error
    _CAN_CONFIG_STMOB_CERR  = 0x04,   // XXXX X1XX  CRC Error
    _CAN_CONFIG_STMOB_FERR  = 0x02,   // XXXX XX1X  Form Error
    _CAN_CONFIG_STMOB_AERR  = 0x01;   // XXXX XXX1  Acknowledgment Error
Library Example
This is a simple demonstration of CAN Library routines usage. First node initiates the communication with the second node by sending some data to its address. The second node responds by sending back the data incremented by 1. First node then does the same and sends incremented data back to second node, etc.
Code for the first CAN node:
unsigned char Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags;                    // can flags
unsigned char Rx_Data_Len;                                                      // received data length in bytes
char RxTx_Data[8];                                                              // can rx/tx data buffer
char Msg_Rcvd = 0;                                                              // reception flag
const long ID_1st = 12111, ID_2nd = 3;                                          // node IDs
long Rx_ID;
void main() {
  PORTC = 0x00;                                                  // clear PORTC
  DDRC  = 0xFF;                                                  // set PORTC as output
  
  Can_Init_Flags = 0;                                            //
  Can_Send_Flags = 0;                                            // clear flags
  Can_Rcv_Flags  = 0;                                            //
  Can_Send_Flags = _CAN_IDE_XTD_FRAME                            // form value to be used
                 & _CAN_NO_RTR_FRAME;                            // with CANWrite
  Can_Init_Flags = _CAN_CONFIG_SAMPLE_THRICE                     // form value to be used
                 & _CAN_CONFIG_XTD_MSG;                          // with CANInit
  CANInitialize(1,6,3,3,1,Can_Init_Flags);                       // initialize external CAN module
  CANSetOperationMode(_CAN_MODE_STANDBY,0xFF);                   // set STANDBY mode
  
  //----------------------------------------------------------//
  CANSetFilter(CAN_RX_FILTER_3,  -1, _CAN_CONFIG_XTD_MSG);    //
  CANSetFilter(CAN_RX_FILTER_4, ID_2nd, _CAN_CONFIG_XTD_MSG); // set ID filter of 4th filter to 2nd node ID
  CANSetFilter(CAN_RX_FILTER_5,  -1, _CAN_CONFIG_XTD_MSG);    // and ones to other filters
  CANSetFilter(CAN_RX_FILTER_6,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_7,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_8,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_9,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_10, -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_11, -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_12, -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_13, -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_14, -1, _CAN_CONFIG_XTD_MSG);
//----------------------------------------------------------//
  
  //----------------------------------------------------------//
  CANSetMask(CAN_RX_MASK_3,  -1, _CAN_CONFIG_XTD_MSG);        // set all mask bits of masks[3..14] to all ones
  CANSetMask(CAN_RX_MASK_4,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_5,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_6,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_7,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_8,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_9,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_10, -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_11, -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_12, -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_13, -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_14, -1, _CAN_CONFIG_XTD_MSG);
//----------------------------------------------------------//
  
  CANSetOperationMode(_CAN_MODE_ENABLE,0xFF);                                   // set ENABLE mode
  RxTx_Data[0] = 9;                                                             // set initial data to be sent
  CANWrite(ID_1st, RxTx_Data, 1, Can_Send_Flags);                               // send initial message
  while(1) {                                                                    // endless loop
    Msg_Rcvd = CANRead(&Rx_ID, RxTx_Data, &Rx_Data_Len, &Can_Rcv_Flags);        // receive message
    if ((Rx_ID == ID_2nd) && Msg_Rcvd) {                                        // if message received check id
      PORTC = RxTx_Data[0];                                                     // id correct, output data at PORTC
      RxTx_Data[0]++;                                                             // increment received data
      Delay_ms(10);
      CANWrite(ID_1st, RxTx_Data, 1, Can_Send_Flags);                           // send incremented data back
    }
  }
}
Code for the second CAN node:
unsigned char Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags;     // can flags
unsigned char Rx_Data_Len;                                       // received data length in bytes
char RxTx_Data[8];                                               // can rx/tx data buffer
char Msg_Rcvd = 0;                                               // reception flag
const long ID_1st = 12111, ID_2nd = 3;                           // node IDs
long Rx_ID;
void main() {
  PORTC = 0x00;                                                  // clear PORTC
  DDRC  = 0xFF;                                                  // set PORTC as output
  Can_Init_Flags = 0;                                            //
  Can_Send_Flags = 0;                                            // clear flags
  Can_Rcv_Flags  = 0;                                            //
  Can_Send_Flags = _CAN_IDE_XTD_FRAME                            // form value to be used
                 & _CAN_NO_RTR_FRAME;                            // with CANWrite
  Can_Init_Flags = _CAN_CONFIG_SAMPLE_THRICE                     // form value to be used
                 & _CAN_CONFIG_XTD_MSG;                          // with CANInit
  CANInitialize(1,6,3,3,1,Can_Init_Flags);                       // initialize external CAN module
  CANSetOperationMode(_CAN_MODE_STANDBY,0xFF);                   // set STANDBY mode
  //----------------------------------------------------------//
  CANSetFilter(CAN_RX_FILTER_3,  -1, _CAN_CONFIG_XTD_MSG);    //
  CANSetFilter(CAN_RX_FILTER_4,  -1, _CAN_CONFIG_XTD_MSG);    //
  CANSetFilter(CAN_RX_FILTER_5,  -1, _CAN_CONFIG_XTD_MSG);    //
  CANSetFilter(CAN_RX_FILTER_6,  -1, _CAN_CONFIG_XTD_MSG);    //
  CANSetFilter(CAN_RX_FILTER_7, ID_1st, _CAN_CONFIG_XTD_MSG); // set ID filter of 7th filter to 2nd node ID
  CANSetFilter(CAN_RX_FILTER_8,  -1, _CAN_CONFIG_XTD_MSG);    // and ones to other filters
  CANSetFilter(CAN_RX_FILTER_9,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_10, -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_11, -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_12, -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_13, -1, _CAN_CONFIG_XTD_MSG);
  CANSetFilter(CAN_RX_FILTER_14, -1, _CAN_CONFIG_XTD_MSG);
  //----------------------------------------------------------//
  
  //----------------------------------------------------------//
  CANSetMask(CAN_RX_MASK_3,  -1, _CAN_CONFIG_XTD_MSG);        // set all mask bits of masks[3..14] to all ones
  CANSetMask(CAN_RX_MASK_4,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_5,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_6,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_7,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_8,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_9,  -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_10, -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_11, -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_12, -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_13, -1, _CAN_CONFIG_XTD_MSG);
  CANSetMask(CAN_RX_MASK_14, -1, _CAN_CONFIG_XTD_MSG);
  //----------------------------------------------------------//
  
  CANSetOperationMode(_CAN_MODE_ENABLE,0xFF);               // set ENABLE mode
  while (1) {                                                              // endless loop
    Msg_Rcvd = CANRead(&Rx_ID, &RxTx_Data, &Rx_Data_Len, &Can_Rcv_Flags);   // receive message
    if ((Rx_ID == ID_1st) && Msg_Rcvd) {                                   // if message received check id
      PORTC = RxTx_Data[0];                                                // id correct, output data at PORTC
      RxTx_Data[0]++;                                                     // increment received data
      CANWrite(ID_2nd, RxTx_Data, 1, Can_Send_Flags);                      // send incremented data back
    }
  }
}
What do you think about this topic ? Send us feedback!




