|
|
View previous topic :: View next topic |
Author |
Message |
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
Trouble when used data frame and request frame in CAN. |
Posted: Wed Mar 12, 2014 7:05 pm |
|
|
Hi all.
I'm a beginner used CAN to build controller network.
I used PIC18F4680 (driver) and MCP2561( tranceiver) in nodes, CCSC ver 5.015.
I used CCS CAN library to coding, include "can-18xxx8.c" and "can-18xxx8.h".
I have a trouble when using can_putd() function in example "EX_CAN.c", has a task send request frame but it has data_send.
Code: |
...
//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;
i=can_putd(tx_id, out_data, tx_len,tx_pri,tx_ext,tx_rtr); //put data on transmit buffer
|
I have a trouble when using function " can_putd()" to send remote frame without data, and how to detect this frame in receiver nodes by using CCSC CAN Library.
Can pls show me this trouble.
Thanks all. _________________ Begin Begin Begin !!! |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
Re: Trouble when used data frame and request frame in CAN. |
Posted: Thu Mar 13, 2014 3:27 am |
|
|
tienchuan wrote: | Hi all.
I used PIC18F4680 (driver) and MCP2561( tranceiver) in nodes, CCSC ver 5.015.
|
MCP2561 is an external CAN controller. The MCP2551 is the transceiver. Are you using the 2551?
Quote: |
I used CCS CAN library to coding, include "can-18xxx8.c" and "can-18xxx8.h".
|
DO NOT include can-18xxx8.h. It's included by the can-18xxx8.c, so just include can-18xxx8.c. You can include can-18F4580.c instead but that's only needed if you are using the advanced functions of the ECAN that's in the PIC, such as FIFO receive buffering and more advanced filtering. Most people don't. As can-18F4580.c is a little slower for most operations, and can-18xxx8.c does everything that most CAN users need, they use can-18xxx8.c.
You must have defines for any CAN stuff that's not can-18xxx8.c's default. can-18xxx8.c assumes you are using 125kbps and 20MHz processor clock. If not then the CAN will run at the wrong speed and you won't be able to talk to to other CAN devices. If the speed is wrong, then you need to define stuff before the include to set the right speed. Look at can-18xxx8.h to work out what you need to define. Setting the CAN timing parameters is difficult, and easy to mess up, but there are CAN bit timing calculators on the web which make the job simpler.
You must call can_init() before the CAN can send or receive. Put it somewhere in your start-up code.
Quote: |
I have a trouble when using can_putd() function in example "EX_CAN.c", has a task send request frame but it has data_send.
Code: |
...
//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;
i=can_putd(tx_id, out_data, tx_len,tx_pri,tx_ext,tx_rtr); //put data on transmit buffer
|
I have a trouble when using function " can_putd()" to send remote frame without data, and how to detect this frame in receiver nodes by using CCSC CAN Library.
|
Hold on there! RTR is a *special* request that asks another CAN node to send a return value pre-loaded into the hardware. It doesn't use software at the receiving end. So unless you are using this special RTR thing, for get about it.
CAN doesn't work like that normally. With CAN, each node sends out message to any other node that wants to listen. The messages are broadcast: they go to all other nodes. Each node can decide which messages it wants to list listen to by filtering, either by masking and filters in the hardware, set up by the firmware, or in the firmware itself once the message has been read.
There are no "requests" (other than the special case of RTR) nor "commands", nor "data", all there is are messages of up to eight bytes. They only mean what you, the programmer, wants them to mean. You can interpret messages as commands, or requests, or data etc., but in CAN messages are just messages, (small) packets of data, with no specified meaning.
Messages can have from zero to eight data bytes. Its possible for the ID itself to be the 'data' of the message, which is why its possible, and useful, to send no bytes in a message.
To send a message you use can_putd:
Code: |
int out_data[8];
int32 tx_id=24; // This is a message type, it has to be unique and so should say which node sent this message.
int1 tx_rtr=0; // Don't use RTR.
int1 tx_ext=0; // Use 11 bit IDs
int tx_len=0; // Send no data bytes
int tx_pri=3; // Priority - don't worry about this now. It doesn't work like most people expect.
can_putd(tx_id, out_data, tx_len,tx_pri,tx_ext,tx_rtr); //put data on a transmit buffer - there are three and we cannot force which is used. The return value tells us which, but that's often not a lot of use.
|
When a message that the hardware receive filter accepts (they are set to accept all by default) arrives, can-18xxx8.c has a kbhit function, and you can use a receive interrupt for more advanced code.
Code: |
if (can_kbhit())
{
// Copy the data and the message length into our buffer.
can_getd(rx_id, Can_Rx_Buffer, rx_len, rxstat);
// rx-len tells us how many bytes were in the message, from zero to eight. rx_id tells us the ID of the message.
...
}
|
I hope this helps. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Thu Mar 13, 2014 7:20 am |
|
|
It should also be pointed out that the node that is responsible for replying to the RTR frame must have one of its filters set aside for the RTR reply. Depending on the size/complexity of your project, that hardware filter may be sorely missed. |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Sun Mar 16, 2014 9:25 am |
|
|
Thanks you RF_Developer and newguy, you're ardor to help me solve this problem.
In my project, I used 50 CAN nodes to communications,so i want to used remote frame, in this case, it is a command to PC request all nodes, in stead of using data frame to ordered all nodes. I think if i used remote frame will reduce data capacity on bus and shorten time to decode message in receiver node, because it only check "ID field", not check "Data field".
I tested to send and receive data frames beetween that nodes, it work fine with Extend ID, but it has problem when i use Standard ID. I tried both CAN driver "can-18F4580.c" and "can-18xxx8" but it still not work.
I tried update to CCS C ver 5.021.
Thanks u very much! _________________ Begin Begin Begin !!! |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Mon Mar 17, 2014 5:08 am |
|
|
tienchuan wrote: |
In my project, I used 50 CAN nodes to communications,so i want to used remote frame, in this case, it is a command to PC request all nodes, in stead of using data frame to ordered all nodes. I think if i used remote frame will reduce data capacity on bus and shorten time to decode message in receiver node, because it only check "ID field", not check "Data field". |
50 nodes is no problem for CAN. Having 50 nodes is no reason for using RTR. With RTR on PICs, the firmware doesn't do anything (other manufacturers processors may do RTR differently). The PIC firmware doesn't even necessarily know that it's received an RTR request. The response is done in the hardware. All the firmware has to do is keep the RTR response data up to date. RTR has no impact on bus capacity, but replies/data get back a little quicker.
I recommend you not using RTR. Its not going to do much for you. Better to work on getting normal messages to work.
Quote: |
I tested to send and receive data frames beetween that nodes, it work fine with Extend ID, but it has problem when i use Standard ID. I tried both CAN driver "can-18F4580.c" and "can-18xxx8" but it still not work.
|
You can send messages with extended IDs and standard IDs just by setting the flag in the can_putd call. However, with the default settings you can only receive one type at a time. The mode is set by whether CAN_USE_EXTENDED_ID is defined. If you've defined CAN_USE_EXTENDED_ID the driver will only read messages with extended ID, but you can send messages with extended or standard IDs.
It is possible to switch between receiving standard ID and extended ID, you have to use can_set_id to reconfigure your CAN receive filters. I use code like this:
Code: |
// Take the CAN module off-line. Was receiving standard
iDs.
can_set_mode(CAN_OP_CONFIG);
// Set up the filters to receive all messages in extended ID mode.
can_set_id(RX0MASK, CAN_MASK_ACCEPT_ALL, 1); //set mask 0
can_set_id(RX0FILTER0, 0, 1);//set filter 0 of mask 0
can_set_id(RX0FILTER1, 0, 1);//set filter 1 of mask 0
can_set_id(RX1MASK, CAN_MASK_ACCEPT_ALL, 1); //set mask 1
can_set_id(RX1FILTER2, 0, 1); //set filter 0 of mask 1
can_set_id(RX1FILTER3, 0, 1); //set filter 1 of mask 1
can_set_id(RX1FILTER4, 0, 1); //set filter 2 of mask 1
can_set_id(RX1FILTER5, 0, 1); //set filter 3 of mask 1
// Bring the CAN back on line, now receiving only extended ID messages.
can_set_mode(CAN_OP_NORMAL);
|
You can probably also set some receive filters to accept extended ID, with the rest set for standard IDs, but I haven't tested that.
Some other important things:
With CAN its best not to think of IDs as addresses. You can't really send to a node in CAN. Please don't think of CAN as sending data from A to B. Instead think of it as A broadcasts a message which B, or any other node, can listen to if it wants. Also messages are not guaranteed to be received in the order they are sent. So the idea of a node to node communications channel is not part of CAN. Each message stands on its own.
Its important that all IDs must be unique. This is for CAN's arbitration to work properly. To do this, IDs generally include the message type and the unique "address" of the sending node. That way any number of nodes can send the same type of message at the same time and the arbitration built in to CAN will sort it all out, making sure there's no message corruption.
If the ID encoded the destination rather than the source, then if more than one node sent the same type of message to the same destination then the arbitration couldn't work and the messages would get confused and corrupted.
So, IDs say what type the message is and where it came from. Nodes that want to listen set their hardware message filters to accept the message types they want to receive, ignoring the source node address (the firmware can decide to do whatever it wants with that part of the ID if that's needed).
So, if you have, say, a network with one master data-collector node and forty-nine nodes sensors, there are a number of ways you could organise it. You could have each sensor node sending out its data regularly on a timer. The master node listens and collects the data as it arrives. Or you could make the sensors all slaves that only send their data when the master asks for it. The master doesn't have to ask each sensor node for data, it could just send out a message that polls, saying, "send your most recent data now", and then all nodes that have data send out their data messages. In both cases, the ID of the message from the sensors say which sensor sent it, making it easy for the master data-collector to keep track of everything. You could have more than one data collector node - remember any node that's interested can listen to any messages it needs. |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Fri Mar 21, 2014 12:48 am |
|
|
Thanks u.
I retested by edit CAN_USE_EXTENDED_ID equal 0 to using Standard ID.
I worked fine and I worked interface beetween nodes, i'm using can_getd to receive data frame in main loop, include with check can_kbhit interrupts flag to read data from buffer.
Now, I want to receive data frame in int_canrx0 and int_canrx1 to avoid data frame can be loss when transmit.
I searched on 4rum and saw your repply has relative of my questions.
http://www.ccsinfo.com/forum/viewtopic.php?t=24155
In your code, I saw you build Can_Buffer_Read() function to read data from circular buffer. I want tried using this function to read out data but it send data not correct.
Code: |
if (Can_Buffer_Read(*buffer))
{
for(i_count=0; i_count <16; i_count++ )
{
printf("\n\r buffer:%x",*buffer);
buffer++;
}
}
|
Pls show me that problems.
I want to build fast receive data function to apply in node interfaces RS232 with PC.
Thanks you. _________________ Begin Begin Begin !!! |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Fri Mar 21, 2014 2:29 am |
|
|
tienchuan wrote: |
In your code, I saw you build Can_Buffer_Read() function to read data from circular buffer. I want tried using this function to read out data but it send data not correct.
Code: |
if (Can_Buffer_Read(*buffer))
{
for(i_count=0; i_count <16; i_count++ )
{
printf("\n\r buffer:%x",*buffer);
buffer++;
}
}
|
Pls show me that problems.
I want to build fast receive data function to apply in node interfaces RS232 with PC.
|
CAN doesn't work like RS232. CAN messages are anything from no bytes to eight bytes of data. Its not a stream of characters or bytes like RS232. In my example the buffer is of structures of type Can_Buffer representing messages, not characters. You can't just print the buffer directly like you are trying to do. That simply isn't going to work.
Another problem is that CAN messages do not necessarily get sent and received in order. A set of messages A, B, C, D may arrive as A, B, D, C. I won't try and explain why that is - its to do with the way the hardware works - but its a problem you'll have to sort out if you want to make CAN emulate a byte-stream interface like RS232. |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Mon Mar 24, 2014 2:00 am |
|
|
Thanks u.
I'm using to read out data and send to RS232 from CAN data frame in your function:
Code: | BOOLEAN Can_Buffer_Read(struct Can_Buffer *Buffer) |
Pls u show me a errors. _________________ Begin Begin Begin !!! |
|
|
|
|
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
|