CAN Library


The mikroPascal 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:

  Important :

Library Routines

CANSetOperationMode

Prototype

procedure CANSetOperationMode(mode : byte, wait_flag : byte);

Returns

Nothing.

Description

Sets CAN to requested mode, i.e. copies mode to CANSTAT. Parameter mode needs to be one of CAN_OP_MODE constants (see CAN constants).

Parameter wait_flag needs to be either 0 or 0xFF:

  • If set to 0xFF, this is a blocking call – the function won’t “return” until the requested mode is set.
  • If 0, this is a non-blocking call. It does not verify if CAN module is switched to requested mode or not. Caller must use CANGetOperationMode to verify correct operation mode before performing mode specific operation.
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

function CANGetOperationMode : byte;

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) then
...

CANInitialize

Prototype

procedure CANInitialize(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, CAN_CONFIG_FLAGS : byte);

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 and _CAN_CONFIG_XTD_MSG) <> 0
  // Set all filters to XTD_MSG
else if (config and _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:

  • SJW as defined in MCU's datasheet
  • BRP as defined in MCU's datasheet
  • PHSEG1 as defined in MCU's datasheet
  • PHSEG2 as defined in MCU's datasheet
  • PROPSEG as defined in MCU's datasheet
  • CAN_CONFIG_FLAGS is formed from predefined constants (see CAN constants)
Requires

CAN must be in Config mode; otherwise the function will be ignored.

Microcontroller must be connected to CAN transceiver (MCP2551 or similar) which is connected to CAN bus.

Example
init := _CAN_CONFIG_SAMPLE_THRICE and
        _CAN_CONFIG_MSG_TYPE_BIT and
        _CAN_CONFIG_STD_MSG;
...
CANInitialize(1, 1, 3, 3, 1, init);   // initialize CAN

CANSetBaudRate

Prototype

procedure CANSetBaudRate(SJW, BRP, PHSEG1, PHSEG2, PROPSEG, CAN_CONFIG_FLAGS : byte);

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:

  • SJW as defined in MCU's datasheet
  • BRP as defined in MCU's datasheet
  • PHSEG1 as defined in MCU's datasheet
  • PHSEG2 as defined in MCU's datasheet
  • PROPSEG as defined in MCU's datasheet
  • CAN_CONFIG_FLAGS is formed from predefined constants (see CAN constants)
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 and
        _CAN_CONFIG_MSG_TYPE_BIT and
        _CAN_CONFIG_STD_MSG;
...
CANSetBaudRate(1, 1, 3, 3, 1, init);

CANSetMask

Prototype

procedure CANSetMask(CAN_MASK : byte; value : longint; CAN_CONFIG_FLAGS : byte);

Returns

Nothing.

Description

Function sets mask for advanced filtering of messages. Given value is bit adjusted to appropriate buffer mask registers.

Parameters:

  • CAN_MASK is one of predefined constant values (see CAN constants)
  • value is the mask register value
  • CAN_CONFIG_FLAGS selects type of message to filter, either _CAN_CONFIG_XTD_MSG or _CAN_CONFIG_STD_MSG
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

procedure CANSetFilter(CAN_FILTER : byte; value : longint; CAN_CONFIG_FLAGS : byte);

Returns

Nothing.

Description

Function sets message filter. Given value is bit adjusted to appropriate buffer mask registers.

Parameters:

  • CAN_FILTER is one of predefined constant values (see CAN constants)
  • value is the filter register value
  • CAN_CONFIG_FLAGS selects type of message to filter, either _CAN_CONFIG_XTD_MSG or _CAN_CONFIG_STD_MSG
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

function CANRead(var id : longint; var data : array[8] of byte; var datalen: byte; var CAN_RX_MSG_FLAGS : byte) : byte;

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:

  • id is message identifier
  • data is an array of bytes up to 8 bytes in length
  • datalen is data length, from 1–8.
  • CAN_RX_MSG_FLAGS is value formed from constants (see CAN constants)
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
var
  rcv, rx, len : byte;
  data : array[8] of byte;
  id : longint;

// ...
rx := 0;
// ...
rcv := CANRead(id, data, len, rx);

CANWrite

Prototype

function CANWrite(id : longint; var data : array[8] of byte; datalen, CAN_TX_MSG_FLAGS : byte) : byte;

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:

  • id is CAN message identifier. Only 11 or 29 bits may be used depending on message type (standard or extended)
  • data is array of bytes up to 8 bytes in length
  • datalen is data length from 1–8
  • CAN_TX_MSG_FLAGS is value formed from constants (see CAN constants)
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
var
  tx, data : byte;
  id : longint;

// ...
tx := _CAN_TX_PRIORITY_0 and
      _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 _CAN_MODE_BITS    = 0x0A;   // Use this to access opmode  bits
const _CAN_MODE_STANDBY = 0x00;
const _CAN_MODE_ENABLE  = 0x02;
const _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 _CAN_CONFIG_SAMPLE_BIT      = 0x01;
const _CAN_CONFIG_SAMPLE_ONCE     = 0xFE;   // XXXX XXX0
const _CAN_CONFIG_SAMPLE_THRICE   = 0xFF;   // XXXX XXX1

const _CAN_CONFIG_MSG_TYPE_BIT    = 0x10;
const _CAN_CONFIG_STD_MSG         = 0xEF;   // XXX0 XXXX
const _CAN_CONFIG_XTD_MSG         = 0xFF;   // XXX1 XXXX

You may use bitwise and to form config byte out of these values. For example:

Copy Code To ClipboardCopy Code To Clipboard
init := _CAN_CONFIG_SAMPLE_THRICE and
        _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 _CAN_CONMOB_DIS        = 0x3F;   // 00XX XXXX   messsage objects work modes
const _CAN_CONMOB_EN_TX      = 0x7F;   // 01XX XXXX
const _CAN_CONMOB_EN_RX      = 0xBF;   // 10XX XXXX
const _CAN_CONMOB_EN_FRAME   = 0xFF;   // 11XX XXXX

const _CAN_IDE_FRAME_BIT     = 0x10;   // Identifier Extension
const _CAN_IDE_STD_FRAME     = 0xEF;   // XXX0 XXXX
const _CAN_IDE_XTD_FRAME     = 0xFF;   // XXX1 XXXX

const _CAN_RTR_BIT           = 0x20;
const _CAN_NO_RTR_FRAME      = 0xFF;   // XX1XXXXX
const _CAN_RTR_FRAME         = 0xDF;   // XX0XXXXX

const _CAN_TX                = 0x01;   // Transmitter Busy
const _CAN_TX_NO_BSY         = 0xFE;   // XXXX XXX0
const _CAN_TX_BSY            = 0xFF;   // XXXX XXX1

You may use bitwise and to adjust the appropriate flags. For example:

Copy Code To ClipboardCopy Code To Clipboard
// form value to be used with CANSendMessage:
send_config := _CAN_TX_PRIORITY_0 and
               _CAN_TX_XTD_FRAME  and
               _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 _CAN_RX        = 0x08;   // Receiver Busy
const _CAN_RX_NO_BSY = 0xF7;   // XXXX 0XXX
const _CAN_RX_BSY    = 0xFF;   // XXXX 1XXX

You may use bitwise and to adjust the appropriate flags. For example:

Copy Code To ClipboardCopy Code To Clipboard
if (MsgFlag and _CAN_RX_BSY) = 0 then
  ...
  // Receiver is busy.

CAN_MASK

CAN_MASK constants define mask codes. Function CANSetMask expects one of these as its argument:

const CAN_RX_MASK_0  = 0x00;
const CAN_RX_MASK_1  = 0x01;
const CAN_RX_MASK_2  = 0x02;
const CAN_RX_MASK_3  = 0x03;
const CAN_RX_MASK_4  = 0x04;
const CAN_RX_MASK_5  = 0x05;
const CAN_RX_MASK_6  = 0x06;
const CAN_RX_MASK_7  = 0x07;
const CAN_RX_MASK_8  = 0x08;
const CAN_RX_MASK_9  = 0x09;
const CAN_RX_MASK_10 = 0x0A;
const CAN_RX_MASK_11 = 0x0B;
const CAN_RX_MASK_12 = 0x0C;
const CAN_RX_MASK_13 = 0x0D;
const CAN_RX_MASK_14 = 0x0E;


CAN_FILTER

CAN_FILTER constants define filter codes. Function CANSetFilter expects one of these as its argument:

const CAN_RX_FILTER_0  = 0x00;
const CAN_RX_FILTER_1  = 0x01;
const CAN_RX_FILTER_2  = 0x02;
const CAN_RX_FILTER_3  = 0x03;
const CAN_RX_FILTER_4  = 0x04;
const CAN_RX_FILTER_5  = 0x05;
const CAN_RX_FILTER_6  = 0x06;
const CAN_RX_FILTER_7  = 0x07;
const CAN_RX_FILTER_8  = 0x08;
const CAN_RX_FILTER_9  = 0x09;
const CAN_RX_FILTER_10 = 0x0A;
const CAN_RX_FILTER_11 = 0x0B;
const CAN_RX_FILTER_12 = 0x0C;
const CAN_RX_FILTER_13 = 0x0D;
const CAN_RX_FILTER_14 = 0x0E;


CAN_MOB

CAN_MOB constants define flags related to transmission of a CAN message :


const _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
const _CAN_EN_MOB1_BIT    = 0x0002;
const _CAN_EN_MOB2_BIT    = 0x0004;
const _CAN_EN_MOB3_BIT    = 0x0008;
const _CAN_EN_MOB4_BIT    = 0x0010;
const _CAN_EN_MOB5_BIT    = 0x0020;
const _CAN_EN_MOB6_BIT    = 0x0040;
const _CAN_EN_MOB7_BIT    = 0x0080;
const _CAN_EN_MOB8_BIT    = 0x0100;
const _CAN_EN_MOB9_BIT    = 0x0200;
const _CAN_EN_MOB10_BIT   = 0x0400;
const _CAN_EN_MOB11_BIT   = 0x0800;
const _CAN_EN_MOB12_BIT   = 0x1000;
const _CAN_EN_MOB13_BIT   = 0x2000;
const _CAN_EN_MOB14_BIT   = 0x4000;

const _CAN_CONFIG_STMOB_TXOK  = 0x40;   // X1XX XXXX  From the CAN MOb Status Register
const _CAN_CONFIG_STMOB_RXOK  = 0x20;   // XX1X XXXX  Receive OK
const _CAN_CONFIG_STMOB_BERR  = 0x10;   // XXX1 XXXX  Bit Error (Only in transmission)
const _CAN_CONFIG_STMOB_SERR  = 0x08;   // XXXX 1XXX  Stuff Error
const _CAN_CONFIG_STMOB_CERR  = 0x04;   // XXXX X1XX  CRC Error
const _CAN_CONFIG_STMOB_FERR  = 0x02;   // XXXX XX1X  Form Error
const _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:

Copy Code To ClipboardCopy Code To Clipboard
program Can_1st;

var Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags, Rx_Data_Len  : byte;  // can flags
    RxTx_Data  : array[8] of byte;                           // can rx/tx data buffer
    Rx_ID : longint;
    Msg_Rcvd : byte;                                         // reception flag

const ID_1st : longint = 12111;
const ID_2nd : longint = 3;                                  // node IDs

begin

  PORTC := 0x00;                                            // clear PORTC
  DDRC  := 0xFF;                                            // set PORTC as output

  Msg_Rcvd := 0;

  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
                 and _CAN_NO_RTR_FRAME;                     // with CANWrite

  Can_Init_Flags := _CAN_CONFIG_SAMPLE_THRICE               // form value to be used
                 and _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);
  //----------------------------------------------------------//
  
  // set all mask bits of masks[3..14] to all ones
  //----------------------------------------------------------//
  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 ( TRUE ) do                                           // endless loop
    begin
      Msg_Rcvd := CANRead(Rx_ID , RxTx_Data , Rx_Data_Len, Can_Rcv_Flags);  // receive message
      if (((Rx_ID = ID_2nd) and Msg_Rcvd) <> 0 ) then                       // if message received check id
        begin
          PORTC := RxTx_Data[0];                                            // id correct, output data at PORTC
          Inc(RxTx_Data[0]);                                                // increment received data
          Delay_ms(10);
          CANWrite(ID_1st, RxTx_Data, 1, Can_Send_Flags);                   // send incremented data back
        end;
    end;
