Jump to main content

##

# 3.25.2 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

- User defined 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 *)&amp;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(&amp;rx_messageID, &amp;rx_messageLength,
    rx_message, 0, 1, &amp;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 &amp; (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(&amp;rx_messageID, &amp;rx_messageLength, rx_message,
    0, 1, &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_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 is context) to be called when the given CAN's transfer events occur
CANx_ErrorCallbackRegister | Sets the pointer to the function (and it is 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