|
|
View previous topic :: View next topic |
Author |
Message |
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
Can-bus, 18F2580+MCP2551. Loopback ok, real can not working. |
Posted: Tue Sep 15, 2009 7:41 pm |
|
|
What can possibly be wrong?
I have a very simple connection between two 18F2580s.
Schema(lcd is not included): http://tinyurl.com/mikavikana
I tested the connection with code from another thread in this forum (http://www.ccsinfo.com/forum/viewtopic.php?t=29627&highlight=ifdef+board1+board),
If I set board1 to loopback mode, everything works fine.
When I try to use the actual connection, it is not working.
Does anyone see right away where the problem is? Or if someone has pointers what to check, please tell me.
My endless supply of components had run out of 120ohm resistors so I did termination with 121ohms (several resistors in series). Also the Rs resistor value for MCP2551 is 11k.
Any ideas?
edit: I just got my old scope working and there is data going in can-wires.
Looks like same sequence repeats itself.
Here is the code I mentioned above:
Code: |
#include <18F2580.H>
#fuses HS, NOPROTECT, PUT, BROWNOUT, NOWDT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include <can-18xxx8.c>
#define BOARD1_ID 24
#define BOARD2_ID 25
// Uncomment this line to compile code for Board #1.
// Comment it out to compile for Board #2.
//#define BOARD1 1
//======================================
void main()
{
struct rx_stat rxstat;
int32 rx_id;
int32 tx_id;
int8 rx_len;
int8 buffer[8];
can_init();
//can_set_mode(CAN_OP_LOOPBACK);
#ifdef BOARD1 // For Board #1
printf("?fOk.");
while(1)
{
output_toggle(PIN_C3);
delay_ms(1000);
buffer[0] = "x"; // Wait for a character
// Transmit it to board #2.
can_putd(BOARD2_ID, buffer, 1, 1, 1, 0);
buffer[0] = 0; // Clear the buffer byte
// Wait for the char to be echoed back.
while(!can_kbhit());
if(can_getd(rx_id, buffer, rx_len, rxstat))
{
if(rx_id == BOARD1_ID) // Is it for this board ?
{
printf(buffer[0]); // If so, display the char
}
}
}
#else // For Board #2
output_high(PIN_C3);
while(1)
{
if(can_kbhit()) // Message available ?
{
output_toggle(PIN_C3);
// If so, get the message.
if(can_getd(rx_id, buffer, rx_len, rxstat))
{
if(rx_id == BOARD2_ID) // Is it for this board ?
{
// If so, echo back the character.
can_putd(BOARD1_ID, buffer, 1, 1, 1, 0);
}
}
}
}
#endif
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 15, 2009 9:08 pm |
|
|
Quote: | #include <18F2580.H>
#fuses HS, NOPROTECT, PUT, BROWNOUT, NOWDT, NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include <can-18xxx8.c> |
The first thing to do would be to re-compile each board's firmware
with the can-18F4580.c driver, instead of the 18xxx8. driver.
The 18F2580 is part of the 18F4580 family. Here's the file location:
Quote: | c:\program files\picc\drivers\can-18f4580.c |
Note: That driver file contains a #use rs232() statement. Since you
have one in your application program, just comment that line out
in the driver file. |
|
|
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
|
Posted: Wed Sep 16, 2009 7:41 am |
|
|
[quote="PCM programmer"] Quote: | #include <18F2580.H>
The first thing to do would be to re-compile each board's firmware
with the can-18F4580.c driver, instead of the 18xxx8. driver.
|
I did that, no difference.
I replaced 2551's with new ones, just in case if they had some problems. No difference.
I also measured Vdd and Vss Nth time and everything seems to be ok.
Pics run ok, I can write to LCD and blink LEDs.
This must be something very simple that I just don't see now.
Last night, with oscilloscope, I found out that Board 1 sends data to CAN-line even if there is nobody in the other end of line.
According to test code, it should wait until it gets reply from board 2, but it transmits same sequence over and over again. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 16, 2009 12:37 pm |
|
|
Does your schematic represent real hardware ? Because, there is no
MCLR circuit. There are no 100 nF ceramic caps on the Vdd pins on any
chip. Also, I would jumper the Rs pins on the MCP2551 chips to ground
for the inital tests.
Are you certain that you compiled two versions of the test program,
one for Board #1 and one for Board #2 ? There's a #define statement
that must be in there for the Bd #1 firmware, and then you must
comment it out for Bd #2. Carefully verify that you have done this.
Do a verify on each PIC with your ICD, to confirm that they contain
the correct program.
Also, your method of printing a variable does not work. The test
program shown below, proves this. It displays nothing.
Code: | #include <16F877.H>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//======================================
void main(void)
{
int8 buffer[8];
buffer[0] = "x";
printf(buffer[0]);
while(1);
} |
Your method of loading the buffer with a single ASCII character is not
correct.
Here's the ASM code where you load the buffer. It's not putting a string
in the buffer. It's just writing a single ASCII byte. It's pure luck that
the buffer RAM happens to come up initialized as 0x00, due to how the
PIC silicon operates. Due to this behavior, the buffer probably does
contain a 0x00 after the 'x' byte, thus creating a string.
Code: |
........ buffer[0] = "x";
MOVLW 78
MOVWF 21
|
You can initialize a string at runtime with the strcpy() function.
Or, you can init it at compile time, by doing what you did above, except
that 'buffer' must be set equal to "x" in the declaration statement.
Example, showing how it correctly works now:
Code: |
...... int8 buffer[8] = "x";
MOVLW 78 // 'x'
MOVWF 21
CLRF 22 // 0x00 string terminator
|
Quote: | printf(buffer[0]); |
This is not the way that a single character is printed. You need to use
a format string, with "%c" to do that. Also, it's not the way that a
string is printed. You can printf a string by just giving it the buffer name:
However, you are just testing the transmission and reception of a single
char, so you shouldn't use a string (as shown above). You should use
only the single char methods. |
|
|
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
|
Posted: Wed Sep 16, 2009 1:10 pm |
|
|
PCM programmer wrote: | Does your schematic represent real hardware ? Because, there is no
MCLR circuit. There are no 100 nF ceramic caps on the Vdd pins on any
chip. Also, I would jumper the Rs pins on the MCP2551 chips to ground
for the inital tests.
Are you certain that you compiled two versions of the test program,
one for Board #1 and one for Board #2 ?
...
Also, your method of printing a variable does not work. The test
program shown below, proves this. It displays nothing.
...
However, you are just testing the transmission and reception of a single
char, so you shouldn't use a string (as shown above). You should use
only the single char methods. |
Schema seems to be missing pull-up resistors of MCLR-pins and 100nF caps.
There are pull-ups and caps in hw.
.
Schema does not have LCD connection either. It is connected to C6.
Yes, I am sure I compiled two different versions. And also verified they were programmed correctly.
Variable printing... what was I thinking... That is corrected now.
With loopback testing it printed some garbage to LCD, but that time I used apostrophes instead of quotation marks.
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 16, 2009 1:31 pm |
|
|
Is it now working ?
Here is how to initialize and display the first character in the buffer:
Code: |
#include <16F877.H>
#fuses XT,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//======================================
void main(void)
{
int8 buffer[8];
buffer[0] = 'x';
printf("%c", buffer[0]);
while(1);
} |
The problem with this method is that if you get something other than
the expected byte, there's no guarantee that it will be a printable
character. It would be better to use "%x" to show a hex value in
the printf statement. |
|
|
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
|
Posted: Wed Sep 16, 2009 7:36 pm |
|
|
PCM programmer wrote: | Is it now working ?
|
Unfortunately no.
Problem is no in printing characters to LCD.
Either Board 1 does not even send any CAN-messages or board 2 does not receive/reply.
Board 1 gets stuck to
Code: | while(!can_kbhit()); |
after it presumably sends message and board 2 does not go inside the
Code: | if(can_kbhit()) // Message available ? |
indicating it does not receive any messages.
Last night I checked CAN-line with oscilloscope and there is something,
some bit sequence that repeats even if I disconnect board 2.
This makes me think that problem is in board 1 sending. If it gets stuck to waiting can_kbhit, the bus should be silent if board 2 does not send anything. Right?
Tomorrow I will hook up the logic analyzer and check what is going on in there. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Thu Sep 17, 2009 10:03 am |
|
|
halibatsuiba wrote: | Last night I checked CAN-line with oscilloscope and there is something,
some bit sequence that repeats even if I disconnect board 2.
This makes me think that problem is in board 1 sending. If it gets stuck to waiting can_kbhit, the bus should be silent if board 2 does not send anything. Right?
Tomorrow I will hook up the logic analyzer and check what is going on in there. |
The CAN protocol is very robust - it's not as simple as you think in that board 1 sends a message ONCE. The CAN protocol will automatically retry if the message wasn't received. Board 1 is expecting an ACK from board 2 when the message is sent. If the ACK is absent, board 1's CAN circuitry will automatically retransmit the message until it is ACKed. |
|
|
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
|
Posted: Thu Sep 17, 2009 10:21 am |
|
|
newguy wrote: |
The CAN protocol is very robust - it's not as simple as you think in that board 1 sends a message ONCE. The CAN protocol will automatically retry if the message wasn't received. Board 1 is expecting an ACK from board 2 when the message is sent. If the ACK is absent, board 1's CAN circuitry will automatically retransmit the message until it is ACKed. |
I have to admit I need to read more CAN specs. I am more familiar with IP-networking and i2c-bus.
Just checked with logic analyzer and yes, board 1 sends (and retransmits) same message several times. Board 2 does not care about the message, can_kbhit does not indicate received message at all.
Both boards work ok in loopback-mode.
Termination resistors are now required 120 ohms and Rs is connected to Vss.
I have replaced MCP2551s but it had no effect at all so I think they are ok. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Sep 17, 2009 11:42 am |
|
|
Post your current test program and post your compiler version. |
|
|
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
|
Posted: Thu Sep 17, 2009 11:55 am |
|
|
PCM programmer wrote: | Post your current test program and post your compiler version. |
Compiler version 4.013
Code: | #include <18F2580.H>
#include <can-18F4580.h>
#fuses HS, NOPROTECT, PUT, BROWNOUT, NOWDT, NOLVP
#use delay(clock=20000000)
#include <C:\Program Files\PICC\Drivers\can-18f4580.c>
#define BOARD1_ID 24
#define BOARD2_ID 25
// Uncomment this line to compile code for Board #1.
// Comment it out to compile for Board #2.
#define BOARD1 1
//======================================
void main()
{
struct rx_stat rxstat;
int32 rx_id;
int32 tx_id;
int8 rx_len;
int8 buffer[8];
can_init();
printf("?fOk.");
//can_set_mode(CAN_OP_LOOPBACK);
#ifdef BOARD1 // For Board #1
while(1)
{
output_toggle(PIN_C3);
delay_ms(1000);
buffer[0] = 'x';
// Transmit it to board #2.
can_putd(BOARD2_ID, buffer, 1, 1, 1, 0);
buffer[0] = 0; // Clear the buffer byte
// Wait for the char to be echoed back.
while(!can_kbhit());
if(can_getd(rx_id, buffer, rx_len, rxstat))
{
if(rx_id == BOARD1_ID) // Is it for this board ?
{
printf("%c",buffer[0]); // If so, display the char
}
}
}
#else // For Board #2
output_high(PIN_C3);
while(1)
{
buffer[0] = 'x';
if(can_kbhit()) // Message available ?
{
output_toggle(PIN_C3);
// If so, get the message.
if(can_getd(rx_id, buffer, rx_len, rxstat))
{
if(rx_id == BOARD2_ID) // Is it for this board ?
{
// If so, echo back the character.
can_putd(BOARD1_ID, buffer, 1, 1, 1, 0);
}
}
}
}
#endif
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Sep 17, 2009 11:56 am |
|
|
That's what I thought. That version is known to have bugs. |
|
|
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
|
Posted: Thu Sep 17, 2009 12:11 pm |
|
|
PCM programmer wrote: | That's what I thought. That version is known to have bugs. |
darn.
I borrowed pickit3 + laptop with mplab and ccs-compiler from a friend to evaluate it if it suits my needs.
Looks like it will do what I need, if I can get this CAN working.
I am currently checking CCS website, I suppose "PCH Command-line Compiler for PIC18 MCU parts" would be the solution for me?
I mean I could use it with mplab ide?
If yes, I will buy it right away. Hopefully there is "download" option instead of using snailmail...
edit: Yes! There is a "download"-option. Now if I just would have some coupons...
edit2: but... butbut... PCH-compiler is said to be 16bit supporting PIC18-family. But Pic 18 is an 8-bit MCU. Confusing.
edit3: PCH compiler on its way. Yeah! |
|
|
halibatsuiba
Joined: 12 Aug 2009 Posts: 30
|
|
Posted: Thu Sep 17, 2009 9:23 pm |
|
|
halibatsuiba wrote: |
edit3: PCH compiler on its way. Yeah! |
Allright. Now I have PCH version 4.099 but...
It did not make things magically work like charm.
Did I pay $200 for nothing?
If Pcm Programmer thinks code is ok and this compiler version should have working CAN implementation, the only place where the problem can be is the hardware. Right?
Observations so far:
- Both boards work as expected in loopback mode (using board 1 sw).
- Verified with logic analyzer that there is data between board 1 pic and mcp2551
- Verified with oscilloscope (in board 2 end of line) that board 1 sends data resending it several times.
- Verified with pickit3 ICD that board 2 does not see messages in bus at all
Looks like the problem lies around board 2 mcp2551-chip or between it and pic 2.
Any ideas what to do/check really appreciated.
Thank you. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Sep 17, 2009 9:38 pm |
|
|
I'll get a couple of 18F2580's and test it. It should work. I don't know
why it doesn't work for you. I won't have an answer until the middle
of next week. |
|
|
|
|
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
|