end.

Code for the second CAN node:

Copy Code To ClipboardCopy Code To Clipboard
program Can_2nd;

var Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags, Rx_Data_Len  : byte;  // can flags
    RxTx_Data  : array[8] of byte;                                       // CAN rx/tx data buffer
    Rx_ID : longint;
    Msg_Rcvd : byte;

const ID_1st  : longint = 12111;
const ID_2nd  : longint = 3;                                  // node IDs

begin

  PORTC := 0x00;                                            // clear PORTC
  DDRC  := 0xFF;                                            // set PORTC as output

  Msg_Rcvd := 0;

  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
                 and _CAN_NO_RTR_FRAME;                       // with CANWrite

  Can_Init_Flags := _CAN_CONFIG_SAMPLE_THRICE               // form value to be used
                 and _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 (TRUE) do                                                               // endless loop
    begin
      Msg_Rcvd := CANRead(Rx_ID , RxTx_Data , Rx_Data_Len, Can_Rcv_Flags);      // receive message
      if (((Rx_ID = ID_1st) and Msg_Rcvd) <> 0 ) then                           // if message received check id
        begin
          PORTC := RxTx_Data[0];                                                // id correct, output data at PORTC
          inc(RxTx_Data[0]);                                                    // increment received data
          CANWrite(ID_2nd, RxTx_Data, 1, Can_Send_Flags);                       // send incremented data back
        end;
    end;
end.
Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code