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 message in a normal CAN 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 8 and baudrate 500KHz.
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
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 =
}
{
}
uint32_t data_length)
{
tx_element.T1.bit.DLC = data_length;
for (i = 0; i < data_length; i++) {
tx_element.data[
i] = *
data;
data++;
}
}
uint32_t data_length)
{
tx_element.T1.bit.DLC = data_length;
for (i = 0; i < data_length; i++) {
tx_element.data[
i] = *
data;
data++;
}
}
{
volatile uint32_t status,
i, rx_buffer_index;
for (i = 0; i < CONF_CAN0_RX_BUFFER_NUM; i++) {
rx_buffer_index);
printf("\n\r Extended message received in Rx buffer. The received data is: \r\n");
} else {
printf("\n\r Standard message received in Rx buffer. The received data is: \r\n");
}
}
printf("\r\n\r\n");
}
}
}
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 message received in FIFO 0. The received data is: \r\n");
}
printf("\r\n\r\n");
}
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 message received in FIFO 1. The received data is: \r\n");
}
printf("\r\n\r\n");
}
| 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 standard message with ID: 0x45A and 4 byte data 0 to 3. \r\n"
" 3: Send standard message with ID: 0x469 and 4 byte data 128 to 131. \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 extended message with ID: 0x100000A5 and 8 byte data 0 to 7. \r\n"
" 7: Send extended message with ID: 0x10000096 and 8 byte data 128 to 135. \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.
uint32_t data_length)
{
tx_element.T1.bit.DLC = data_length;
for (i = 0; i < data_length; i++) {
tx_element.data[
i] = *
data;
data++;
}
}
uint32_t data_length)
{
tx_element.T1.bit.DLC = data_length;
for (i = 0; i < data_length; 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 message received in Rx buffer. The received data is: \r\n");
} else {
printf("\n\r Standard message received in Rx buffer. The received data is: \r\n");
}
}
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 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 message received in FIFO 1. The received data is: \r\n");
}
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 standard message with ID: 0x45A and 4 byte data 0 to 3. \r\n"
" 3: Send standard message with ID: 0x469 and 4 byte data 128 to 131. \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 extended message with ID: 0x100000A5 and 8 byte data 0 to 7. \r\n"
" 7: Send extended message with ID: 0x10000096 and 8 byte data 128 to 135. \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 4 byte data 0 to 3. \r\n");
CONF_CAN_ELEMENT_DATA_SIZE / 2);
break;
case '3':
printf(" 3: Send standard message with ID: 0x469 and 4 byte data 128 to 131. \r\n");
CONF_CAN_ELEMENT_DATA_SIZE / 2);
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 8 byte data 0 to 7. \r\n");
CONF_CAN_ELEMENT_DATA_SIZE);
break;
case '7':
printf(" 7: Send extended message with ID: 0x10000096 and 8 byte data 128 to 135. \r\n");
CONF_CAN_ELEMENT_DATA_SIZE);
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 4 byte data 0 to 3. \r\n");
CONF_CAN_ELEMENT_DATA_SIZE / 2);
break;
case '3':
printf(" 3: Send standard message with ID: 0x469 and 4 byte data 128 to 131. \r\n");
CONF_CAN_ELEMENT_DATA_SIZE / 2);
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 8 byte data 0 to 7. \r\n");
CONF_CAN_ELEMENT_DATA_SIZE);
break;
case '7':
printf(" 7: Send extended message with ID: 0x10000096 and 8 byte data 128 to 135. \r\n");
CONF_CAN_ELEMENT_DATA_SIZE);
break;
default:
break;
}
}