1.22.3 Controller Area Network (CAN)

The Controller Area Network (CAN) module supports the following key features.

Standards Compliance:

  • Full CAN 2.0B compliance

  • Programmable bit rate up to 1 Mbps Message Reception and Transmission:

  • 32/16 message FIFOs

  • Each FIFO can have up to 32 messages

  • FIFO can be a transmit message FIFO or a receive message FIFO

  • Userdefined priority levels for message FIFOs used for transmission

  • Acceptance filters for message filtering

  • Acceptance filter mask for message filtering

  • Automatic response to Remote Transmit Request (RTR)

Using The Library

The CAN library supports the CAN Normal (Classic) mode. The CAN Normal mode can transfer message in a polling or an interrupt mode.

CAN normal operation with polling

The following example shows the CAN normal mode operation with polling implementation.

void print_menu(void)

{

printf(" ------------------------------ \\r\\n");

printf(" Press '1' to Transmit message \\r\\n");

printf(" Press '2' to Receive message \\r\\n");

}

int main ( void )
{

uint32_t messageID = 0;

uint32_t rx_messageID = 0;

uint8_t message[8];

uint8_t rx_message[8];

uint32_t status = 0;

uint8_t messageLength = 0;

uint8_t rx_messageLength = 0;

uint8_t count = 0;

uint8_t user_input = 0;

CAN_MSG_RX_ATTRIBUTE msgAttr = CAN_MSG_RX_DATA_FRAME;

/* Initialize all modules */

SYS_Initialize ( NULL );

printf(" ------------------------------ \\r\\n");

printf(" CAN Demo \\r\\n");

printf(" ------------------------------ \\r\\n");

print_menu();

/* Prepare the message to send*/

messageID = 0x469;

messageLength = 8;

for (count = 8; count \>=1; count--){

message[count - 1] = count;

}

while ( true )

{

/* Maintain state machines of all polled Harmony modules. */

/* Check if there is a received character */

if(UART6_ReceiverIsReady() == true)

{

if(UART6_ErrorGet() == UART_ERROR_NONE)

{

UART6_Read((void *)&user_input, 1);

}

switch (user_input)

{

case '1':

printf(" Transmitting Message:");

if (CAN1_MessageTransmit(messageID, messageLength, message, 0,
CAN_MSG_TX_DATA_FRAME) == true)

{

printf("Success \\r\\n");

LED_Toggle();

}

else

{

printf("Failed \\r\\n");

}

break;

case '2':

printf(" Waiting for message: \\r\\n");

while (true)

{

if (CAN1_InterruptGet(1, CAN_FIFO_INTERRUPT_RXNEMPTYIF_MASK))

{

/* Check CAN Status */

status = CAN1_ErrorGet();



if (status == CAN_ERROR_NONE)

{

memset(rx_message, 0x00, sizeof(rx_message));



/* Receive New Message */

if (CAN1_MessageReceive(&rx_messageID, &rx_messageLength,
rx_message, 0, 1, &msgAttr) == true)

{

printf(" New Message Received \\r\\n");

status = CAN1_ErrorGet();

if (status == CAN_ERROR_NONE)

{

/* Print message to Console */

uint8_t length = rx_messageLength;

printf(" Message - ID : 0x%x Length : 0x%x ", (unsigned int)
rx_messageID,(unsigned int) rx_messageLength);

printf("Message : ");

while(length)

{

printf("0x%x ", rx_message[rx_messageLength - length--]);

}

printf("\\r\\n");

LED_Toggle();

break;

}

else

{

printf("Error in received message");

}

}

else

{

printf("Message Reception Failed \\r");

}

}

else

{

printf("Error in last received message");

}

}

}

break;

default:

printf(" Invalid Input \\r\\n");

break;

}

print_menu();

}

}



/* Execution should not come here during normal operation */



return ( EXIT_FAILURE );

}

CAN normal operation with interrupt

The following example shows the CAN normal mode operation with interrupt implementation.

/* Application's state machine enum */

typedef enum

{

APP_STATE_CAN_RECEIVE,

APP_STATE_CAN_TRANSMIT,

APP_STATE_CAN_IDLE,

APP_STATE_CAN_USER_INPUT,

APP_STATE_CAN_XFER_SUCCESSFUL,

APP_STATE_CAN_XFER_ERROR

} APP_STATES;



/* Variable to save application state */

static APP_STATES state = APP_STATE_CAN_USER_INPUT;



void APP_CAN_Callback(uintptr_t context)

