Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
21615 Discussions

MCP2515 CAN controller using SPI interface

Altera_Forum
Honored Contributor II
4,796 Views

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.
0 Kudos
1 Reply
Altera_Forum
Honored Contributor II
3,690 Views

 

--- 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.
0 Kudos
Reply