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 *)&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 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 |
