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

ECAN on the pic18f2580
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Bryan



Joined: 23 Apr 2005
Posts: 73

View user's profile Send private message Send e-mail AIM Address

ECAN on the pic18f2580
PostPosted: Wed Nov 15, 2006 11:09 pm     Reply with quote

I am using a PIC18F2580 with the ECAN module. I am using a MCP2551 transceiver chip to convert the CAN messages to readable format. The transceiver chip receives the CAN messages and I have verified that I get a squarewave RS232 output on pin 4 (the MCP2551 Tx pin) with an oscilloscope. The problem is that when I use the code below, I never get a CAN kbhit. I modified the <can-18F4580.h> to set the baud rate to 500kbps instead of the 125kbps that is the default since this is an automobile application. I changed the baud rate constants as such:

Code:

#IFNDEF CAN_BRG_SYNCH_JUMP_WIDTH
  #define CAN_BRG_SYNCH_JUMP_WIDTH  0  //synchronized jump width (def: 1 x Tq)
#ENDIF

#IFNDEF CAN_BRG_PRESCALAR
  #define CAN_BRG_PRESCALAR  4  //baud rate generator prescalar (def: 4) ( Tq = (2 x (PRE + 1))/Fosc )
#ENDIF

#ifndef CAN_BRG_SEG_2_PHASE_TS
 #define CAN_BRG_SEG_2_PHASE_TS   TRUE //phase segment 2 time select bit (def: freely programmable)
#endif

#ifndef CAN_BRG_SAM
 #define CAN_BRG_SAM 0 //sample of the can bus line (def: bus line is sampled 1 times prior to sample point)
#endif

#ifndef CAN_BRG_PHASE_SEGMENT_1
 #define CAN_BRG_PHASE_SEGMENT_1  0 //phase segment 1 (def: 1 x Tq)
#endif

#ifndef CAN_BRG_PROPAGATION_TIME
 #define CAN_BRG_PROPAGATION_TIME 0 //propagation time select (def: 1 x Tq)
#endif

#ifndef CAN_BRG_WAKE_FILTER
 #define CAN_BRG_WAKE_FILTER FALSE   //selects can bus line filter for wake up bit
#endif

#ifndef CAN_BRG_PHASE_SEGMENT_2
 #define CAN_BRG_PHASE_SEGMENT_2 0 //phase segment 2 time select (def: 1 x Tq)
#endif

#ifndef CAN_USE_RX_DOUBLE_BUFFER
 #define CAN_USE_RX_DOUBLE_BUFFER TRUE   //if buffer 0 overflows, do NOT use buffer 1 to put buffer 0 data
#endif


I am using a 20 MHz crystal which should work fine with this setup (I worked through the calculations) and my code is posted below. Any ideas? I am thinking that the baud rate of my CAN Rx pin on the PIC may be set up incorrectly, but I can't figure out how to set it or where it is set in the CCS can driver.

Code:
Code:

#include <18F2580.h>
#fuses NOWDT,NOPROTECT,NOLVP,NOMCLR,HS
#use delay(clock=20000000)
#include <can-18F2580.c>


void main() {
   struct rx_stat rxstat;
   int32 rx_id;
   int in_data[8];
   int rx_len;

   int i;

   for (i=0;i<8;i++) {
      in_data[i]=0;
   }

   while (fgetc(out) != 36);

   fprintf(out,"\r\n\r\nCCS CAN EXAMPLE\r\n");

   can_init();

   while(TRUE)
   {

      if ( can_kbhit() )   //if data is waiting in buffer...
      {
         if(can_getd(rx_id, &in_data[0], rx_len, rxstat)) { //...then get data from buffer
            fprintf(out,"\r\nGOT: BUFF=%U ID=%LU LEN=%U OVF=%U ", rxstat.buffer, rx_id, rx_len, rxstat.err_ovfl);
            fprintf(out,"FILT=%U RTR=%U EXT=%U INV=%U", rxstat.filthit, rxstat.rtr, rxstat.ext, rxstat.inv);
            fprintf(out,"\r\n    DATA = ");
            for (i=0;i<rx_len;i++) {
               fprintf(out,"%X ",in_data[i]);
            }
            fprintf(out,"\r\n");
         }
         else {
            fprintf(out,"\r\nFAIL on GETD\r\n");
         }

      }
    }
}

jma_1



Joined: 08 Feb 2005
Posts: 147
Location: Wisconsin

View user's profile Send private message

PostPosted: Thu Nov 16, 2006 7:27 am     Reply with quote

Greetings,

