|
|
View previous topic :: View next topic |
Author |
Message |
dara hayes
Joined: 26 Nov 2003 Posts: 12 Location: Ireland
|
Sending more than 3 frames with CAN BUS |
Posted: Sat Jan 03, 2004 12:11 pm |
|
|
Hello all
am using a simple piece of code taken from the CCS Can Dev kit samples to send some bytes across can bus
the problems seem to occur when I want to send more than 24bytes
(more than 3 can frames) the frames dont allways get transmitted and
some seem to arrive in the wrong order at the other end
the code i am using is seen below
while(!can_putd(transmit_id, buffer, 8, 3, TRUE, FALSE)){} //send data
should I be filling all three buffers first and then setting the txreq bit for all and waiting till all 3 buffers are empty before filling them again
I understand priority needs to change when filling the buffers 3 at a time
I have experimented with rotating a value for priority from 3 to 0 but this doesnt seem to help either , unless I put a hefty delay_ms(50) after each transmission they dont seem to arrive in the right order even all get across the bus
could some one point me in the right direction to sending large strings in an orderly manner
thanks
dara hayes |
|
|
asturkinos
Joined: 16 Nov 2003 Posts: 5 Location: Asturias-Spain
|
More than 3 CAN frames |
Posted: Sat Jan 03, 2004 3:13 pm |
|
|
Hello Dara, I've got a little experience on Microchip CAN bus but I think your CAN bus is not working right... Maybe your physical layer isn't wired?
Have you tried your bus with EX_CAN.c file?
Are you receiving this 3 bytes? or you have reveived garbage into the reception node....
Is your reception node configured to recive all can frames? By reading your post I guess you haven't touch the files <can-18xxx8.c> or <can-mcp2510.c>... Have you?
Another cuestion: what's the PIC you are using? Are you working whit MCP2510 or 18xxx8?
A good way to test the CAN bus may be add the line
#define CAN_DO_DEBUG TRUE
before the include can-xxx line.. So you can debug your bus through RS232... This should help you a lot.
Now ¡f you see whit this debug that you are filling all the tree tx buffers you'll know something is not going good.
if you post your full code I'll try to help you....
Regards, and excuse my "spanish-talker" english :-) _________________ ----------------------------------------------------------------------------------kinOs----------------------------
---------------------------------------------------------- |
|
|
dara hayes
Joined: 26 Nov 2003 Posts: 12 Location: Ireland
|
more than 3 frames on can |
Posted: Sat Jan 03, 2004 4:35 pm |
|
|
ola !
and many thanks for your reply
my can bus is the physical bus on the dev kit pcb , and it works fine between the four nodes on this board, node A is my transmitter (18F458) and node b (16f876a + mcp chip) is my receiver, I am using the rs232 code for supplied in kit for listening to all frames and
outputing all received frames , the frames are being received but not all
or in the right order when ever i transmit more than three frames from my txmtr node if I transmit one or two frames , 8 or 16bytes then all is ok.
seems to be an issue with priority or some frames just not getting transmitted as the sender seems to send the frames in the other TXbuf
and not the one I have just loaded with fresh data
I have a simple loop decreasing a counter pointer to my large string
and doing a while(!can_putd ..........) {}
it works for 1 and a half frames or even two but not more than three frames.
If however I put a long delay in the code delay_ms(50) after each
transmission I can get more than 3 frames in the right order across the
bus without problem
regards dara |
|
|
dara hayes
Joined: 26 Nov 2003 Posts: 12 Location: Ireland
|
The Answer is |
Posted: Sat Jan 03, 2004 6:45 pm |
|
|
Hello all
I think I have found the answer to my problem
I scoped the bus and found that the correct number of frames were being sent the reason I couldnt see them was the speed of the receiver RS232 device on the 16F876 its only runing at 250k as its clock is sub divided from the mcp chip , i tried upping the baud rate but it cant see all the frames with the way its coded in a if ( can_kbhit() ) { loop
its not going to catch all the frames , so the delay ensured they were all spotted , I also put a can tx interrupt debug in all 3 tx buffer interrupts to increase a variable on the tx side and it always read the correct number
so from the scope and the interrupts I am sure I am txing the correct number of frames its just my rx monitor program cant pick them all up
when they come in rapid sucession
if anyone else knows another possible reason I would be glad to hear from them , thanks
dara hayes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 04, 2004 3:41 pm |
|
|
As I understand it, your problem is this:
You're trying to send a string of characters -- for example, an English
language sentence. The string might be 80 characters in length.
You're breaking it up into several CAN messages, with each message
holding 8 characters (or less).
My first thought would be that CAN was not intended for this.
It was invented as a control bus for automobile systems. Each
message is supposed to contain a discrete piece of information,
such as engine speed, water temperature, oil pressure, etc.
Or, it can contain a command which will turn on the rear window defroster, etc.
These CAN messages don't have to arrive at the destination
in a specific order. Each recipient device just looks for messages
that are of interest to the device. For example, a device might
look for current water temperature and current oil temperature.
It doesn't really care if one message comes in before the other.
But in your design, message order is important. Some ideas:
If you want to do it that way, you might have to include in each
CAN message, a String ID, which tells the recipient that the
current message is part of string "x". Also, each CAN message
would have a sub-string index, which tells the recipient where to
insert this little sub-string into the larger string (in an array).
You would also need to include a field which holds the overall
length of the string (either in terms of the number of CAN messages
or characters). Some or all of this information could possibly be
encoded into an Extended CAN message ID (ie., the 29 bit ID).
These are just some ideas. I don't know if it's required, because
my CAN project was very simple.
Another idea is that possibly, a different bus and protocol should be
used -- RS-485 with addressable nodes ?
Some other thoughts:
You said that sometimes the CAN messages are received in the
wrong order. If you look at the CCS driver file, can-18xxx8.c,
in the can_getd() routine, you can see that they first check Receive
buffer 0, and if it's not full, then they check Receive buffer 1.
But what if the CAN transmitter sent out 3 messages rapid-fire ?
You are polling for a CAN message in your recipient device.
You call can_getd(). It has a message in buffer 0. You get it.
But during that time, the other two messages have come in.
The 2nd message went into buffer 1, and the 3rd went into buffer 0
again (because you emptied it). BUT, on the your next call to
can_getd(), the routine first checks buffer 0. And that's the message
it will return. So you'll get message A, then message C, and then
on your final call to can_getd(), it will return message B, which came
to buffer 1. Instead of getting ABC like you want, you'll get ACB.
So what's the solution ? Possibly, disable the use of the 2nd receive
buffer. Or, use the protocol I described above. |
|
|
dara hayes
Joined: 26 Nov 2003 Posts: 12 Location: Ireland
|
can bus multi frames |
Posted: Sun Jan 04, 2004 8:17 pm |
|
|
Thanks for your input
Yes the can bus is not designed for this type of data delivery but I reckon
my problem is partly due to the way I am accessing the rx buffers i am not using interrupts directly but using the ccs example code and the libs supplied, Can is the way I have decided to approach the problem and I
feel it CAN be done ... just need more practice with it..
many thanks for your input and ideas
regards
dara hayes |
|
|
Gunshot Guest
|
|
Posted: Mon Jan 26, 2004 6:49 am |
|
|
the solution is to disable can send buffer 1 and 2 and only use buffer 0
it works for me i had the same problem
when i send 11112222 33334444 22225555
i somtimes get 11112222 22225555 33334444
best regards
Thomas |
|
|
dara hayes
Joined: 26 Nov 2003 Posts: 12 Location: Ireland
|
more than 3 frames with can bus |
Posted: Mon Jan 26, 2004 8:50 am |
|
|
Hello
Following from Michael Lieske Mchip usa the trick is to fill buffer 0 with
prior 3 buffer 2 with prior2 buffer 1 with prior1 and then transmit
the first three frames and upon can tx 2 interrupt fill buffer 2 with prior 1
and upon 1 emptying fill it with prior 1 , 2 will allways go first
this way you avoid the can engine having to reacquire the bus
keeps the frames going across the bus and all in the right order
best wishes
Dara Hayes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jan 26, 2004 2:07 pm |
|
|
Hi Dara,
Can you post a "snippet" of the code, so we can see how to do it
for future reference ? |
|
|
dara hayes
Joined: 26 Nov 2003 Posts: 12 Location: Ireland
|
more than 3 frames code sample |
Posted: Tue Jan 27, 2004 9:13 am |
|
|
Here follows some code samples showing how I transmit many can frames in the correct order in which there are loaded into the buffers
without losing hold of the can bus (assuming no lost arbitration of course)
// ****** First the three CAN BUS TRANSMIT INTERRUPTS **********
#INT_CANTX0 // BUFFER 0 TX **********
void do_cantx0(void) // NOTHING TO DO IN CAN_TX0
{
if(tx_counter<30) // for debug to see in what order the ints occured
{tx_string[tx_counter]=0x30; // load number "0" for this interrupt
tx_counter++;}
}
#INT_CANTX1 // BUFFER 1 TX ************
void do_cantx1(void)
{
if(tx_counter<30) // for debug to see in what order the ints occured
{tx_string[tx_counter]=0x31; // load number "1" for this interrupt
tx_counter++; }
if(bit_test(CtrlReg,TX_ON)==1) // CHECK THE FLAG TO SAY WE GOT LOTS TO GO OUT
{
if(frames_to_go>0) // CHECK REMAINING FRAMES TO GO ?
{bit_set(CtrlReg,TX_1);} // ONLY SET FLAG WHEN THERE ARE MORE FRAMES TO GO
}
}
#INT_CANTX2 // BUFFER 2 TX ***********
void do_cantx2(void)
{
if(tx_counter<30) // for debug to see in what order the ints occured
{tx_string[tx_counter]=0x32; // load number "2" for this interrupt
tx_counter++;}
if(bit_test(CtrlReg,TX_ON)==1)
{
if(frames_to_go>0)
{bit_set(CtrlReg,TX_2);} // ONLY SET FLAG WHEN THERE ARE MORE FRAMES TO GO
}
}
Assuming there are more than 3 frames (>24 bytes of data) to be sent across the CAN BUS
then we first Load all three buffers ,
First Buffer 0 with PRIORITY Level 3
Next We load Buffer 2 With PRIORITY Level 2
Lastly we load Buffer 1 With PRIORITY Level 2
The variable "frames_to_go" is decreased after each buffer is loaded with fresh data.
// Meanwhile back inside the MAIN LOOP we check for the two flags "TX_2" and "TX_1"
// in order to refill the respective buffers with data as soon as they flag empty with their TX interrupt.
Main() .............
// Check the flags from Interrupts
if (bit_test(CtrlReg,TX_2)==1)
{
bit_clear(CtrlReg,TX_2);
fill_buffer2(); // only fill buffer 2 priority 1
}
if (bit_test(CtrlReg,TX_1)==1)
{
bit_clear(CtrlReg,TX_1);
fill_buffer1(); // only fill buffer 1 priority 1
}
// ccs code supplied in "can-18xxx8.c" needs to be modified to create a "can_putd" routine for each
// individual buffer , as the "can_putd" routine simply puts data to the fist available buffer
// in this case we need to write to a pariticualar buffer.
// fill_just_one() fill_just two() are used to fill either buffer 2 or buffer 1
void fill_buffer2(void)
{
if (frames_to_go>1)
{
fill_just_two(0);
}
else if (frames_to_go==1)
{
fill_just_two(1);
}
}
void fill_buffer1(void)
{
if (frames_to_go>1)
{
fill_just_one(0);
}
else if (frames_to_go==1)
{
fill_just_one(1);
}
}
// FILL JUST BUFFER ONE calls can_putd1 a simply modified routine in CCS can18xxx.c code
void fill_just_one(int lastx) // if lastx=1 then last frame
{
// fill just 1 buffer prior 1
int county;
int tempr;
tempr=8;
if (lastx==1)
{Bit_Clear(CtrlReg,TX_ON); // CAN IS FINISHED
Bit_set(CtrlReg,CAN_END);
tempr=total_rs232;}
for(county=0;county<tempr;county++)
{ buffer[county]=rs232_buffer[out_counter];
out_counter++; // up the pointer
total_rs232--; } // down the counter
can_putd1(transmit_id, buffer, tempr, 1, FALSE, FALSE); // modifed "can_putd"
frames_to_go--;
}
// FILL JUST BUFFER TWO calls can_putd2 a simply modified routine in CCS can18xxx.c code
void fill_just_two(int lastx) // last one just do it now
{
// we got less than = 8 bytes to send so fill just one buffer prior 0
int county;
int tempr;
tempr=8;
if (lastx==1)
{Bit_Clear(CtrlReg,TX_ON);
Bit_set(CtrlReg,CAN_END);
tempr=total_rs232;}
for(county=0;county<tempr;county++)
{ buffer[county]=rs232_buffer[out_counter];
out_counter++; // up the pointer
total_rs232--; } // down the counter // down the counter
can_putd2(transmit_id, buffer, tempr, 1, FALSE, FALSE); // modifed "can_putd"
frames_to_go--;
}
// CCS CAN c18xxx8.C modifed routine to just tx one particualar buffer
////////////////////////////////////////////////////////////////////////
//
// can_putd2() to buffer 2 dont assume tx buffer2 is free
//
////////////////////////////////////////////////////////////////////////
int1 can_putd2(int32 id, int * data, int len, int priority, int1 ext, int1 rtr)
{
int i;
int * txd0;
txd0=&TXRXBaD0;
if (TXB2CON.txreq) // must be empty before we start
{return(0);}
CANCON.win=CAN_WIN_TX2;
// we have an emtpy transmitter buffer zero
//set priority.
TXBaCON.txpri=priority;
//set tx mask
can_set_id(TXRXBaID, id, ext);
//set tx data count
TXBaDLC=len;
TXBaDLC.rtr=rtr;
for (i=0; i<len; i++) {
*txd0=*data;
txd0++;
data++;
}
//enable transmission
TXBaCON.txreq=1;
CANCON.win=CAN_WIN_RX0; // RETURN TO NORMAL ADDRESSING
return(1);
}
// ************************************
When the first three frames are loaded with buffer 0 priority 3 buffer 2 priority 2 buffer 1 prioirty 2
and upon interrupt can_tx2 buffer 2 is reloaded with priority 1 and upon interrupt can_tx1 buffer 1
is reloaded with prioity 1 and so on ,
This regeime will maintain data tranmission in the order in which they were loaded and the buffers
will ALLWAYS transmit in the following order 0212121212121 .... etc... etc ...
The bus will be "hogged" by this routine for as many frames are needed to be transmitted assuming the unit does not lose arbitration to a higher priority ID...
best wishes
Dara Hayes |
|
|
|
|
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
|