CAN on ATSAMC21J18A

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am learning how to program a ATSAMC21J18A MCU, and so far, I have managed to properly write an I2C initialization and Read/Write Transmission code on the register level, things like below...

SERCOM5->I2CM.ADDR.reg = 0x16;

SERCOM5->I2CM.DATA.reg = 0x44;

 

I am now trying to do a CAN Extended ID transmit and receive by writing the code on a register level as well, things like below...

CAN0->CCCR.reg |= CAN_CCCR_INIT;

CAN0->XIDFC.bit.LSE = 0x00; 

 

So now, I have roughly wrote the CAN initialization code, but the datasheet does not say clearly which registers should I put the Extended Address for Receiving messages, or also where should I put the data for Transmitting.

I am lost on the Tx/Rx FIFO and Message RAM as well, where to put the Address and Data etc.

Could someone guide me on the steps involved or a certain link for a tutorial on this topic?

 

Thanks in advance...

Regards,
Zie Hao

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any particular reason for not using Atmel START? It will generate all of the driver level code for you and give an example which has receiving/transmitting of a CAN frame with a standard ID, as well as extended.

murph

Debugging - Being a detective in a crime movie where you are also the murderer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Murph,

 

I tried using Atmel Start, but I now have a problem reading the received CAN message and saving the data into a buffer in my main program. Do you have any ideas/suggestions where I can do that?

Regards,
Zie Hao

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So, just a solution for future ppl who are using CAN for ATSAMC21J, below are sections of the code that im using for CAN tx and rx with the help of Atmel Start

 

void CAN_tx(uint32_t tx_address, uint8_t tx_message[8])    {
    struct can_message msg;
    struct can_filter  filter;
    //insert code to copy received message into tx_message_2
    if (rtr == 1)
    {
        /*Send extended message with ID: rtr_id and 8 byte data 0 to 7*/
        msg.id   = rtr_id;
        msg.type = CAN_TYPE_DATA;
        //msg.data = rx_data;
        msg.data = tx_message;
        msg.len  = 8;
        msg.fmt  = CAN_FMT_EXTID;
        can_async_register_callback(&CAN_0, CAN_ASYNC_TX_CB, (FUNC_PTR)CAN_0_tx_callback);
        can_async_enable(&CAN_0);
        can_async_write(&CAN_0, &msg);
        button_pressed = 0;
        rtr = 0;
    }
    else
    {
        /*Send extended message with ID: 0x155555A5 and 8 byte data rx_data*/
        msg.id   = tx_address;
        msg.type = CAN_TYPE_DATA;
        msg.data = rx_data;
        //msg.data = tx_message_2;
        msg.len  = 8;
        msg.fmt  = CAN_FMT_EXTID;
        can_async_register_callback(&CAN_0, CAN_ASYNC_TX_CB, (FUNC_PTR)CAN_0_tx_callback);
        can_async_enable(&CAN_0);
        can_async_write(&CAN_0, &msg);
        button_pressed = 0;
    }
}

void CAN0_Handler(void)
{
    volatile uint32_t status, interrupt;
    status = CAN0->IR.reg;
    interrupt = CAN0->IR.reg;
    
    if (interrupt & CAN_IR_RF0N) {                        // Rx New Message
        received_msg = 1;
        PORT->Group[0].OUTTGL.reg |= PORT_PA15;        // Toggle LED
        CAN0->IR.bit.RF0N = 1;                    // Reset Interrupt
    }
}

Main

while (1)
	{
		if (received_msg == 1)
		{
			int buffer_index = CAN0->RXF0S.bit.F0GI;
			CAN_0_rx_callback(&CAN_0);					// save data into rx_data
			CAN0->RXF0A.bit.F0AI = buffer_index;
			received_msg = 0;
			button_pressed = 1;
			//PORT->Group[0].OUTTGL.reg |= PORT_PA15;		// Toggle LED
		}
		
		if (button_pressed == 1) // or when message received
		{
                        CAN_tx(0x155555A5, tx_message_2);
                        button_pressed = 0;
                }
    }

 

 

Regards,
Zie Hao