I did not verify the bit timing you specified, but you must call the can_init() function before using the CAN module.

You did not include what you are receiving the data from. Perhaps the setup of the device transmitting is the issue.

Cheers,
JMA
sjbaxter



Joined: 26 Jan 2006
Posts: 141
Location: Cheshire, UK

View user's profile Send private message Visit poster's website

PostPosted: Thu Nov 16, 2006 7:59 am     Reply with quote

have you tried inserting a breakpoint at the main 'while' loop statement and making sure the code is getting past the can_init() . This can sometimes block as it tries to change the operating mode from Configuration to Normal if there is activity on the can receive pin. (Search the forum for notes on this one).

An easy way to test RX code (and get the hardware out of the equation) is to put the can module into LOOPBACK mode and send yourself a message. (Again, plenty of examples of this on the forum).

BTW: Rather than changing the canxxx.h file, just #define the new settings before including the CAN driver in your main code.

i.e
Code:

#include <18F2580.h>
#fuses NOWDT,NOPROTECT,NOLVP,NOMCLR,HS
#use delay(clock=20000000)

#define CAN_BRG_SYNCH_JUMP_WIDTH  0  //synchronized jump width (def: 1 x Tq)
#define CAN_BRG_PRESCALAR  4  //baud rate generator prescalar (def: 4) ( Tq = (2 x (PRE + 1))/Fosc )
#define CAN_BRG_SEG_2_PHASE_TS   TRUE //phase segment 2 time select bit (def: freely programmable)
#define CAN_BRG_SAM 0 //sample of the can bus line (def: bus line is sampled 1 times prior to sample point)
#define CAN_BRG_PHASE_SEGMENT_1  0 //phase segment 1 (def: 1 x Tq)
#define CAN_BRG_PROPAGATION_TIME 0 //propagation time select (def: 1 x Tq)
#define CAN_BRG_WAKE_FILTER FALSE   //selects can bus line filter for wake up bit
#define CAN_BRG_PHASE_SEGMENT_2 0 //phase segment 2 time select (def: 1 x Tq)
#define CAN_USE_RX_DOUBLE_BUFFER TRUE   //if buffer 0 overflows,

#include <can-18F2580.c>

...


The TX and RX bit timing are setup with the same code so these are the settings for both TX and RX. They have to be the same as the bus you are connecting to otherwise you will get a lot of bus errors being generated !

you might also want to add:

Code:

#define CAN_ENABLE_DRIVE_HIGH  1


to the end of these defines, as without this set (and depending on the transceiver) you can get unpredictable results as the transceiver may drive the CAN bus with garbage when you least expect it.

Not sure if this is applicable to the MCP2551 (from memory, it already has a pull up on the TX pin) but I use the PCA82C250/251 and it does cause problems without it.

For a 500Kbit/sec bus speed using a clock of 20MHz and a bit sample point of 70%, the settings should be:

Code:

#define CAN_BRG_SYNCH_JUMP_WIDTH  0
#define CAN_BRG_PRESCALAR  1
#define CAN_BRG_SAM 0
#define CAN_BRG_PHASE_SEGMENT_1  4
#define CAN_BRG_PHASE_SEGMENT_2  2


should give the registers of:

Code:

BRGCON1 = 0x01
BRGCON2 = 0xA0
BRGCON3 = 0x02


Again, put a breakpoint in the can_init and check these are being set.

On a side note, compiler versions of 3.237 and above cause the CAN structs used by the can driver to get allocated incorrectly and cause corruption of the settings, so you may want to let us know what version of the compiler you are using.
_________________
Regards,
Simon.
jma_1



Joined: 08 Feb 2005
Posts: 147
Location: Wisconsin

View user's profile Send private message

PostPosted: Thu Nov 16, 2006 9:26 am     Reply with quote

My bad. I completely overlooked that you already had can_init() in your code.

Cheers,
JMA
Bryan



Joined: 23 Apr 2005
Posts: 73

View user's profile Send private message Send e-mail AIM Address

PostPosted: Thu Nov 16, 2006 4:13 pm     Reply with quote

If I am not mistaken, here is the baud rate that will be generated using your constant definitions in the code you posted:

Code:

#define CAN_BRG_SYNCH_JUMP_WIDTH  0
#define CAN_BRG_PRESCALAR  1
#define CAN_BRG_SAM 0
#define CAN_BRG_PHASE_SEGMENT_1  4
#define CAN_BRG_PHASE_SEGMENT_2  2


