Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

MCP2515 CAN controller using SPI interface

Hello everybody,

This is my first post on the Altera Forums, and i have to say it's been quite helpfull to me the last few months, so thanks for that.

This is my situation:

I need to send and recieve messages via the CAN interface with the MCP2515 chip.

I've done the Quartus block diagram which includes the NIOS 2 processor, an SDRAM from the Deo-Nano board, and an SPI interface with which to communicate with the CAN controller, and everything works perfectly (no timing errors or nothing).

So basically, i just need help with the C coding using alt_avalon_spi_command. i'll just show my code and you give oppinions if you'd like.


void RESET ()
{
unsigned char command;
command=0x30;
			alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
}
unsigned char READ_RX_BUFF (unsigned char reg)
{
	//00 RXB0SIDH
	//01 RXB0D0
	//02 RXB1SIDH
	//03 RXB0D1
unsigned char rdata,rdata1,command;
unsigned char data_out;
unsigned int i;
command=(1<<7) | (1<<4) | (reg<<1);
printf("\n%d     ",command);
for (i=0; i<8; i++)
					{
				rdata=0 ;
				rdata1=0 ;
				data_out=0;
					}
		if ((reg==0) || (reg==2))
		{
			alt_avalon_spi_command(SPI_BASE,0,1,command,5,rdata,0);
				for (i=0; i<5; i++)
					{
					data_out= rdata ;
					printf("%x    ",data_out);
					}
		}
		if ((reg==1) || (reg==3))
				{
					alt_avalon_spi_command(SPI_BASE,0,1,command,8,rdata1,0);
						for (i=0; i<8; i++)
							{
							data_out= rdata1 ;
							printf("%x    ",data_out);
							}
				}
	return *data_out;
}
void SPI_WRITE(alt_u8 adress, alt_u8 message)
{
unsigned char command;
command=0x02;
	alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
	alt_avalon_spi_command(SPI_BASE,0,1,&adress,0,NULL,0);
	alt_avalon_spi_command(SPI_BASE,0,1,&message,0,NULL,0);
}
unsigned char SPI_READ(alt_u8 adress)
{
unsigned char command;
unsigned char read;
unsigned char data_out;
command=0x03;
read=0;
	alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
	alt_avalon_spi_command(SPI_BASE,0,1,&adress,1,read,0);
	data_out=read;
return data_out;
}
void SPI_LOAD_TX(long int message, alt_u8 reg)
{
	//reg 0x0   TXB0SIDH
	//reg 0x1   TXB0D0
	//reg 0x2   TXB1SIDH
	//reg 0x3   TXB0D1
	//reg 0x4   TXB2SIDH
	//reg 0x5   TXB1D2
unsigned char message1,command;   ////read byte 0x04
int i;
			command=(1<<6)|reg;
				alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
					if ((reg==0x00) || (reg==0x02) || (reg==0x4))
					{
						for (i=0; i<5; i++)
						{	message=message>>(i*8);
							message1=message & 0xff;
						alt_avalon_spi_command(SPI_BASE,0,1,message1,0,NULL,0);
						}
					}
					if ((reg==0x01) || (reg==0x03) || (reg==0x5))
						{
						for (i=0; i<8; i++)
						{	message=message>>(i*8);
						message1=message & 0xff;
						alt_avalon_spi_command(SPI_BASE,0,1,message1,0,NULL,0);
						}
					}
}
void RTS(alt_u8 reg)
{
	//reg 0x00   T1
	//reg 0x02   T2
	//reg 0x04   T3
unsigned char command;
	command=(0x01<<7) | reg;
	alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
}
void BIT_MODIFY(alt_u8 adress, alt_u8 mask, alt_u8 data)
{
unsigned char command;
	command=0x05;
	alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
	alt_avalon_spi_command(SPI_BASE,0,1,&adress,0,NULL,0);
	alt_avalon_spi_command(SPI_BASE,0,1,&mask,0,NULL,0);
	alt_avalon_spi_command(SPI_BASE,0,1,&data,0,NULL,0);
}
void SPEED_RATE(alt_u8 rate)
{
	if (rate==10)
	{
		BIT_MODIFY(CNF1,0xff,0x31);		//CNF1
		BIT_MODIFY(CNF2,0xff,0xb8);		//CNF2
		BIT_MODIFY(CNF3,0xff,0x05);		//CNF3
	}
	if (rate==20)
		{
		BIT_MODIFY(CNF1,0xff,0x18);		//CNF1
		BIT_MODIFY(CNF2,0xff,0xb8);		//CNF2
		BIT_MODIFY(CNF3,0xff,0x05);		//CNF3
		}
	if (rate==50)
		{
		BIT_MODIFY(CNF1,0xff,0x09);		//CNF1
		BIT_MODIFY(CNF2,0xff,0xb8);		//CNF2
		BIT_MODIFY(CNF3,0xff,0x05);		//CNF3
		}
	if (rate==100)
		{
		BIT_MODIFY(CNF1,0xff,0x04);		//CNF1
		BIT_MODIFY(CNF2,0xff,0xb8);		//CNF2
		BIT_MODIFY(CNF3,0xff,0x05);		//CNF3
		}
	if (rate==125)
		{
		BIT_MODIFY(CNF1,0xff,0x03);		//CNF1
		BIT_MODIFY(CNF2,0xff,0xb8);		//CNF2
		BIT_MODIFY(CNF3,0xff,0x05);		//CNF3
		}
	if (rate==250)
		{
		BIT_MODIFY(CNF1,0xff,0x01);		//CNF1
		BIT_MODIFY(CNF2,0xff,0xb8);		//CNF2
		BIT_MODIFY(CNF3,0xff,0x05);		//CNF3
		}
	if (rate==500)
		{
		BIT_MODIFY(CNF1,0xff,0x00);		//CNF1
		BIT_MODIFY(CNF2,0xff,0xb8);		//CNF2
		BIT_MODIFY(CNF3,0xff,0x05);		//CNF3
		}
}
void CONFIG_STATE(char state)
{
	if (state==1)
		{
			//CANCTRL status config
				BIT_MODIFY(CANCTRL,0xff,MODE_CONFIG);       //configuration mode
				SPEED_RATE(100);   //speed rate 100kbps
				BIT_MODIFY(0x2b,0xff,0x00);		//CANINTE clear
				BIT_MODIFY(0x2c,0xff,0x00);		//CANINTF clear
				//BFPCTRL set
				BIT_MODIFY(0x0c,0xff,0x0f);			// RXnBF set as interrupt pin(0x0f)
				BIT_MODIFY(RXB0CTRL,0xff,0x60);		// Write to RXB0CTRL and set masks and filters off
				BIT_MODIFY(RXB1CTRL,0xff,0x60);		// Write to RXB1CTRL and set masks and filters off
				//RX BUFFER 0
				BIT_MODIFY(RXM0SIDH,0xff,0x00);		// RXM0SIDH clear
				BIT_MODIFY(RXM0SIDL,0xff,0x00);		// RXM0SIDL clear
				BIT_MODIFY(RXM0EID8,0xff,0x00);		// RXM0EID8 clear
				BIT_MODIFY(RXM0EID0,0xff,0x00);		// RXM0EID0 clear
				//RX BUFFER 1
				BIT_MODIFY(RXM1SIDH,0xff,0x00);		// RXM1SIDH clear
				BIT_MODIFY(RXM1SIDL,0xff,0x00);		// RXM1SIDL clear
				BIT_MODIFY(RXM1EID8,0xff,0x00);		// RXM1EID8 clear
				BIT_MODIFY(RXM1EID0,0xff,0x00);		// RXM1EID0 clear
				//TXRTSCTRL set
				BIT_MODIFY(0x0d,0xff,0x01);		// request to send from txb0 (0x01)
				BIT_MODIFY(0x2D,0xff,0x00);		// clear EFLG
		}
	if (state==2)
		{
		BIT_MODIFY(CANCTRL,0xff,MODE_LISTEN);       //listen mode
		}
	if (state==3)
		{
		BIT_MODIFY(CANCTRL,0xff,MODE_LOOPBACK);     //loopback mode
		}
	if (state==4)
		{
		BIT_MODIFY(CANCTRL,0xff,MODE_SLEEP);        //sleeep mode
		}
	if (state==5)
		{
		BIT_MODIFY(CANCTRL,0xff,MODE_NORMAL);       //normal mode
		}
}
int main()
{unsigned long int delay;
unsigned char radu,radu1;
		RESET();
		CONFIG_STATE(1);
		CONFIG_STATE(5);
		while(1)
		{delay=0;
			while (delay<200000)
			{delay++;}
		y=READ_RX_BUFF(1);
		SPI_WRITE(0x61,0x05);
		x=SPI_READ(0x61);
		printf("         %d            %d  ",y,x);
		}
}

