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 CCS Technical Support

I need a ton of help with CANBUS on a pic18f4480

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



Joined: 04 Jun 2009
Posts: 107

View user's profile Send private message

I need a ton of help with CANBUS on a pic18f4480
PostPosted: Tue Sep 01, 2009 3:52 pm     Reply with quote

Hi folks. I'm completely lost. I have some firmware that I inherited and I've been making some tweaks to it. Up until now I've left alone anything to do with CAN because it seemed to work and it all is a bit beyond my grey matter capacity.

I need to dive into it now because we expanded how many addresses are being used and with the way they coded this thing there are only 6 CAN input filters and now I need a few more.

From the reading I've done, it thankfully doesn't look like a hardware limitation. The specs for the 18F4480 suggest there are 16 available filters, but you have to be in Mode 1 or 2 rather than legacy (0), which is the way our firmware was setup.

As far as I can tell, 18F4580 is the same as our PIC just with more memory, and I see under drivers that there is are can-18F4580.c an .h files. Our firmware uses what appears to be modified versions of the more generic can-18xxx8 series (which only supports Mode 0 apparently).

So I've been trying to adopt the new files but I'm not having a lot of luck. Actually I just don't really know where to start. First thing, I can't really find any explanation for how the BAUD is setup. In our existing firmware, I see this:

Code:
void SetBAUD( int BRP )
{
   int BRPtemp;
   BRPtemp = read_eeprom(EEPROM_BRP_ADDR);

   if (BRPtemp != BRP)
      write_eeprom(EEPROM_BRP_ADDR,BRP);
   write_eeprom(EEPROM_BRP_RAW,0x55); // use BRP
   CANSetOperationMode(CAN_OP_MODE_CONFIG);
          // Now set the baud rate.
   CANSetBaudRate( 4, // SJW
            BRP, // BRP
            8, // PHSEG1
            8, // PHSEG2
            3, // PROPSEG
            CAN_CONFIG_PHSEG2_PRG_BIT & CAN_CONFIG_VALID_STD_MSG & CAN_CONFIG_STD_MSG & CAN_CONFIG_DBL_BUFFER_ON);
   CANSetOperationMode(CAN_OP_MODE_NORMAL);
}