You didn't define the #define CAN_BRG_PROPAGATION_TIME setting and I assume this would be 0 as well because I ran the calculation and if you set that to 0 you come out with a baud rate of 500kbps.

I am curius though, why there are several ways to create the same exact baud rate. Even though my way also came up with 500 kbps, could this be the problem? Or do those other delays such as phase segment 1 & 2, jump delay, etc affect other portions of the bus?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 16, 2006 4:27 pm     Reply with quote

Look at my long post in this thread. Download the Bit Timing program
from the www.intrepidcs.com at the link provided in the thread.
Use it to determine the register values, per the instructions in my post.
http://www.ccsinfo.com/forum/viewtopic.php?p=41196
sjbaxter



Joined: 26 Jan 2006
Posts: 141
Location: Cheshire, UK

View user's profile Send private message Visit poster's website

PostPosted: Thu Nov 16, 2006 4:49 pm     Reply with quote

Bryan,

Using your clock (20MHz) and requiring a 500Kbit bus speed, you can ony achieve the correct timings with two setting of the prescaler (0 or 1) which gives an overall bit length of 10Tq or 20Tq. You have a value of 4 !!! The Bit Timing Calculator that PCM refers to will confirm this.

How did you calculate the values ... I presume from you last post you haven't yet grasped the ins and outs of CAN bit timings. Again, the Bit Timing Calculator will graphically show you how the various phases, etc and how they relate to each other.

Do remember however that the values given by the calculator are in Time Quanta's (Tq) and the #defines are the values required for the various bits of the BRGCONx registers. This does mean that they are not always a 1 to 1 relationship. From memory, I think PCM's thread explains this.
_________________
Regards,
Simon.
Bryan



Joined: 23 Apr 2005
Posts: 73

View user's profile Send private message Send e-mail AIM Address

PostPosted: Thu Nov 16, 2006 6:18 pm     Reply with quote

I used the bit time calculator and got the same results as you, Simon but this didn't work when I changed the can_set_baud() function to:

Code:

void can_set_baud(void) {
   //500kbs @ 20MHz
   BRGCON1 = 0x01;
   BRGCON2 = 0xA0;
   BRGCON3 = 0x02;
   /*BRGCON1.brp=CAN_BRG_PRESCALAR;
   BRGCON1.sjw=CAN_BRG_SYNCH_JUMP_WIDTH;

   BRGCON2.prseg=CAN_BRG_PROPAGATION_TIME;
   BRGCON2.seg1ph=CAN_BRG_PHASE_SEGMENT_1;
   BRGCON2.sam=CAN_BRG_SAM;
   BRGCON2.seg2phts=CAN_BRG_SEG_2_PHASE_TS;

   BRGCON3.seg2ph=CAN_BRG_PHASE_SEGMENT_2;
   BRGCON3.wakfil=CAN_BRG_WAKE_FILTER;*/
}


By the way, I am using PCH v4.005 and you had said this might mess with the CAN registers. Any suggestions on what to do? (Changing this did not get any reception, I successfully get a send, but never get a can_kbhit as before).
Bryan



Joined: 23 Apr 2005
Posts: 73

View user's profile Send private message Send e-mail AIM Address

PostPosted: Thu Nov 16, 2006 6:33 pm     Reply with quote

Here is my test program:

Code:

#include <18F2580.h>
#fuses NOWDT,NOPROTECT,NOLVP,NOMCLR,HS
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=outstream)

#include <can-18F2580.c>

int16 ms;

#int_timer2
void isr_timer2(void) {
   ms++; //keep a running timer that increments every milli-second
}


