The supported board list:
This quick start need two SAMC21 Xplained Pro boards with CAN interface connected by the jump wire: CANH - CANH and CANL - CANL.
It show how to handle standard and FD message in a CAN FD network with filter setting, message sending, receive buffer and FIFO usage and interrupt handling.
User can choose to set up two standard filter id and two extended filter id as receive filter. And then user can choose to send messages with the standard or extended filter id. If the message has been received, it will print the received data on the console. The configuration is defined in conf_can.h file with message max data length 64 and data phase baudrate 3MHz.
Setup
Prerequisites
There are no special setup requirements for this use-case.
Code
Add to the main application source file, outside of any functions:
#define CAN_RX_STANDARD_FILTER_INDEX_0 0
#define CAN_RX_STANDARD_FILTER_INDEX_1 1
#define CAN_RX_STANDARD_FILTER_ID_0 0x45A
#define CAN_RX_STANDARD_FILTER_ID_0_BUFFER_INDEX 2
#define CAN_RX_STANDARD_FILTER_ID_1 0x469
#define CAN_RX_EXTENDED_FILTER_INDEX_0 0
#define CAN_RX_EXTENDED_FILTER_INDEX_1 1
#define CAN_RX_EXTENDED_FILTER_ID_0 0x100000A5
#define CAN_RX_EXTENDED_FILTER_ID_0_BUFFER_INDEX 1
#define CAN_RX_EXTENDED_FILTER_ID_1 0x10000096
#define CAN_TX_BUFFER_INDEX 0
static uint8_t tx_message_0[CONF_CAN_ELEMENT_DATA_SIZE];
static uint8_t tx_message_1[CONF_CAN_ELEMENT_DATA_SIZE];
static volatile uint32_t standard_receive_index = 0;
static volatile uint32_t extended_receive_index = 0;
Copy-paste the following setup code to your user application:
{
config_cdc.baudrate = 38400;
config_cdc.mux_setting = EDBG_CDC_SERCOM_MUX_SETTING;
config_cdc.pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0;
config_cdc.pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1;
config_cdc.pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2;
config_cdc.pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3;
stdio_serial_init(&
cdc_instance, EDBG_CDC_MODULE, &config_cdc);
}
{
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
tx_message_1[
i] = i + 0x80;
}
pin_config.mux_position = CAN_TX_MUX_SETTING;
pin_config.mux_position = CAN_RX_MUX_SETTING;
}
{
sd_filter.S0.bit.SFEC =
}
{
}
{
et_filter.F0.bit.EFEC =
}
{
}
{
tx_element.T1.bit.DLC = 8;
for (i = 0; i < 8; i++) {
tx_element.data[
i] = *
data;
data++;
}
}
{
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
tx_element.data[
i] = *
data;
data++;
}
}
{
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
tx_element.data[
i] = *
data;
data++;
}
}
{
volatile uint32_t status,
i, rx_buffer_index;
if (status & CAN_RX_BUFFER_NEW_MESSAGE) {
for (i = 0; i < CONF_CAN0_RX_BUFFER_NUM; i++) {
rx_buffer_index);
printf("\n\r Extended FD message received in Rx buffer. The received data is: \r\n");
} else {
printf("\n\r Standard FD message received in Rx buffer. The received data is: \r\n");
}
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
}
printf("\r\n\r\n");
}
}
}
if (status & CAN_RX_FIFO_0_NEW_MESSAGE) {
standard_receive_index);
standard_receive_index);
standard_receive_index++;
if (standard_receive_index == CONF_CAN0_RX_FIFO_0_NUM) {
standard_receive_index = 0;
}
printf("\n\r Standard FD message received in FIFO 0. The received data is: \r\n");
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
}
} else {
printf("\n\r Standard normal message received in FIFO 0. The received data is: \r\n");
}
}
printf("\r\n\r\n");
}
if (status & CAN_RX_FIFO_1_NEW_MESSAGE) {
extended_receive_index);
extended_receive_index);
extended_receive_index++;
if (extended_receive_index == CONF_CAN0_RX_FIFO_1_NUM) {
extended_receive_index = 0;
}
printf("\n\r Extended FD message received in FIFO 1. The received data is: \r\n");
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
}
printf("\r\n\r\n");
}
if ((status & CAN_PROTOCOL_ERROR_ARBITRATION)
| CAN_PROTOCOL_ERROR_DATA);
printf("Protocol error, please double check the clock in two boards. \r\n\r\n");
}
}
{
printf("Menu :\r\n"
" -- Select the action:\r\n"
" 0: Set standard filter ID 0: 0x45A, store into Rx buffer. \r\n"
" 1: Set standard filter ID 1: 0x469, store into Rx FIFO 0. \r\n"
" 2: Send FD standard message with ID: 0x45A and 64 byte data 0 to 63. \r\n"
" 3: Send FD standard message with ID: 0x469 and 64 byte data 128 to 191. \r\n"
" 4: Set extended filter ID 0: 0x100000A5, store into Rx buffer. \r\n"
" 5: Set extended filter ID 1: 0x10000096, store into Rx FIFO 1. \r\n"
" 6: Send FD extended message with ID: 0x100000A5 and 64 byte data 0 to 63. \r\n"
" 7: Send FD extended message with ID: 0x10000096 and 64 byte data 128 to 191. \r\n"
" a: Send normal standard message with ID: 0x469 and 8 byte data 0 to 7. \r\n"
" h: Display menu \r\n\r\n");
}
Add to user application initialization (typically the start of main()
):
Workflow
- Create USART CDC module and CAN module software instance structure.
- Define CAN standard filter setting.
#define CAN_RX_STANDARD_FILTER_INDEX_0 0
#define CAN_RX_STANDARD_FILTER_INDEX_1 1
#define CAN_RX_STANDARD_FILTER_ID_0 0x45A
#define CAN_RX_STANDARD_FILTER_ID_0_BUFFER_INDEX 2
#define CAN_RX_STANDARD_FILTER_ID_1 0x469
#define CAN_RX_EXTENDED_FILTER_INDEX_0 0
#define CAN_RX_EXTENDED_FILTER_INDEX_1 1
#define CAN_RX_EXTENDED_FILTER_ID_0 0x100000A5
#define CAN_RX_EXTENDED_FILTER_ID_0_BUFFER_INDEX 1
#define CAN_RX_EXTENDED_FILTER_ID_1 0x10000096
- Define CAN standard transfer message setting.
#define CAN_TX_BUFFER_INDEX 0
static uint8_t tx_message_0[CONF_CAN_ELEMENT_DATA_SIZE];
static uint8_t tx_message_1[CONF_CAN_ELEMENT_DATA_SIZE];
- Define CAN standard receive message setting.
static volatile uint32_t standard_receive_index = 0;
static volatile uint32_t extended_receive_index = 0;
- Configure the USART CDC for output message.
{
config_cdc.baudrate = 38400;
config_cdc.mux_setting = EDBG_CDC_SERCOM_MUX_SETTING;
config_cdc.pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0;
config_cdc.pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1;
config_cdc.pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2;
config_cdc.pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3;
stdio_serial_init(&
cdc_instance, EDBG_CDC_MODULE, &config_cdc);
}
- Configure the CAN module.
{
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
tx_message_1[
i] = i + 0x80;
}
pin_config.mux_position = CAN_TX_MUX_SETTING;
pin_config.mux_position = CAN_RX_MUX_SETTING;
}
- Configure the CAN standard receive filter.
{
sd_filter.S0.bit.SFEC =
}
{
}
{
et_filter.F0.bit.EFEC =
}
{
}
- Configure the CAN transfer message.
{
tx_element.T1.bit.DLC = 8;
for (i = 0; i < 8; i++) {
tx_element.data[
i] = *
data;
data++;
}
}
{
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
tx_element.data[
i] = *
data;
data++;
}
}
{
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
tx_element.data[
i] = *
data;
data++;
}
}
- Implement the interrupt handler function.
{
volatile uint32_t status,
i, rx_buffer_index;
if (status & CAN_RX_BUFFER_NEW_MESSAGE) {
for (i = 0; i < CONF_CAN0_RX_BUFFER_NUM; i++) {
rx_buffer_index);
printf("\n\r Extended FD message received in Rx buffer. The received data is: \r\n");
} else {
printf("\n\r Standard FD message received in Rx buffer. The received data is: \r\n");
}
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
}
printf("\r\n\r\n");
}
}
}
if (status & CAN_RX_FIFO_0_NEW_MESSAGE) {
standard_receive_index);
standard_receive_index);
standard_receive_index++;
if (standard_receive_index == CONF_CAN0_RX_FIFO_0_NUM) {
standard_receive_index = 0;
}
printf("\n\r Standard FD message received in FIFO 0. The received data is: \r\n");
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
}
} else {
printf("\n\r Standard normal message received in FIFO 0. The received data is: \r\n");
}
}
printf("\r\n\r\n");
}
if (status & CAN_RX_FIFO_1_NEW_MESSAGE) {
extended_receive_index);
extended_receive_index);
extended_receive_index++;
if (extended_receive_index == CONF_CAN0_RX_FIFO_1_NUM) {
extended_receive_index = 0;
}
printf("\n\r Extended FD message received in FIFO 1. The received data is: \r\n");
for (i = 0; i < CONF_CAN_ELEMENT_DATA_SIZE; i++) {
}
printf("\r\n\r\n");
}
if ((status & CAN_PROTOCOL_ERROR_ARBITRATION)
| CAN_PROTOCOL_ERROR_DATA);
printf("Protocol error, please double check the clock in two boards. \r\n\r\n");
}
}
- User menu function.
{
printf("Menu :\r\n"
" -- Select the action:\r\n"
" 0: Set standard filter ID 0: 0x45A, store into Rx buffer. \r\n"
" 1: Set standard filter ID 1: 0x469, store into Rx FIFO 0. \r\n"
" 2: Send FD standard message with ID: 0x45A and 64 byte data 0 to 63. \r\n"
" 3: Send FD standard message with ID: 0x469 and 64 byte data 128 to 191. \r\n"
" 4: Set extended filter ID 0: 0x100000A5, store into Rx buffer. \r\n"
" 5: Set extended filter ID 1: 0x10000096, store into Rx FIFO 1. \r\n"
" 6: Send FD extended message with ID: 0x100000A5 and 64 byte data 0 to 63. \r\n"
" 7: Send FD extended message with ID: 0x10000096 and 64 byte data 128 to 191. \r\n"
" a: Send normal standard message with ID: 0x469 and 8 byte data 0 to 7. \r\n"
" h: Display menu \r\n\r\n");
}
Use Case
Code
Copy-paste the following code to your user application:
while(1) {
scanf("%c", (char *)&key);
switch (key) {
case 'h':
break;
case '0':
printf(" 0: Set standard filter ID 0: 0x45A, store into Rx buffer. \r\n");
break;
case '1':
printf(" 1: Set standard filter ID 1: 0x469, store into Rx FIFO 0. \r\n");
break;
case '2':
printf(" 2: Send standard message with ID: 0x45A and 64 byte data 0 to 63. \r\n");
break;
case '3':
printf(" 3: Send standard message with ID: 0x469 and 64 byte data 128 to 191. \r\n");
break;
case '4':
printf(" 4: Set extended filter ID 0: 0x100000A5, store into Rx buffer. \r\n");
break;
case '5':
printf(" 5: Set extended filter ID 1: 0x10000096, store into Rx FIFO 1. \r\n");
break;
case '6':
printf(" 6: Send extended message with ID: 0x100000A5 and 64 byte data 0 to 63. \r\n");
break;
case '7':
printf(" 7: Send extended message with ID: 0x10000096 and 64 byte data 128 to 191. \r\n");
break;
case 'a':
printf(" a: Send normal standard message with ID: 0x469 and 8 byte data 0 to 7. \r\n");
break;
default:
break;
}
}
Workflow
- Set up CAN module.
- Display user menu .
- Enter the main loop, wait for the user input .
while(1) {
scanf("%c", (char *)&key);
switch (key) {
case 'h':
break;
case '0':
printf(" 0: Set standard filter ID 0: 0x45A, store into Rx buffer. \r\n");
break;
case '1':
printf(" 1: Set standard filter ID 1: 0x469, store into Rx FIFO 0. \r\n");
break;
case '2':
printf(" 2: Send standard message with ID: 0x45A and 64 byte data 0 to 63. \r\n");
break;
case '3':
printf(" 3: Send standard message with ID: 0x469 and 64 byte data 128 to 191. \r\n");
break;
case '4':
printf(" 4: Set extended filter ID 0: 0x100000A5, store into Rx buffer. \r\n");
break;
case '5':
printf(" 5: Set extended filter ID 1: 0x10000096, store into Rx FIFO 1. \r\n");
break;
case '6':
printf(" 6: Send extended message with ID: 0x100000A5 and 64 byte data 0 to 63. \r\n");
break;
case '7':
printf(" 7: Send extended message with ID: 0x10000096 and 64 byte data 128 to 191. \r\n");
break;
case 'a':
printf(" a: Send normal standard message with ID: 0x469 and 8 byte data 0 to 7. \r\n");
break;
default:
break;
}
}