where BRP is 2, and that (according to comments) is evidentally what makes it a 500K baud rate. The CANSetBaudRate function in the #included file is as follows:
Code:
void CANSetBaudRate(BYTE SJW,
                     BYTE BRP,
                     BYTE PHSEG1,
                     BYTE PHSEG2,
                     BYTE PROPSEG,
                     CAN_CONFIG_FLAGS flags)
 {

and doesn't exist in the can-18F4580.c file, which instead has:
Code:
void can_set_baud(void) {
   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;
}


Ok, fine... so then I realize what I need to do is set CAN_BRG_PRESCALAR, CAN_BRG_SYNCH_JUMP_WIDTH, etc with the appropriate values to obtain a BAUD rate of 500k... but that's where I'm lost.

Any help is appreciated. Thanks.
s_mack



Joined: 04 Jun 2009
Posts: 107

View user's profile Send private message

PostPosted: Tue Sep 01, 2009 3:57 pm     Reply with quote

Oh, and what actually confused me and prompted the post was this in the can-18F4580.h file:

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


That's what made me throw up my hands. Why's it have a value of 0 when the comments say the default is 1 x Tq? Nothing states what Tq is that i can find, but the only way 1 x Tq is zero is if Tq is zero.

Anyway, also wanted to mention that we're using a 40M clock speed.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 01, 2009 4:13 pm     Reply with quote

Quote:

First thing, I can't really find any explanation for how the BAUD is setup.

Read this post to learn how to use the MBtime calculator tool:
http://www.ccsinfo.com/forum/viewtopic.php?t=22138&start=7


Quote:
The CANSetBaudRate function in the #included file is as follows: void CANSetBaudRate(BYTE SJW,
BYTE BRP,
BYTE PHSEG1,
BYTE PHSEG2,
BYTE PROPSEG,
CAN_CONFIG_FLAGS flags)
{

and doesn't exist in the can-18F4580.c file.

Google for CANSetBaudRate. It's from the Microchip PIC18C CAN Routines in ā€˜Cā€™ appnote. Read the docs that Google finds.


Quote:
Oh, and what actually confused me and prompted the post was this in the can-18F4580.h file:
#define CAN_BRG_SYNCH_JUMP_WIDTH 0 //synchronized jump width (def: 1 x Tq)

Download the PIC data sheet and read this section:
Quote:

REGISTER 23-52: BRGCON1: BAUD RATE CONTROL REGISTER 1

http://ww1.microchip.com/downloads/en/DeviceDoc/39637c.pdf
The basic idea is that values that are programmed into registers in
embedded devices do not always correspond directly to their meaning.
They are often "off by 1" because the hardware or firmware
implementation works better that way.
s_mack



Joined: 04 Jun 2009
Posts: 107

View user's profile Send private message

PostPosted: Tue Sep 01, 2009 4:26 pm     Reply with quote

An impressively helpful post, thank you. That gives me a ton to read, but that tool alone filled in a lot of gaps.

Cheers
s_mack



Joined: 04 Jun 2009
Posts: 107

View user's profile Send private message

PostPosted: Tue Sep 01, 2009 7:19 pm     Reply with quote

Thanks again. So I figure this should set up the chip and "see" the bus - as a basic test.

Code:
#include "ecan_test.h"
#include "can-18F4580.c"

//setup eCAN for 500kbaud
#define CAN_BRG_PRESCALAR 1
#define CAN_BRG_SYNCH_JUMP_WIDTH 0
#define CAN_BRG_PROPAGATION_TIME 2
#define CAN_BRG_PHASE_SEGMENT_1 7
#define CAN_BRG_SAM 0
#define CAN_BRG_SEG_2_PHASE_TS 1
#define CAN_BRG_PHASE_SEGMENT_2 7
#define CAN_BRG_WAKE_FILTER 0


void main()
{
   can_init();
   can_set_functional_mode( CAN_FUN_OP_ENHANCED );   //turn on eCAN enhanced mode to give us more filters
   while (1)
   {
      if ( can_kbhit() )
      {
         output_high( GRN_LED );
      }
      else
      {
         output_low( GRN_LED );
      }
   }
}


So I'm expecting that to set up for a 500 kbaud network and the thousands of messages that I know are on the bus should be streaming into this puppy and lighting up the GRN_LED, right? But its not. What am I missing now? I haven't even gotten to the hard stuff yet!!

ecan_test.h I just copied over from the (successful) version that uses Mode 0. Most of it has nothing to do with the above code but I'll post here for completeness sake:

Code:
#include <18F4480.h>

#DEVICE HIGH_INTS=TRUE, ADC=8, WRITE_EEPROM=ASYNC
#use delay(clock=40000000)
#fuses HS,NOWDT,WDT16,BROWNOUT,BORV28
//PROTECT,CPB,CPD,NOEBTR
#ZERO_RAM

//////// Fuses: LP,XT,HS,RC,EC,EC_IO,H4,RC_IO,PROTECT,NOPROTECT,OSCSEN
//////// Fuses: NOOSCSEN,NOBROWNOUT,BROWNOUT,WDT1,WDT2,WDT4,WDT8,WDT16,WDT32
//////// Fuses: WDT64,WDT128,WDT,NOWDT,BORV20,BORV27,BORV42,BORV45,PUT,NOPUT
//////// Fuses: CPD,NOCPD,NOSTVREN,STVREN,NODEBUG,DEBUG,NOLVP,LVP,WRT,NOWRT
//////// Fuses: NOWRTD,WRTD,WRTB,NOWRTB,CPB,NOCPB,WRTC,NOWRTC,EBTR,NOEBTR
//////// Fuses: EBTRB,NOEBTRB
////////


// ASCII BYTE STUFFING DEFINES
#define USB_DLE 0x10
#define USB_STX 0x02
#define USB_ETX 0x03


// ===== PORTA ================== TRISA   1111 1111  = FF
#define PEDAL_INPUT2   PIN_A0
#define PEDAL_INPUT1   PIN_A1
#define PEDAL_OUTPUT2  PIN_A2
#define PEDAL_OUTPUT1  PIN_A3
#define SPARE_A4       PIN_A4
#define SPARE_A5       PIN_A5
#define SPARE_A6       PIN_A6

// ===== PORTB ==================  TRISB 1111 1010 = FA
#define USER_LED     PIN_B0
#define SPARE_RB1    PIN_B1
#define CAN_TX       PIN_B2
#define CAN_RX       PIN_B3
#define USER_BUTTON  PIN_B4
#define SPARE_B5     PIN_B5
#define PGC          PIN_B6
#define PGD          PIN_B7

// ===== PORTC ================== TRISC 1011 1011 = BB
#define SPARE_C0     PIN_C0 // used to be SI_WU
#define SPARE_C1     PIN_C1
#define PWM1         PIN_C2
#define SPARE_C3      PIN_C3
#define SPARE_C4    PIN_C4
#define SPARE_C5     PIN_C5
#define   SERIAL_TX    PIN_C6
#define SERIAL_RX    PIN_C7

// ===== PORTD ================== TRISD 1110 1111 = EF
#define OPTION1      PIN_D0
#define OPTION2      PIN_D1
#define OPTION3      PIN_D2
#define OPTION4      PIN_D3
#define PWM2         PIN_D4
#define OPTION5      PIN_D5
#define OPTION6      PIN_D6
#define SPARE_D7     PIN_D7

// ===== PORTE ================== TRISE 1111 1100 = FC
#define GRN_LED      PIN_E1
#define RED_LED      PIN_E0
#define SPARE_E2     PIN_E2

#define TX_BUSY      output_low(RED_LED)
#define RX_BUSY      output_low(GRN_LED)
#define TX_NOT_BUSY  output_high(RED_LED)
#define RX_NOT_BUSY  output_high(GRN_LED)





#use fast_io(D)
// we use port D now for 18F6680
#byte  data_port = 0xf83

//#use I2C(master, sda=I2C_DATA, scl=I2C_CLK) // configure device as I2C master


Thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 01, 2009 10:39 pm     Reply with quote

You should be testing the board in Loopback mode first.
Do a search on the forum for:
Quote:
can bus Loopback

Search for "all terms".


Quote:

#DEVICE HIGH_INTS=TRUE, ADC=8, WRITE_EEPROM=ASYNC
#use delay(clock=40000000)
#fuses HS,NOWDT,WDT16,BROWNOUT,BORV28
//PROTECT,CPB,CPD,NOEBTR
#ZERO_RAM

#use fast_io(D)
// we use port D now for 18F6680
#byte data_port = 0xf83

Delete all the items shown in bold above for the loopback test.


Quote:

#use delay(clock=40000000)
#fuses HS,NOWDT,WDT16,BROWNOUT,BORV28

This BORV fuse implies that you may be running the PIC at 3.3 volts.
To run at 40 MHz, the PIC must have a Vdd of at least 4.2 volts.
s_mack



Joined: 04 Jun 2009
Posts: 107

View user's profile Send private message

PostPosted: Tue Sep 01, 2009 10:51 pm     Reply with quote

it is operating at 5V. I have no idea what the BORV28 fuse is for or why its there... it was in the existing firmware which is working fine, so I'm a bit hesitant to change it without understanding what it does. I'm not sure if I'm the only one, but frankly I've found the fuses to be horribly documented and confusing.

I do understand the loopback concept, but I'm not really sure how it'll help me to confirm that my board can talk to itself. I need to know that it can communicate with the external device. And I know it can... as it works just fine with the existing firmware. I've not changed the board at all, I'm just looking to get more CAN filters in play. I'm not saying its a bad idea to work in loopback, but I fail to see what I could implement that would help. Also it means writing (somewhat) more complex code because then I'd have to send as well as listen rather than just listen which of course introduces more variables to debug. I'll search though - maybe you're leading me to something.

Thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 01, 2009 11:36 pm     Reply with quote

Then make your program work in normal CAN mode first, instead of
enhanced mode.

My whole point is, back off all program options to a minimal state.
Make that work. Then start adding enhancements.
s_mack



Joined: 04 Jun 2009
Posts: 107

View user's profile Send private message

PostPosted: Tue Sep 01, 2009 11:56 pm     Reply with quote

Yeah, ok... in the morning I'll run that code in normal mode.

I was hoping with it as simple as it already is that there might be some glaring error or omission that your experience my point out.

Because other than the enhanced tag... I'm not sure how to make it much more minimal.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 02, 2009 1:06 am     Reply with quote

It's my understanding that your previous code was built from the
Microchip Pic18 source code. Your new proposed code is built
from the CCS drivers that are shipped with the compiler.
I assume that your board has never been tested with the CCS
drivers in any form. Therefore I propose that you start from
the ground up, with a loopback test. If you want to do it
some other way, then go ahead.
s_mack



Joined: 04 Jun 2009
Posts: 107

View user's profile Send private message

PostPosted: Wed Sep 02, 2009 1:25 am     Reply with quote

good point.

I've been working on it for the last couple hours. So far no luck.

In loopback, am I at all correct in saying that the baud rate doesn't make a lick of a difference?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 02, 2009 1:41 am     Reply with quote

I have only ever done loopback mode at 125 kbps, I think.
I've never read any documentation about it.
s_mack



Joined: 04 Jun 2009
Posts: 107

View user's profile Send private message

PostPosted: Wed Sep 02, 2009 1:47 am     Reply with quote

Shouldn't something as simple as this work?
Code:

#include <18F4480.h>
#use delay(clock=40000000)
#fuses HS,NOWDT,BROWNOUT
#include "can-18F4580.c"

unsigned int1 rtcc_counter;

#int_rtcc
void isr( void )
{
   set_rtcc( 0x9E58 );
   rtcc_counter=1;
}

void main()
{
   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;
   }

   can_init();
   setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_8 );
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);
   can_set_mode(CAN_OP_LOOPBACK);
   
   while (1)
   {
      if ( can_kbhit() )
      {
         output_toggle(PIN_E1);  //green led
      }
      if ( can_tbe() && (rtcc_counter!=0))
      {
         can_putd(tx_id, out_data, tx_len,tx_pri,tx_ext,tx_rtr);
         rtcc_counter = 0;
      }
   }
}