{

xferContext = context;



/* Check CAN Status */

status = CAN1_ErrorGet();



if ((status & (CAN_ERROR_TX_RX_WARNING_STATE |
CAN_ERROR_RX_WARNING_STATE |

CAN_ERROR_TX_WARNING_STATE | CAN_ERROR_RX_BUS_PASSIVE_STATE |

CAN_ERROR_TX_BUS_PASSIVE_STATE | CAN_ERROR_TX_BUS_OFF_STATE)) ==
CAN_ERROR_NONE)

{

switch ((APP_STATES)context)

{

case APP_STATE_CAN_RECEIVE:

case APP_STATE_CAN_TRANSMIT:

{

state = APP_STATE_CAN_XFER_SUCCESSFUL;

break;

}

default:

break;

}

}

else

{

state = APP_STATE_CAN_XFER_ERROR;

}

}



int main ( void )
{

uint8_t count = 8;

bool user_input = 0;



/* Initialize all modules */

SYS_Initialize ( NULL );



/* Prepare the message to send*/

messageID = 0x469;

messageLength = 8;

for (count = 8; count \>=1; count--){

message[count - 1] = count;

}



while ( true )

{

if (state == APP_STATE_CAN_USER_INPUT)

{

if(SWITCH_Get() == SWITCH_PRESSED_STATE)

{

while(SWITCH_Get() == SWITCH_PRESSED_STATE);



switch (user_input)

{

case 0:

CAN1_CallbackRegister( APP_CAN_Callback,
(uintptr_t)APP_STATE_CAN_TRANSMIT, 0 );

state = APP_STATE_CAN_IDLE;

CAN1_MessageTransmit(messageID, messageLength, message, 0,
CAN_MSG_TX_DATA_FRAME);

break;

case 1:

CAN1_CallbackRegister( APP_CAN_Callback,
(uintptr_t)APP_STATE_CAN_RECEIVE, 1 );

state = APP_STATE_CAN_IDLE;

memset(rx_message, 0x00, sizeof(rx_message));

/* Receive New Message */

CAN1_MessageReceive(&rx_messageID, &rx_messageLength, rx_message,
0, 1, &msgAttr);

break;

default:

break;

}

}

else

{

continue;

}

}

/* Check the application's current state. */

switch (state)

{

case APP_STATE_CAN_IDLE:

{

/* Application can do other task here */

break;

}

case APP_STATE_CAN_XFER_SUCCESSFUL:

{

if ((APP_STATES)xferContext == APP_STATE_CAN_RECEIVE)

{

}

else if ((APP_STATES)xferContext == APP_STATE_CAN_TRANSMIT)

{

}

LED_Toggle();

state = APP_STATE_CAN_USER_INPUT;

break;

}

case APP_STATE_CAN_XFER_ERROR:

{

if ((APP_STATES)xferContext == APP_STATE_CAN_RECEIVE)

{

}

else

{

}

state = APP_STATE_CAN_USER_INPUT;

break;

}

default:

break;

}



}



/* Execution should not come here during normal operation */



return ( EXIT_FAILURE );
}

Library Interface

peripheral library provides the following interfaces:

Functions

Name Description
CANx_Initialize Initializes given instance of the CAN peripheral
CANx_MessageTransmit Transmits a message into CAN bus
CANx_MessageReceive Receives a message from CAN bus
CANx_MessageAbort Abort request for a FIFO
CANx_MessageAcceptanceFilterSet Set Message acceptance filter configuration
CANx_MessageAcceptanceFilterGet Get Message acceptance filter configuration
CANx_MessageAcceptanceFilterMaskSet Set Message acceptance filter mask configuration
CANx_MessageAcceptanceFilterMaskGet Get Message acceptance filter mask configuration
CANx_ErrorGet Returns the error during transfer
CANx_ErrorCountGet Returns the transmit and receive error count during transfer
CANx_InterruptGet Returns the FIFO Interrupt status
CANx_TxFIFOIsFull Returns true if Tx FIFO is full otherwise false
CANx_AutoRTRResponseSet Set the Auto RTR response for remote transmit request
CANx_BitTimingCalculationGet Returns the bit timing information
CANx_BitTimingSet Sets the bit timing
CANx_CallbackRegister Sets the pointer to the function (and it's context) to be called when the given CAN's transfer events occur
CANx_ErrorCallbackRegister Sets the pointer to the function (and it's context) to be called when error occurs in CAN

Data types and constants

Name Type Description
CAN_MSG_TX_ATTRIBUTE Enum CAN Message TX Attribute for Data Frame and Remote Frame
CAN_MSG_RX_ATTRIBUTE Enum CAN Message RX Attribute for Data Frame and Remote Frame
CAN_FIFO_INTERRUPT_FLAG_MASK Enum CAN FIFO Interrupt Status Flag Mask
CAN_ERROR Enum CAN Transfer Error data type
CAN_CALLBACK Typedef CAN Callback Function Pointer
CAN_RX_MSG Struct CAN RX Message Buffer structure
CAN_TX_RX_MSG_BUFFER Struct CAN Message Buffer structure
CAN_NOMINAL_BIT_TIMING Struct Nominal bit timing parameters
CAN_BIT_TIMING Struct Bit timing parameters