CAN out - CAN output mailbox

The CAN_out block implements an output mailbox that supports sending messages using the CAN bus protocol. To receive messages, the CAN in block should be used instead. The supported CAN protocol variants are as follows:

  • CAN 2.0A: standard format (11-bit identifier), up to 8 bytes payload
  • CAN 2.0B: extended format (29-bit identifier), up to 8 bytes payload
  • CAN FD: standard and extended format, up to 64 bytes payload

CAN 2.0A/B are supported on all imperix controllers, provided that the related hardware exists. However, CAN FD (flexible data) is only supported on the B-Box 4. The detailed compatibility list is shown below.

CANopen is a high-level protocol (OSI layer 7), which should not be confused with CAN (OSI layers 1 and 2). It is currently not supported on imperix equipment.

ControllerHardware resourcesCAN 2.0ACAN 2.0BCAN FD
B-Box 42x channels (one RJ45 socket for each)
Max. 5 Mbps (FD)
YesYesYes
B-Box 3 (RCP)1x channel (one RJ45 socket)
Max. 1 Mbps
YesYesNo
B-Board 3 (PRO)1x channel (Tx/Rx pins or D-sub on EVM)
Max. 1 Mbps
YesYesNo
B-Box microN/ANoNoNo
TPI 80321x channel (two common RJ45 sockets)
Max. 1 Mbps
YesYesNo
Supported variants of the CAN protocol on imperix controllers

Parameters

Addressing

  • Physical port: selects the port on which the mailbox operate (Port A or Port B). Port B is only available on B-Box 4. For all the other devices, Port A must be selected.
  • Frame format: selects between Standard (11-bit identifier) and Extended (29-bit identifier).
  • Identifier (ID): sets the CAN identifier.
  • Enable CAN FD Bit Rate Switch (BRS): Activates the CAN-FD extension to enable the communication at a higher data bitrate (see also CAN bus configuration below).

Communication parameters

  • Signal(s) type: defines the data type accepted in the data input (int8, int16, int32, uint8, uint16, uint32, float32, or float64).
  • Number of signals: specifies the vector size of the data to be sent.
  • Byte order: defines the byte order in which the data will be sent. Either little-endian or big-endian.
  • Data transmission mode: selects when the data is sent.
    • On-demand: the user manually triggers the message transmissions.
    • Periodically: the message is sent periodically, whether the data has been changed or not.
  • Tx Frequency (Hz): sets the data transmission frequency when the Data transmission mode is set to Periodically.

CAN bus configuration

In Simulink, the CAN bus configuration is performed from within the CAN block. In PLECS, the configuration is performed in the Target tab of Coder options windows (Coder -> Coder options, or Ctrl+Alt+B).

  • The bitrate is the rate at which bits are transmitted on the bus (up to 1 Mbps),
  • The data bitrate is the increased bitrate used to transmit the CAN FD frame payload when the Bit Rate Switch (BRS) is enabled (up to 5 Mbps).
CAN bus configuration in Simulink
CAN bus configuration in PLECS

Simulink block

Signal specification

  • The data input signal supports a vector of data. The accepted data type is configured by Signal type parameter. The vector length can be configured with Number of signals parameter.
  • The second input is the send data signal. It is used to initiate a data transmission when the on-demand mode has been selected. Data is sent upon a rising edge on this signal.

Mask

PLECS block

Signal specification

  • The data input signal supports a vector of data. The accepted data type is configured by Signal type parameter. The vector length can be configured with Number of signals parameter.
  • The second input is the send data signal. It is used to initiate a data transmission when the on-demand mode has been selected. Data is sent upon a rising edge on this signal.

Mask

C++ functions

Standard functions

void Can_ConfigureCanBus(unsigned int bitrate, tCanPort can_port, bool canfd, 
unsigned int dataBitrate);Code language: C++ (cpp)

Configures the CAN bus.

Can only be called in UserInit().

Parameters

  • bitrate: transfer rate of the CAN bus in bits/s (up to 1 Mbit/s)
  • can_port: CAN port to configure (CAN_A or CAN_B)
  • canfd: enable CAN FD mode (false = classic CAN, true = CAN FD)
  • dataBitrate: transfer rate of the data phase for CAN FD (only used if canfd = true, up to 5 Mbit/s)
bool Can_ConfigureOutputMailbox(unsigned int maildboxId, unsigned int canIdentifier, unsigned int dataLength, float maxTxFrequency, tEndianness endianness, bool extended, tCanPort can_port, bool bitrateSwitch);Code language: C++ (cpp)

Configures a CAN output mailbox.

Can only be called in UserInit().

Parameters

  • mailboxId: the mailbox unique identifier. This ID must be unique throughout all ETH and CAN input/output mailboxes
  • canAddress: the identifier of the CAN input mailbox. The CAN identifier range is 0 to 2047, and it also represents the message priority
  • dataLength: number of bytes of data to transmit (1 to 8 bytes)
  • maxTxFrequency: maximal frequency at which data can be sent. The frequency must be a multiple of the main interrupt frequency. If the requested frequency is not achievable, it will be automatically set to the closest valid frequency
  • endianness: defines the bytes order (BIG_ENDIAN or LITTLE_ENDIAN)
  • extended: enable the extended frame format (true = 29-bit identifier, false = 11-bit identifier)
  • can_port: the target CAN port (CAN_A or CAN_B)
  • bitrateSwitch: enable bitrate switching for CAN FD (only applicable if CAN FD is enabled)