void main() {
   struct rx_stat rxstat;
      int32 rx_id;
      int in_data[8];
      int rx_len;
   
   //send a request (tx_rtr=1) for 8 bytes of data (tx_len=8) from id 24 (tx_id=24)
      int out_data[8];
      int32 tx_id=24;
      int1 tx_rtr=1;
      int1 tx_ext=0;
      int tx_len=8;
      int tx_pri=3;
   
      int i;
   
      for (i=0;i<8;i++) {
         out_data[i]=0;
         in_data[i]=0;
       }
   
   while (fgetc(outstream) != 36);

   fprintf(outstream,"\r\n\r\nCCS CAN EXAMPLE\r\n");

   setup_timer_2(T2_DIV_BY_4,79,16);   //setup up timer2 to interrupt every 1ms if using 20Mhz clock
   
   can_init();
   
   enable_interrupts(INT_TIMER2);   //enable timer2 interrupt
    enable_interrupts(GLOBAL);       //enable all interrupts (else timer2 wont happen)
   
   //
   can_set_mode(CAN_OP_LOOPBACK);
   //

   fprintf(outstream,"\r\nRunning...");
   
   

   while(TRUE)
   {
      
      if ( can_kbhit() )   //if data is waiting in buffer...
      {
         if(can_getd(rx_id, &in_data[0], rx_len, rxstat)) { //...then get data from buffer
            fprintf(outstream,"\r\nGOT: BUFF=%U ID=%LU LEN=%U OVF=%U ", rxstat.buffer, rx_id, rx_len, rxstat.err_ovfl);
            fprintf(outstream,"FILT=%U RTR=%U EXT=%U INV=%U", rxstat.filthit, rxstat.rtr, rxstat.ext, rxstat.inv);
            fprintf(outstream,"\r\n   DATA = ");
            for (i=0;i<rx_len;i++) {
               fprintf(outstream,"%X ",in_data[i]);
            }
            fprintf(outstream,"\r\n");
          }
          else {
            fprintf(outstream,"\r\nFAIL on GETD\r\n");
          }
 
      }
      
   //every two seconds, send new data if transmit buffer is empty
        if ( can_tbe() && (ms > 2000))
        {
          ms=0;
          i=can_putd(tx_id, out_data, tx_len,tx_pri,tx_ext,tx_rtr); //put data on transmit buffer
          if (i != 0xFF) { //success, a transmit buffer was open
            fprintf(outstream,"\r\nPUT %U: ID=%LU LEN=%U ", i, tx_id, tx_len);
            fprintf(outstream,"PRI=%U EXT=%U RTR=%U\r\n   DATA = ", tx_pri, tx_ext, tx_rtr);
            for (i=0;i<tx_len;i++) {
               fprintf(outstream,"%X ",out_data[i]);
            }
            fprintf(outstream,"\r\n");
          }
          else { //fail, no transmit buffer was open
            fprintf(outstream,"\r\nFAIL on PUTD\r\n");
          }
          }
   }
}



I receive all of the messages and the 2 second put outputs, but a kbhit is never received so I never get any of the "Got" messages. Any ideas why I wouldn't receive anything? As I mentioned before I am using the beta PCH 4.005 compiler.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 16, 2006 6:35 pm     Reply with quote

You're actually testing several things at once. Here's a partial list:

1. The configuration of the CCS CAN bus driver, so it works with
the (partially unknown) configuration of the automotive CAN bus.

2. Vs. 4.005 of the compiler.

3. The CAN bus hardware. (driver chip, terminator resistor, etc.)

Ideally, you would have two demo boards and the first thing you
would do is to get them talking to each other, without errors.
Once you have that done, then try to connect one of the boards
to the automotive CAN bus.
Bryan



Joined: 23 Apr 2005
Posts: 73

View user's profile Send private message Send e-mail AIM Address

PostPosted: Thu Nov 16, 2006 7:09 pm     Reply with quote

Since I am using loopback mode, I should at least see it receiving the messages internally and getting a kbhit, right? It seems odd that even in loopback mode I never get a single kbhit...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 16, 2006 8:25 pm     Reply with quote

There are a few threads on loopback mode. This one might help you:
http://www.ccsinfo.com/forum/viewtopic.php?t=23825
Bryan



Joined: 23 Apr 2005
Posts: 73

View user's profile Send private message Send e-mail AIM Address

PostPosted: Thu Nov 16, 2006 8:38 pm     Reply with quote

Got loopback to work, thanks for the help - One of your previous posts helped. It turns out that extended id mode is not enabled by default in the CCS example CAN code so I had to turn that on and you had pointed this out in a post awhile back.

Now, I have hooked my device up to the transceiver chip which receives a CAN message from a test device that I have (which simulates the can bus) and my digital scope confirms that the signal tied from the transceiver to the CAN Rx pin on my PIC outputs a 500kbps signal. I measured the bit time on my scope and it is approximately 25us which is very close to 500kbps. Is it possible that since this is not exact, the Rx pin is not detecting the incoming signal? I still never receive a kbhit.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 16, 2006 9:34 pm     Reply with quote

According to the CAN bus v2.0 specification, a controller could be
designed to accept up to a 1.5% frequency tolerance. Normally,
the required tolerance is 0.5%.

All my CAN bus projects have been done between PICs, with crystals
that that have .005% tolerance. I haven't done any automotive
projects, so I can't really help too much on that.
Micke
Guest







PostPosted: Sat Jun 09, 2007 9:57 am     Reply with quote

Where can I Find files can-18F2580.c and can-18F2580.h ?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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