of course this includessome Macros declarations in a separate file.

So the problem is this. What am I doing wrong :)

thanks if you read, and sorry for the bad english.

1 Reply

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Hello everybody,

    This is my first post on the Altera Forums, and i have to say it's been quite helpfull to me the last few months, so thanks for that.

    This is my situation:

    I need to send and recieve messages via the CAN interface with the MCP2515 chip.

    I've done the Quartus block diagram which includes the NIOS 2 processor, an SDRAM from the Deo-Nano board, and an SPI interface with which to communicate with the CAN controller, and everything works perfectly (no timing errors or nothing).

    So basically, i just need help with the C coding using alt_avalon_spi_command. i'll just show my code and you give oppinions if you'd like.

    
    void RESET ()
    {
    unsigned char command;
    command=0x30;
                alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
    }
    unsigned char READ_RX_BUFF (unsigned char reg)
    {
        //00 RXB0SIDH
        //01 RXB0D0
        //02 RXB1SIDH
        //03 RXB0D1
    unsigned char rdata,rdata1,command;
    unsigned char data_out;
    unsigned int i;
    command=(1<<7) | (1<<4) | (reg<<1);
    printf("\n%d     ",command);
    for (i=0; i<8; i++)
                        {
                    rdata=0 ;
                    rdata1=0 ;
                    data_out=0;
                        }
            if ((reg==0) || (reg==2))
            {
                alt_avalon_spi_command(SPI_BASE,0,1,command,5,rdata,0);
                    for (i=0; i<5; i++)
                        {
                        data_out= rdata ;
                        printf("%x    ",data_out);
                        }
            }
            if ((reg==1) || (reg==3))
                    {
                        alt_avalon_spi_command(SPI_BASE,0,1,command,8,rdata1,0);
                            for (i=0; i<8; i++)
                                {
                                data_out= rdata1 ;
                                printf("%x    ",data_out);
                                }
                    }
        return *data_out;
    }
    void SPI_WRITE(alt_u8 adress, alt_u8 message)
    {
    unsigned char command;
    command=0x02;
        alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
        alt_avalon_spi_command(SPI_BASE,0,1,&adress,0,NULL,0);
        alt_avalon_spi_command(SPI_BASE,0,1,&message,0,NULL,0);
    }
    unsigned char SPI_READ(alt_u8 adress)
    {
    unsigned char command;
    unsigned char read;
    unsigned char data_out;
    command=0x03;
    read=0;
        alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
        alt_avalon_spi_command(SPI_BASE,0,1,&adress,1,read,0);
        data_out=read;
    return data_out;
    }
    void SPI_LOAD_TX(long int message, alt_u8 reg)
    {
        //reg 0x0   TXB0SIDH
        //reg 0x1   TXB0D0
        //reg 0x2   TXB1SIDH
        //reg 0x3   TXB0D1
        //reg 0x4   TXB2SIDH
        //reg 0x5   TXB1D2
    unsigned char message1,command;   ////read byte 0x04
    int i;
                command=(1<<6)|reg;
                    alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
                        if ((reg==0x00) || (reg==0x02) || (reg==0x4))
                        {
                            for (i=0; i<5; i++)
                            {    message=message>>(i*8);
                                message1=message & 0xff;
                            alt_avalon_spi_command(SPI_BASE,0,1,message1,0,NULL,0);
                            }
                        }
                        if ((reg==0x01) || (reg==0x03) || (reg==0x5))
                            {
                            for (i=0; i<8; i++)
                            {    message=message>>(i*8);
                            message1=message & 0xff;
                            alt_avalon_spi_command(SPI_BASE,0,1,message1,0,NULL,0);
                            }
                        }
    }
    void RTS(alt_u8 reg)
    {
        //reg 0x00   T1
        //reg 0x02   T2
        //reg 0x04   T3
    unsigned char command;
        command=(0x01<<7) | reg;
        alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
    }
    void BIT_MODIFY(alt_u8 adress, alt_u8 mask, alt_u8 data)
    {
    unsigned char command;
        command=0x05;
        alt_avalon_spi_command(SPI_BASE,0,1,command,0,NULL,0);
        alt_avalon_spi_command(SPI_BASE,0,1,&adress,0,NULL,0);
        alt_avalon_spi_command(SPI_BASE,0,1,&mask,0,NULL,0);
        alt_avalon_spi_command(SPI_BASE,0,1,&data,0,NULL,0);
    }
    void SPEED_RATE(alt_u8 rate)
    {
        if (rate==10)
        {
            BIT_MODIFY(CNF1,0xff,0x31);        //CNF1
            BIT_MODIFY(CNF2,0xff,0xb8);        //CNF2
            BIT_MODIFY(CNF3,0xff,0x05);        //CNF3
        }
        if (rate==20)
            {
            BIT_MODIFY(CNF1,0xff,0x18);        //CNF1
            BIT_MODIFY(CNF2,0xff,0xb8);        //CNF2
            BIT_MODIFY(CNF3,0xff,0x05);        //CNF3
            }
        if (rate==50)
            {
            BIT_MODIFY(CNF1,0xff,0x09);        //CNF1
            BIT_MODIFY(CNF2,0xff,0xb8);        //CNF2
            BIT_MODIFY(CNF3,0xff,0x05);        //CNF3
            }
        if (rate==100)
            {
            BIT_MODIFY(CNF1,0xff,0x04);        //CNF1
            BIT_MODIFY(CNF2,0xff,0xb8);        //CNF2
            BIT_MODIFY(CNF3,0xff,0x05);        //CNF3
            }
        if (rate==125)
            {
            BIT_MODIFY(CNF1,0xff,0x03);        //CNF1
            BIT_MODIFY(CNF2,0xff,0xb8);        //CNF2
            BIT_MODIFY(CNF3,0xff,0x05);        //CNF3
            }
        if (rate==250)
            {
            BIT_MODIFY(CNF1,0xff,0x01);        //CNF1
            BIT_MODIFY(CNF2,0xff,0xb8);        //CNF2
            BIT_MODIFY(CNF3,0xff,0x05);        //CNF3
            }
        if (rate==500)
            {
            BIT_MODIFY(CNF1,0xff,0x00);        //CNF1
            BIT_MODIFY(CNF2,0xff,0xb8);        //CNF2
            BIT_MODIFY(CNF3,0xff,0x05);        //CNF3
            }
    }
    void CONFIG_STATE(char state)
    {
        if (state==1)
            {
                //CANCTRL status config
                    BIT_MODIFY(CANCTRL,0xff,MODE_CONFIG);       //configuration mode
                    SPEED_RATE(100);   //speed rate 100kbps
                    BIT_MODIFY(0x2b,0xff,0x00);        //CANINTE clear
                    BIT_MODIFY(0x2c,0xff,0x00);        //CANINTF clear
                    //BFPCTRL set
                    BIT_MODIFY(0x0c,0xff,0x0f);            // RXnBF set as interrupt pin(0x0f)
                    BIT_MODIFY(RXB0CTRL,0xff,0x60);        // Write to RXB0CTRL and set masks and filters off
                    BIT_MODIFY(RXB1CTRL,0xff,0x60);        // Write to RXB1CTRL and set masks and filters off
                    //RX BUFFER 0
                    BIT_MODIFY(RXM0SIDH,0xff,0x00);        // RXM0SIDH clear
                    BIT_MODIFY(RXM0SIDL,0xff,0x00);        // RXM0SIDL clear
                    BIT_MODIFY(RXM0EID8,0xff,0x00);        // RXM0EID8 clear
                    BIT_MODIFY(RXM0EID0,0xff,0x00);        // RXM0EID0 clear
                    //RX BUFFER 1
                    BIT_MODIFY(RXM1SIDH,0xff,0x00);        // RXM1SIDH clear
                    BIT_MODIFY(RXM1SIDL,0xff,0x00);        // RXM1SIDL clear
                    BIT_MODIFY(RXM1EID8,0xff,0x00);        // RXM1EID8 clear
                    BIT_MODIFY(RXM1EID0,0xff,0x00);        // RXM1EID0 clear
                    //TXRTSCTRL set
                    BIT_MODIFY(0x0d,0xff,0x01);        // request to send from txb0 (0x01)
                    BIT_MODIFY(0x2D,0xff,0x00);        // clear EFLG
            }
        if (state==2)
            {
            BIT_MODIFY(CANCTRL,0xff,MODE_LISTEN);       //listen mode
            }
        if (state==3)
            {
            BIT_MODIFY(CANCTRL,0xff,MODE_LOOPBACK);     //loopback mode
            }
        if (state==4)
            {
            BIT_MODIFY(CANCTRL,0xff,MODE_SLEEP);        //sleeep mode
            }
        if (state==5)
            {
            BIT_MODIFY(CANCTRL,0xff,MODE_NORMAL);       //normal mode
            }
    }
    int main()
    {unsigned long int delay;
    unsigned char radu,radu1;
            RESET();
            CONFIG_STATE(1);
            CONFIG_STATE(5);
            while(1)
            {delay=0;
                while (delay<200000)
                {delay++;}
            y=READ_RX_BUFF(1);
            SPI_WRITE(0x61,0x05);
            x=SPI_READ(0x61);
            printf("         %d            %d  ",y,x);
            }
    }
    

    of course this includessome Macros declarations in a separate file.

    So the problem is this. What am I doing wrong :)

    thanks if you read, and sorry for the bad english.

    --- Quote End ---

    Hi, Pallys,

    Have you found an answer?

    I'm currently working on the same connection (Nios/MCP2515).

    I've learned from the datasheet that you cannot use BIT_MODIFY on all registers.

    You need to do an SPI_WRITE instead.

    Also, the minimum registers you need to write to are TXBnSIDH, TXBnSIDL and TXBnDLC before performing an RTS.

    From your comments, I can see you do not consider the last two, although you consider the data register TXBnDm.

    I think that before you send any data using TXBnDm you should, first, send only a message with headers, which will require less SPI tranmissions, thus rendering the process less prone to errors.

    Well, let me know if you could make it work.

    Thanks,

    Lucas.