Jump to main content

##

# 3.16.2 Controller Area Network (CAN)

The Controller Area Network with Flexible Data-rate (CAN FD) module supports the following key features:

Standards Compliance:

- Full CAN 2.0B compliance

- Programmable bit rate

- ISO118981:2015 plus CAN FD 1.0 compliant, supports up to 64 data bytes payload/message

- Arbitration Bit Rate up to one Mbps

- FD Bit Rate up to eight Mbps Message Reception and Transmission:

- 32 message FIFOs

- Each FIFO can have up to 32 messages for a total of 512 messages

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

- User defined priority levels for message FIFOs used for transmission

- 32 acceptance filters for message filtering

- 32 acceptance filter mask registers for message filtering

- Automatic response to Remote Transmit Request (RTR)

Using The Library

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

CAN FD operation with polling

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

    void print_menu(void)

    {

    printf("Menu :\\r\\n"

    " -- Select the action:\\r\\n"

    " 1: Send FD standard message with ID: 0x45A and 64 byte data 0 to 63.
    \\r\\n"

    " 2: Send normal standard message with ID: 0x469 and 8 byte data 0 to
    \7. \\r\\n"

    " 3: To receive CAN FD or Normal message \\r\\n"

    " m: Display menu \\r\\n\\r\\n");

    }

    int main ( void )
    {

    uint32_t messageID = 0;

    uint32_t rx_messageID = 0;

    uint32_t status = 0;

    uint8_t messageLength = 0;

    uint8_t rx_messageLength = 0;

    uint8_t count = 0;

    uint8_t user_input = 0;

    CANFD_MSG_RX_ATTRIBUTE msgAttr = CANFD_MSG_RX_DATA_FRAME;

    /* Initialize all modules */

    SYS_Initialize ( NULL );

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

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

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

    print_menu();

    /* Prepare the message to send*/

    for (count = 0; count \< 64; count++)

    {

    message[count] = count;

    }

    while ( true )

    {

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

    /* Check if there is a received character */

    if(UART2_ReceiverIsReady() == true)

    {

    if(UART2_ErrorGet() == UART_ERROR_NONE)

    {

    UART2_Read((void *)&amp;user_input, 1);

    }

    switch (user_input)

    {

    case '1':

    printf(" Transmitting CAN FD Message:");

    messageID = 0x45A;

    messageLength = 64;

    if (CAN1_MessageTransmit(messageID, messageLength, message, 1,
    CANFD_MODE_FD_WITH_BRS, CANFD_MSG_TX_DATA_FRAME) == true)

    {

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

    LED_Toggle();

    }

    else

    {

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

    }

    break;

    case '2':

    printf(" Transmitting CAN Normal Message:");

    messageID = 0x469;

    messageLength = 8;

    if (CAN1_MessageTransmit(messageID, messageLength, message, 1,
    CANFD_MODE_NORMAL, CANFD_MSG_TX_DATA_FRAME) == true)

    {

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

    LED_Toggle();

    }

    else

    {

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

    }

    break;

    case '3':

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

    while (true)

    {

    if (CAN1_InterruptGet(2, CANFD_FIFO_INTERRUPT_TFNRFNIF_MASK))

    {

    /* Check CAN Status */

    status = CAN1_ErrorGet();

    if (status == CANFD_ERROR_NONE)

    {

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

    /* Receive New Message */

    if (CAN1_MessageReceive(&amp;rx_messageID, &amp;rx_messageLength,
    rx_message, 0, 2, &amp;msgAttr) == true)

    {

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

    status = CAN1_ErrorGet();

    if (status == CANFD_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 FD operation with interrupt

The following example shows the CAN FD 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 &amp; (CANFD_ERROR_TX_RX_WARNING_STATE |
    CANFD_ERROR_RX_WARNING_STATE |

    CANFD_ERROR_TX_WARNING_STATE | CANFD_ERROR_RX_BUS_PASSIVE_STATE |

    CANFD_ERROR_TX_BUS_PASSIVE_STATE | CANFD_ERROR_TX_BUS_OFF_STATE)) ==
    CANFD_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 = 0;

    bool user_input = 0;

    /* Initialize all modules */

    SYS_Initialize ( NULL );

    /* Prepare the message to send*/

    messageID = 0x45A;

    messageLength = 64;

    for (count = 0; count \< 64; count++)

    {

    message[count] = 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, 1 );

    state = APP_STATE_CAN_IDLE;

    CAN1_MessageTransmit(messageID, messageLength, message, 1,
    CANFD_MODE_FD_WITH_BRS, CANFD_MSG_TX_DATA_FRAME);

    break;

    case 1:

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

    state = APP_STATE_CAN_IDLE;

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

    /* Receive New Message */

    CAN1_MessageReceive(&amp;rx_messageID, &amp;rx_messageLength, rx_message,
    0, 2, &amp;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_TransmitEventFIFOElementGet | Get the Transmit Event FIFO Element for the transmitted message
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_TxFIFOQueueIsFull | Returns true if Tx FIFO/Queue 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
--- | --- | ---
CANFD_MODE | Enum | CANFD Mode for Classic CAN and CAN FD
CANFD_MSG_TX_ATTRIBUTE | Enum | CANFD Tx Message Attribute for Tx FIFO and Tx Queue
CANFD_MSG_RX_ATTRIBUTE | Enum | CANFD Message RX Attribute for Data Frame and Remote Frame
CANFD_FIFO_INTERRUPT_FLAG_MASK | Enum | CANFD FIFO Interrupt Status Flag Mask
CANFD_ERROR | Enum | CANFD Transfer Error data type
CANFD_CALLBACK | Typedef | CANFD Callback Function Pointer
CANFD_RX_MSG | Struct | CANFD RX Message Buffer structure
CANFD_RX_MSG_OBJECT | Struct | CANFD Receive Message Object structure
CANFD_TX_MSG_OBJECT | Struct | CANFD Transmit Message Object structure
CANFD_TX_EVENT_FIFO_ELEMENT | Struct | CANFD Trasmit Event FIFO Element structure
CAN_NOMINAL_BIT_TIMING | Struct | Nominal bit timing parameters
CAN_BIT_TIMING | Struct | Bit timing parameters