Return value

  • Returns false if the maximum output mailboxes limit is exceeded or if the canIdentifier is invalid.
int Can_Write(unsigned int maildboxId, void* data, int size);Code language: C++ (cpp)

These functions are used to send data on the CAN bus.

Can only be called in the interrupt routine.

Parameters

  • maildboxId: the CAN input mailbox unique identifier
  • data: pointer to the data to be loaded into the CAN write buffer
  • size: number of bytes of data to transmit (must correspond to the configured dataLength for the selected mailbox

Return value

  • Returns 1 if the data has successfully been loaded in the write buffer, returns 0 otherwise.

Example of use

This example shows how to configure and use CAN Port A in Classic CAN mode with a baud rate of 1 Mb/s. Two mailboxes are initialized using an unique ID of 0 and 1, a CAN identifier of 128 and 129, a fixed data length of 8 bytes and 8 bytes (total size of the structure), and a transfer rate of 500 Hz and 1000 Hz.

Data stored in any structure (or any array or data type) will be transmitted at a decimated rate derived from the interrupt frequency. This rate is tuned to match, or closely approximate, the frequency specified in the mailbox configuration.

#include "user.h"

#define MAILBOX_ID_A   0
#define MAILBOX_ID_B   1
#define CAN_ID_A       128
#define CAN_ID_B       129

uint8_t data_a[8] = {0};

struct {
  float   field_0;
  uint8_t field_1;
} data_b;

tUserSafe UserInit(void)
{
  Clock_SetFrequency(CLOCK_0, SW_FREQ);
  ConfigureMainInterrupt(UserInterrupt, CLOCK_0, 0.5);

  Can_ConfigureCanBus(1000000, CAN_A, false, 0);
  Can_ConfigureOutputMailbox(MAILBOX_ID_A, CAN_ID_A, sizeof(data_a), 500, LITTLE_ENDIAN, false, CAN_A, false);
  Can_ConfigureOutputMailbox(MAILBOX_ID_B, CAN_ID_B, sizeof(data_b), 1000, LITTLE_ENDIAN, false, CAN_A, false);
  return SAFE;
}
 
tUserSafe UserInterrupt(void)
{
  data_a[0] = 1;
  // ...
  data_a[7] = 8;

  data_b.field_0 = 4.0;
  data_b.field_1 = 255;

  Can_Write(MAILBOX_ID_A, (void *)data_a, sizeof(data_a));
  Can_Write(MAILBOX_ID_B, (void *)&data_b, sizeof(data_b));

  return SAFE;
}

void UserError(tErrorSource source)
{

}Code language: C++ (cpp)

Legacy functions

// 64-bit (8 bytes) types: uint64, int64 and double
int Can_Write(unsigned int maildboxId, uint64_t data); //8 bytes
int Can_Write(unsigned int maildboxId, int64_t data); //8 bytes
int Can_Write(unsigned int maildboxId, double data); //8 bytesCode language: C++ (cpp)
// 32-bit (4 bytes) types: int32, uint32 and float
// dataLow  represents the bytes 0, 1, 2 and 3
// dataHigh represents the bytes 4, 5, 6 and 7
int Can_Write(unsigned int maildboxId, unsigned int dataLow, unsigned int dataHigh); //8 bytes
int Can_Write(unsigned int maildboxId, unsigned int dataLow); //4 bytes
int Can_Write(unsigned int maildboxId, int dataLow, int dataHigh); //8 bytes
int Can_Write(unsigned int maildboxId, int dataLow); //4 bytes
int Can_Write(unsigned int maildboxId, float dataLow, float dataHigh); //8 bytes
int Can_Write(unsigned int maildboxId, float dataLow); //4 bytesCode language: C++ (cpp)
// 16-bit (2 bytes) types: int16 and uint16
// dataLow     represents the bytes 0 and 1
// dataMedLow  represents the bytes 2 and 3
// dataMedHigh represents the bytes 4 and 5
// dataHigh    represents the bytes 6 and 7
int Can_Write(unsigned int maildboxId, uint16_t dataLow, uint16_t dataMedLow, uint16_t dataMedHigh, uint16_t dataHigh); //8 bytes
int Can_Write(unsigned int maildboxId, uint16_t dataLow, uint16_t dataMedLow, uint16_t dataMedHigh); //6 bytes
int Can_Write(unsigned int maildboxId, uint16_t dataLow, uint16_t dataMedLow); //4 bytes
int Can_Write(unsigned int maildboxId, uint16_t dataLow); //2 bytes
int Can_Write(unsigned int maildboxId, int16_t dataLow, int16_t dataMedLow, int16_t dataMedHigh, int16_t dataHigh); //8 bytes
int Can_Write(unsigned int maildboxId, int16_t dataLow, int16_t dataMedLow, int16_t dataMedHigh); //6 bytes
int Can_Write(unsigned int maildboxId, int16_t dataLow, int16_t dataMedLow); //4 bytes
int Can_Write(unsigned int maildboxId, int16_t dataLow); //2 bytesCode language: C++ (cpp)
// array of uint8
typedef struct {
  uint8_t data[8];
} tCanMsg;

int Can_Write(unsigned int maildboxId, tCanMsg& data); //1 to 8 bytesCode language: C++ (cpp)

These functions are used to send data on the CAN bus.

Can only be called in the interrupt routine.

Parameters

  • maildboxId: the CAN input mailbox unique identifier
  • data: data to be loaded into the output mailbox write buffer

Return value

  • Returns 1 if the data has successfully been loaded in the write buffer, returns 0 otherwise.