CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

MCP2515 CAN RXStatus not working.... datasheet wrong ?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

MCP2515 CAN RXStatus not working.... datasheet wrong ?
PostPosted: Wed Feb 22, 2006 11:42 pm     Reply with quote

So.....

I have my MCP2515 working pretty well, wrote a driver in C, got messages to loopback, but...

RXSTATUS (0xB0) reports wrong data.


Here is some of my ouput to give you an idea of what could be going on, the source is long and complicated. The problem here is reading RXStatus gives me 00000011 and it should be 10000000.


Code:

Resetting MCP2515

Read STAT : 80
Read CTRL : 87

Set to Loopback
Read STAT : 40
Read CTRL : 47

Set to 250k and Accept All
Read CFG1 : 01
Read CFG2 : ac
Read CFG3 : 47
Read RXB0 : 60

Set ID TX0 : 7EB
Setting Data 10,20,30,40
Priority : 03


Clearing Local Data


Read TX0ID : 7EB
DLC : 04
DT0 : 10
DT0 : 20
DT0 : 30
DT0 : 40
Pri : 03


Sending CAN Message

INTF : 05
RXST : 03      <--- WRONG
Read RX0DLC : 04
Read RX0ID : 7EB
Rear RX0DAT: 10,20,30,40




So, I setup the chip, put it in loopback, write the TXB0 data, clear my local vars and read in the data from TX0 just to make sure it went in. Send the message by using a 0x81 command. INTF turns to 101, but RXSTATUS should not be 0x03. It should be 0x40 according to the datasheet.

Anyone know what could be wrong here / Have this problem ? I mean I worked around it, but I'de like to know why RXStatus doesn't work.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 12:43 am     Reply with quote

Here is the data sheet for the MCP2515:
http://ww1.microchip.com/downloads/en/DeviceDoc/21801d.pdf

Quote:

RXSTATUS
STAT
RXST

I searched the data sheet for the words above, as given in your post.
I can't find any register by those names.

Quote:
RXSTATUS (0xB0)

I also searched for a register at address 0xB0, but can't find it.
According to the register map on page 61, the register addresses are
from 0x00 to 0x7F. There is no register at 0xB0.

Can you clarify this ?
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 11:59 am     Reply with quote

Sure thing,

Page 67, Figure 12-9.

RX Status Instruction
10110000 = 0xB0

Sucks, now I am having the same error with READ STATUS, which is a super handy way of checking the rx and tx status, only 1 call to spi for all tx instead of 3 calls to check the RTS bits. Same page figure 12-8
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 2:21 pm     Reply with quote

I send 1 message from TX0 to RX0

Check the intf, RX0==1, RX1==0... good

Now I check the Read Status Command (0xA0), == 0x47.

Now how could that be ? It cant.

I'm seriously thinking that this command is broken.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 3:22 pm     Reply with quote

Can you post a really short program that shows the problem ?
It show your SPI setup code, and your SPI read function, and
whatever other functions are required for the test program to
compile properly. Post a complete (but short) program that
can be pasted into MPLAB and compiled.
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 4:38 pm     Reply with quote

Not really. I have all of my functions so specifically set up that its really not possible to post a cut down version without posting the entire program. Or at least it will take more work cutting them out for an example then just rewriting them.

I borrow this code from DougH here, added the send message and check registers real fast.

Funny... Its different from MY code, but still wrong. Making me think the data that its returning is misc data from some other register or ram.

Code:

CAN CFG TEST

Resetting the MCP2515

Reading registers...
CANSTAT = 80
CANCTRL = 87
CNF1 = 00
CNF2 = 00
CNF3 = 00

Writing status registers...
Setting CNF1 = 01
Seg CNF2 = ac
Setting CNF3 = 47

Reading back status registers...
CANSTAT = 40
CANCTRL = 47
CNF1 = 01
CNF2 = ac
CNF3 = 47