I can confirm with the above code that the timer is working correctly (by temporarily putting the LED toggle into the last IF) but it doesn't seem as though the can message is being sent.
s_mack



Joined: 04 Jun 2009
Posts: 107

View user's profile Send private message

PostPosted: Wed Sep 02, 2009 2:08 am     Reply with quote

All this headache, and I'm starting to ask myself, "for what".

The whole reason I'm doing this (changing over the way the firmware handles its CAN operations) was to take advantage of the extra filters available in eCAN enhanced mode. Right now our firmware doesn't actually use the filters - its just accepting everything and ignoring unwanted messages via program logic. Recent tests have shown that some data is getting lost, and I thought that was perhaps because the buffer was getting flushed before the "correct" data had a chance to get parsed. So to test that theory I was going to use the filters. However, we have more IDs then we have filters in Mode 0.

Maybe I'm barking up the wrong tree. Maybe using hardware filters won't make any difference or I'm simply wrong on why the data is missing.

I thought switching this code over would be relatively simple! Very Happy

But I feel I'm moving backwards instead of forwards.

I can't understand why the above code won't work and I can't see how I can make it any more basic. I can't imagine how it could be a hardware issue unless the CCS compiler drivers are somehow tranceiver specific (or?).

1:00am. I'll look at it again in the AM. Thanks.
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