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

Can't make CAN bus work, even in loopback mode!

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Chris.h
Guest







Can't make CAN bus work, even in loopback mode!
PostPosted: Tue Aug 03, 2004 3:57 pm     Reply with quote

Hi,

I'm banging my head trying to use the CAN bus of a PIC 18F448 for a project I'm working on. But I can't even seem to make it work in loopback mode. I tried on more than one chip, so I'd have to be really unlucky to have the CAN bus part of more than one chip fried. On the other hand the test code I'm using to test the CAN bus in loopback is now so short, I don't know where to look for coding errors anymore.

Could someone have a look at my test code and tell me if I'm missing something or if they think it should work. When I press a key in the terminal (to trigger the test), I get the "tx ok", but then can_getd fails, complaining there's nothing in the CAN rx buffers.

If someone could point out what I'm doing wrong (or tell me that it should work and I really have a hardware problem), I'd be much obliged. Here is the code:

Code:
#include <18f448.h>
#device ICD=TRUE, ADC=10
#fuses HS, NOWDT, NOPROTECT, DEBUG, LVP
#use delay(clock=9830400)
#use rs232(baud=57600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8)

#define CAN_DO_DEBUG 1
#include <can-18xxx8.c>

void main(void) {
   int32 can_id;
   int can_data[8];
   int can_length, counter;
   struct rx_stat rxstat;
   
   can_init();
   can_set_mode(CAN_OP_LOOPBACK);
   counter = 0;
   puts("Starting");

   for (;;) {
      if (kbhit()) {
         getch();
         if (can_putd(42, &counter, sizeof(counter), 3, FALSE, FALSE))
            puts("tx ok");
         if (can_getd(can_id, can_data, can_length, rxstat))
            puts("rx ok");
         counter++;
      }
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 03, 2004 5:38 pm     Reply with quote

I made some changes and got it working on my test board.
The changes are shown in bold below. Some of them
were done just to make it work on my test board.
So you'll have to change them back for your board.

In your post, you have the LVP fuse set. But you're
using ICD. That doesn't use LVP. It can cause problems
to leave that fuse in LVP mode. So unless there's
something I don't know about, you should change it
to NOLVP.

I use a "wall wart" to power my test board. I find that
I need the Brownout fuse to make it be reliable if I flick
the AC power switch off and on quickly. (To reset the board).
I also use the PUT fuse to make the system more reliable.

The main things about your CAN code were that I didn't
like some of your parameters, so I changed them.
I think the CCS CAN driver is setup to use Extended ID's
by default, so that's why I set that flag to be true.

You should check can_kbhit() before you call can_getd(),
so I put that in there. I didn't put in a timeout loop for it
because this is just a test program.

I suggest that you make the minimum necessary changes
to the pre-processor statements to get the program working
with your test board. Then maybe change the CAN code
a little bit at a time for your own tests.

Also, I use the ICD2 in programmer mode (instead of debugger
mode), so that's why I disabled your "device=ICD" and DEBUG
statements.

#include <18F458.h>
//#device ICD=TRUE, ADC=10
#fuses XT, NOWDT, NOPROTECT, NOLVP, PUT, BROWNOUT // DEBUG
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8)

//#define CAN_DO_DEBUG 1
#include <can-18xxx8.c>

void main(void) {
int32 can_id;
int can_data[8];
int can_length, counter;
struct rx_stat rxstat;

can_init();
can_set_mode(CAN_OP_LOOPBACK);
counter = 0;
puts("Starting");

can_data[0] = 0x55;
while(1)
{
if(kbhit())
{
getch();

if(can_putd(42, can_data, 1, 3, TRUE, FALSE))
puts("tx ok");

while(!can_kbhit());
if(can_getd(can_id, &can_data[0], can_length, rxstat))
puts("rx ok");

counter++;
}

}
}
Chris.h
Guest







PostPosted: Wed Aug 04, 2004 9:26 pm     Reply with quote

Thanks for the quick reply.

For the LVP fuse, I dimly remember an older version of MPLAB complaining when I set it, so that's why I had changed it. The newer version of MPLAB I'm using now doesn't seem to mind anymore, so I switched it back to LVP.

At first I tried to get my code as close to yours. That got it working, so it looks like I won't be going completely crazy, at least not this time. Then I backtracked to find the minimal change that makes the code work. It turns out that the change is very simple: changing the fifth parameter of the can_putd call ("use extended ids") from FALSE to TRUE makes everything work.

I'll go with the flow and use extended ids for my project, I guess. But I'd still really like to understand why standard ids won't work. I looked at the CAN driver code, and in can_init() the registers RXB0CON.rxm and RXB1CON.rxm are set to 0 (which means "receive all valid messages") and they aren't referenced anywhere else in the code. So the thing should be able to receive messages with either standard or extended ids... I even added a check in the loop in my test code that checks if these two bits stay at 0 and complains loudly if they change... nothing. Is there some other register that needs to be set differently for standard vs. extended ids? If so, I missed it a couple of times already.

If someone can explain what I'm missing, it'd be the cherry on top of the sundae...

Thanks for the help!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 04, 2004 10:16 pm     Reply with quote

Quote:
The newer version of MPLAB I'm using now doesn't seem to mind
anymore, so I switched it back to LVP.

I'm not sure I understand you correctly. Are you leaving the fuse
set to LVP in your current program ? If you're using the ICD as the
only programmer for the PIC, then the fuse should be set to NOLVP.
If you leave it set to LVP, you risk random lockups of the PIC.
For example, with the fuse set to LVP, if you then set pin B5 (PGM pin)
as an input, and turn on Port B pull-ups, then you will get instant lockup,
as the PIC goes into Low Voltage Programming Mode.

Quote:
But I'd still really like to understand why standard ids won't work.

Look at the can_init() function in the CCS driver file, can-18xxx8.c.
They call can_set_id() three times to setup Receive Buffer 0, and
they call it five times to setup Receive Buffer 1.

The 3rd parameter in can_init() is set to 1, in all cases. This sets up
both RXB0 and RXB1 to use Extended ID's.

In the following post, someone had a similar problem or question:
http://www.ccsinfo.com/forum/viewtopic.php?t=17862
His solution was to setup RXB0 to use Standard ID's, by changing the
3rd parameter to be 0, in the first three calls to can_set_id() in the
can_init() function. The changes are shown in bold, below.
can_set_id(RX0MASK, CAN_MASK_ACCEPT_ALL, 0); //set mask 0
can_set_id(RX0FILTER0, 0, 0); //set filter 0 of mask 0
can_set_id(RX0FILTER1, 0, 0); //set filter 1 of mask 0

I haven't tested this myself, because in our applications we only use
extended ID's. You could test it and let us know the results.
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