Running...
SENT MESSAGE

Message in RXB0:
RX0DLC : 04
INTFlags : 05
READSTATUS : 20
RXSTATUS : 20



Just a warning, this is pretty rough
Code:

#include <16F876A.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT,PUT
#use delay(clock=20000000)
#use rs232(DEBUGGER)

#define CAN_DO_DEBUG TRUE

//define the SPI control pins for PIC16F876A 28 PDIP
#define MCP2515_CS   PIN_A3
#define MCP2515_RESET_PIN PIN_A2
#define READCMD      0x03
#define WRITECMD   0x02

#include <can-mcp2510.c> //Same for the 2515


int rreg,i;
long temp;

int data[8];


void ResetMCP2515(void)
{
   output_high(MCP2515_CS);
   output_low(MCP2515_RESET_PIN);
   delay_us(10);
   output_high(MCP2515_RESET_PIN);
}

int ReadRegister(int regaddr)
{
   output_low(MCP2515_CS);
   spi_write(READCMD);
   spi_write(regaddr);
   rreg = spi_read(0);
   output_high(MCP2515_CS);
   return(rreg);
}

void WriteRegister(int regaddr, int regvalue)
{
   output_low(MCP2515_CS);
   spi_write(WRITECMD);
   spi_write(regaddr);
   spi_write(regvalue);
   output_high(MCP2515_CS);
}

void ConfigureMCP2515(void)
{
   int cnfr1 = 0x01;
   int cnfr2 = 0xAC;
   int cnfr3 = 0x47;

   can_debug("Setting CNF1 = %2x\n", cnfr1);
   can_debug("Setting CNF2 = %2x\n", cnfr2);
   can_debug("Setting CNF3 = %2x\n", cnfr3);

   WriteRegister(CANCTRL, 0x80); //set to config mode
   WriteRegister(CNF1, cnfr1);
   WriteRegister(CNF2, cnfr2);
   WriteRegister(CNF3, cnfr3);

   WriteRegister(RXB0CTRL,0x60);
   WriteRegister(RXB1CTRL,0x60); //accept all messages

   WriteRegister(CANCTRL, 0x47); //reset to loopback
}

void main()
{
   can_debug("\n\nCAN CFG TEST\n");

   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | SPI_CLK_DIV_4);

   can_debug("\nResetting the MCP2515\n");
   ResetMCP2515();

   can_debug("\nReading registers...\n");
   can_debug("CANSTAT = %2x\n", ReadRegister(CANSTAT));
   can_debug("CANCTRL = %2x\n", ReadRegister(CANCTRL));
   can_debug("CNF1 = %2x\n", ReadRegister(CNF1));
   can_debug("CNF2 = %2x\n", ReadRegister(CNF2));
   can_debug("CNF3 = %2x\n", ReadRegister(CNF3));

   can_debug("\nWriting status registers...\n");
   ConfigureMCP2515();

   can_debug("\r\nReading back status registers...\n");
   can_debug("CANSTAT = %2x\n", ReadRegister(CANSTAT));
   can_debug("CANCTRL = %2x\n", ReadRegister(CANCTRL));
   can_debug("CNF1 = %2x\n", ReadRegister(CNF1));
   can_debug("CNF2 = %2x\n", ReadRegister(CNF2));
   can_debug("CNF3 = %2x\n", ReadRegister(CNF3));

   can_debug("\nRunning...");






   data[0]=0x10;
   data[0]=0x20;
   data[0]=0x30;
   data[0]=0x40;

   WriteRegister(TXB0SIDH, 0x0F);
   WriteRegister(TXB0SIDL, 0x02);

   WriteRegister(TXB0DLC, 0x04);

   for (i=0; i<0x04; i++)
    WriteRegister(TXB0D0, data[i]);

   output_low(MCP2515_CS);
   spi_write(0x81);           //Quick set RTS command
   output_high(MCP2515_CS);

   printf("\nSENT MESSAGE\n\n");


   delay_ms(1);



   printf("Message in RXB0: \n");

   temp = ReadRegister(RXB0DLC);
   printf("RX0DLC : %2X\n", temp);


