|
|
View previous topic :: View next topic |
Author |
Message |
s_mack
Joined: 04 Jun 2009 Posts: 107
|
I need a ton of help with CANBUS on a pic18f4480 |
Posted: Tue Sep 01, 2009 3:52 pm |
|
|
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
|
|
Posted: Tue Sep 01, 2009 3:57 pm |
|
|
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
|
|
Posted: Tue Sep 01, 2009 4:13 pm |
|
|
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
|
|
Posted: Tue Sep 01, 2009 4:26 pm |
|
|
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
|
|
Posted: Tue Sep 01, 2009 7:19 pm |
|
|
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
|
|
Posted: Tue Sep 01, 2009 10:39 pm |
|
|
You should be testing the board in Loopback mode first.
Do a search on the forum for:
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
|
|
Posted: Tue Sep 01, 2009 10:51 pm |
|
|
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
|
|
Posted: Tue Sep 01, 2009 11:36 pm |
|
|
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
|
|
Posted: Tue Sep 01, 2009 11:56 pm |
|
|
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
|
|
Posted: Wed Sep 02, 2009 1:06 am |
|
|
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
|
|
Posted: Wed Sep 02, 2009 1:25 am |
|
|
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
|
|
Posted: Wed Sep 02, 2009 1:41 am |
|
|
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
|
|
Posted: Wed Sep 02, 2009 1:47 am |
|
|
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
|
|
Posted: Wed Sep 02, 2009 2:08 am |
|
|
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!
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. |
|
|
|
|
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
|