1.23.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 |