/*
   printf("RX0DATA :");             //I wrote this REALLY fast and there is
   for (i=0; i<0x04; i++) {         //a bug in it, not important anyway
    temp = ReadRegister(RXB0D0+i);  //look at DLC that comes back
    printf(" %2X", temp);
   }
    printf("\n\n");
*/

   temp= ReadRegister(CANINTF);           //WORKS
   printf("INTFlags : %2X\n", temp);

   temp= ReadRegister(0xA0);              //BROKEN
   printf("READSTATUS : %2X\n", temp);

   temp= ReadRegister(0xB0);              //BROKEN
   printf("RXSTATUS : %2X", temp);



   while(TRUE)
   {
   }
}


My code is pulling 03 and 09 for the, this one returns 0x20 for both. On my setup anyway,
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 7:09 pm     Reply with quote

I made some changes to the code and how I have this:

Code:

INTF = 0x05
READ STATUS = 0x08
RXSTATUS = 0x08


Which can NEVER happen.

INTF = 0x05 means I've had activity on TXB0 (sent a message) and RXB0 (received that message)

READ STATUS = 0x08 means TXB0 set an int... which from above I can see is true.... except that it should be 9... the 0bit should be a 1 as we saw from the INTF register

RXSTATUS = 0x08 is REALLY messed up. It says there is no receive buffer with a message waiting. That no filters were hit (true), but that there is a Standard Remote Frame message IS waiting... thus contradicting itself.

Ideas ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 23, 2006 11:20 pm     Reply with quote

The problem is that you're not following the MCP2515 data sheet.
Also, you wanted to improve on the CCS MCP2510 driver by changing
it from bit-banging to hardware SPI. The problem is that you truncated
parts of the driver. CCS has different routines for reading the status
and for reading the buffer. You've combined them all into one routine.

According to the data sheet and the CCS driver, you have to read
16 bits of data for the Status. You should use the first byte that is
read and throw away the 2nd one. But in your driver, you're only
reading 8 bits. Basically, you need to print out the CCS driver and
go through it, and copy the routines and substitute hardware SPI
where applicable, and read the same of bits that the CCS routines read.
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

Yea.... not really tho,
PostPosted: Fri Feb 24, 2006 1:16 am     Reply with quote

The problem is that you're not following the MCP2515 data sheet.
Also, you wanted to improve on the CCS MCP2510 driver by changing
it from bit-banging to hardware SPI. The problem is that you truncated
parts of the driver. CCS has different routines for reading the status
and for reading the buffer. You've combined them all into one routine.


I just took DougH's posted code and added in a write function. My own code is VERY well suited for my project. As far as I am concerned the CCS driver is horribly inefficient and not just because its software spi.


According to the data sheet and the CCS driver, you have to read
16 bits of data for the Status. You should use the first byte that is
read and throw away the 2nd one. But in your driver, you're only
reading 8 bits.


Ummm.... Are you sure about that? Page 12-8 shows CS going low, the A0 command being sent, then the READ STATUS is sent as 8 bits. The next 8bits it shows are "Repeat Data Out"... I suppose I could keep the clock going on and on but everything after the first 8bits that I read is just going to be repeated data. I see NO requirement to send 16. I beleive they are just showing that you can get a repeat of the data by keeping the clock going. Even if it was required, what would it matter? I read in the first 8 then wether I go on to read the next 8 or not it is not going to change the data of the first byte I already read in. Maybe it uses wishs and dreams to do so

There is no functional difference between this:
Code:

   command=0xA0;

   output_low(EXT_CAN_CS);

   for (i=0;i<8;i++) {
      output_bit(EXT_CAN_SI, shift_left(&command,1,0));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }
   for (i=0;i<8;i++) {
      shift_left(&data,1,input(EXT_CAN_SO));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }
   for (i=0;i<8;i++) {
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }


