|
|
View previous topic :: View next topic |
Author |
Message |
iso9001
Joined: 02 Dec 2003 Posts: 262
|
MCP2515 CAN RXStatus not working.... datasheet wrong ? |
Posted: Wed Feb 22, 2006 11:42 pm |
|
|
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
|
|
Posted: Thu Feb 23, 2006 12:43 am |
|
|
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.
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
|
|
Posted: Thu Feb 23, 2006 11:59 am |
|
|
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
|
|
Posted: Thu Feb 23, 2006 2:21 pm |
|
|
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
|
|
Posted: Thu Feb 23, 2006 3:22 pm |
|
|
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
|
|
Posted: Thu Feb 23, 2006 4:38 pm |
|
|
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
|
|
Posted: Thu Feb 23, 2006 7:09 pm |
|
|
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
|
|
Posted: Thu Feb 23, 2006 11:20 pm |
|
|
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
|
Yea.... not really tho, |
Posted: Fri Feb 24, 2006 1:16 am |
|
|
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
|
|
Posted: Fri Feb 24, 2006 1:42 am |
|
|
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
|
|
Posted: Fri Feb 24, 2006 10:51 am |
|
|
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
|
|
Posted: Mon Dec 08, 2008 3:53 pm |
|
|
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
|
|
Posted: Mon Dec 08, 2008 4:01 pm |
|
|
There is no can_read() function in any of the CCS driver files. |
|
|
khannic Guest
|
|
Posted: Tue Dec 09, 2008 3:29 am |
|
|
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
|
|
Posted: Tue Dec 09, 2008 10:39 am |
|
|
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. |
|
|
|
|
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
|