and this:
Code:

output_low(EXT_CAN_CS);
spi_write(0xA0);
data = spi_read(0);
output_high(EXT_CAN_CS);



The CCS driver does not take advantage of A0. Instead when looking for an open TX buffer they read the status of all 3 all at once (a total of 9 bytes over SPI), insead of checking 1, then checking another, then if that fails check the last on (a best case of 3 worst of 9). But it would be MUCH better for them to just use the 0xA0 command. Which they do, but only for use in the receive data commands.... Makes me think someone did it in a hurry or was lazy.

...Acutally... mcp2510_status() is never even used!! They have the function but it is never called. Not once in any of the CAN files. Also, the structure for rx_stat is all wrong for A0 and B0... I'm starting to think even CCS couldn't get it to work. So they made up there own struct for rx_stat and modify it only in the putd()


Basically, you need to print out the CCS driver and
go through it, and copy the routines and substitute hardware SPI
where applicable, and read the same of bits that the CCS routines read.


Did that. I see that they send in an A0 command, grab the first 8 of data, and then for some reason do another 8 clock cycles, which unless it can magicaly change the contents of a register in the pic, is pointless. I think its a pretty lame mistake in the CCS driver acutally. Looks like somone skimmed the datasheet.


I've gone over a lot of different things, my own code and two other examples I've found online all have 0xA0 reporting incorrect data. I even tried reading in 16bits on the command, same result.

Anyone have any ideas ?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 24, 2006 1:42 am     Reply with quote

One quick and easy test is to drop in the CCS bit-bang code
and see if everything starts working.
iso9001



Joined: 02 Dec 2003
Posts: 262

View user's profile Send private message

PostPosted: Fri Feb 24, 2006 10:51 am     Reply with quote

Doesn't matter.

It should not be possible to EVER get:

Code:

INTF = 0x05
READ STATUS = 0x08
RXSTATUS = 0x08


Ever, Ever, Ever.

I'm not understnding what using CCS's driver will do, it doesn't even use A0. I could code up a mock example and then use A0 myself, but seriously what would the point be. It is working 100% reliably wrong right now, not erratically wrong.

IF I use the ccs driver and it does or does not work I am no closer to understanding what is going on with this.

I have FULLY read over the datasheet many times now. I am doing exactly what I should be doing.

Anyone have experience with this ?
khannic
Guest







PostPosted: Mon Dec 08, 2008 3:53 pm     Reply with quote

I have a same situation, What I've got is the last value that I've read.


I've try this (I'm in loopback mode)
Code:
   
   can_read(0x3D);  //got 0x07
   can_read(0xB0);  //got 0x07
   can_read(0x3C);  //got 0x08
   can_read(0xB0);  //got 0x08


any suggestions ? thanks in advance.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 08, 2008 4:01 pm     Reply with quote

There is no can_read() function in any of the CCS driver files.
khannic
Guest







PostPosted: Tue Dec 09, 2008 3:29 am     Reply with quote

PCM programmer wrote:
There is no can_read() function in any of the CCS driver files.


ah, yes it didn't. actually I've implemented myself cause I prefer hardware SPI and it works fine. Here is my function

Code:

int can_read(int addr){                                         
   int ret;

   output_low(CAN_CS);                                                     
   spi_write(0x03); //read cmd
   spi_write(addr); 
   ret = spi_read(0);
   output_high(CAN_CS);
   
   return ret;
}
khannic



Joined: 09 Dec 2008
Posts: 4

View user's profile Send private message

PostPosted: Tue Dec 09, 2008 10:39 am     Reply with quote

It's ok now, it's my mistake.
The first byte to command to send should be 0xb0, but when I'm using my can_read function that will write 0x03 0xb0 !!

Thanks for your attention.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group