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

dsPic30f4011 + CAN loop back strange problem

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



Joined: 16 Mar 2012
Posts: 31

View user's profile Send private message

dsPic30f4011 + CAN loop back strange problem
PostPosted: Mon Mar 26, 2012 8:52 am     Reply with quote

Hi everybody, I am doing a CAN communication between two dsPic30f4011. Because it hasn't worked so I decide to test it in loop back mode. I connect the dsPic with MCP2551 just like many schematic (Rs connect directly to ground,other pins connect as in the datasheet...). It works fine in loop back mode,but the problem is when I disconnect the dsPic from MCP2551, just the dsPIC by itself, the LED still flash like it is connected with MCP !!!???
Here is my code:

Code:
#include <30F4011.h>
#DEVICE ADC=10
#include <stdlib.h>
#include <can-dsPIC30.h>
#include <can-dsPIC30.c>

#FUSES FRC,NOWDT
#use delay(clock=4000000)

void main()
{
   struct rx_stat rxstat;
   int32 rx_id;
   int32 tx_id;
   int8 rx_len;
   int8 buffer[8];
   int8 i;
   set_tris_b(0x00);
   can_init();
   can_set_mode(CAN_OP_LOOPBACK);
   for (i=0;i<8;i++)
   { 
      buffer[i] = 0;
   }
   while(1)
   {
      buffer[0] = 3;
      buffer[1] = 2;
      buffer[2] = 1;
      buffer[3] = 0;
      for (i=0;i<4;i++)
      {
         can_putd(25,&buffer[i],1,1,1,0);
         delay_ms(1000);
      }
      if(can_kbhit())
      {
         if(can_getd(rx_id, &buffer, rx_len, rxstat))
         {
            if(rx_id == 25)
            {
               output_b(buffer[0]);
               delay_ms(1000);
               output_b(buffer[1]);
               delay_ms(1000);
               output_b(buffer[2]);
               delay_ms(1000);
               output_b(buffer[3]);
               delay_ms(1000);
            }
         }
      }
   }
}

My code is to flash the LEDs in portB when it output value from 0 to 3.
Can anyone help me figure why the LEDS still flash even when I disconnect the dsPic from the MCP2551.
Thank you very much.
hoangkhuong



Joined: 16 Mar 2012
Posts: 31

View user's profile Send private message

PostPosted: Mon Mar 26, 2012 9:11 am     Reply with quote

I have connected the two dsPic30f4011 directly without the two MCP2551s and it works perfectly. I will keep trying again with the MCPs. It seems that even in the loopback mode, dsPic doesn't need the MCP to do CAN.

Edit : When I connect the two dsPic directly, I connect CANTX on the 1st dsPic to CANTX on the 2nd dsPic and the same for CANRX and it works !!! But if I connect CANTX on the 1st to CANRX to the 2nd then it doesn't work !!! I am really confused. Hope somebody can help me out.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 26, 2012 11:11 am     Reply with quote

Quote:

When I disconnect the dsPic from MCP2551, just the dsPIC by itself, the LED still flash.
It seems that even in the loopback mode, dsPic doesn't need the MCP to do CAN.

Loopback mode is completely internal to the PIC. No external drivers
are used. No signals are present on the C1TX and C1RX pins during
loopback mode. This is explained in the dsPIC30F4011 data sheet:
Quote:

19.3.6 LOOPBACK MODE

If the Loopback mode is activated, the module will
connect the internal transmit signal to the internal
receive signal at the module boundary. The transmit
and receive pins revert to their port I/O function.



Quote:
I have connected the two dsPic30f4011 directly without the two MCP2551s

Direct connection of two PICs without the CAN bus transceivers is not
supported. Read this Microchip FAQ page on the CAN bus:
Quote:

What is required for a CAN node?

It says a transceiver (MCP2551) is required for a CAN bus node.
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2009&param=en001003
hoangkhuong



Joined: 16 Mar 2012
Posts: 31

View user's profile Send private message

PostPosted: Mon Mar 26, 2012 5:47 pm     Reply with quote

Thank you, PCM progammer for your quick reply !
1st problem: Checked. I also figured that out.
2nd problem: according to the info you provided to me, they said "a transceiver that is the physical layer interface (adapts the signal levels to/from the bus from/to the CAN controller)", I think this is because in a CAN network, the nodes can be different MCU and different type of CAN controller with different physical voltage value, so they need a common interface, but here is between two identical uC and the voltage level is also the same. so it doesn't need a CAN transceiver (at least that's what I think). Anyway, if it is the case, then why the CAN works while I disconnect the MCP, can you help me figure that out ? And strangely enough, I have to connect together two CANTX and two CANRX of the two uC for it to work, not CANTX to CANRX and vice versa.
Thank you very much for your help Smile
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Mar 27, 2012 6:31 am     Reply with quote

hoangkhuong wrote:
according to the info you provided to me, they said "a transceiver that is the physical layer interface (adapts the signal levels to/from the bus from/to the CAN controller)", I think this is because in a CAN network, the nodes can be different MCU and different type of CAN controller with different physical voltage value, so they need a common interface,


Not really. Its because CAN is a differentially signalled broadcast bus. The two CAN bus lines are not TX & RX, they are CAN_L (CAN LOW) and CAN_H (CAN HIGH and are bi-directional. It also means a CAN mode cannot easily listen to itself and so the PIC CAN peripheral provides the loopback mode. The transceiver converts the unidirectional CANTX and CANRX to the bi-directional CAN_L and CAN_H and protects the micro from the possibly high voltages on the CAN BUS. the MCP2551 is capable of being used in a truck based variant of CAN and so it can withstand over 30V on CAN_L and CAN_H. I've been thankful of that: it really works!

You don't have to use the MCP2551, though its a good choice: easy to buy, low cost, works well, There are other CAN transceivers out there. Its not CAN unless you do use a transceiver.

The CAN bus connects all CAN-Ls together, and all CAN_Hs together. There is often at least one terminating resistor connected between CAN_L and CAN_H at one or more transceivers. Sometimes on every transceiver.

Check up on how CAN works, you seem to be a little confused.

RF Developer
hoangkhuong



Joined: 16 Mar 2012
Posts: 31

View user's profile Send private message

PostPosted: Tue Mar 27, 2012 8:44 am     Reply with quote

Thanks,RF Developer. Now I understand more about the transceiver. I have connected the 2 boards via the 2 MCP2551. And now it works, I have no idea :D. Anyway, here is my other problem, I hope that you can clear it out so I can understand more about CAN in microcontroller.
My problem is when I try to send 3 numbers continuously from board 1 to board 2 and output to port B, it seems that only the 1st buffer that is sent from board 1,the other two value didn't show up. so board 2 only capture the 1st byte it receives.
Hope somebody can figure it out for me.Thanks very much.
Here is my code:
For 1st Board,just sending
Code:
#include <30F4011.h>
#DEVICE ADC=10
#include <stdlib.h>
#include <can-dsPIC30.h>
#include <can-dsPIC30.c>

#FUSES FRC,NOWDT
#use delay(clock=4000000)

void main()
{
   struct rx_stat rxstat;
   int32 rx_id;
   int32 tx_id;
   int8 rx_len;
   int8 buffer[3];
   int8 i;
   can_init();
   for (i=0;i<3;i++)
   { 
      buffer[i] = 0;
   }
   while(1)
   {
      buffer[0] = 3;
      buffer[1] = 2;
      buffer[2] = 1;
      if (can_tbe())
      {
         for (i=0;i<3;i++)
         {
            can_putd(25,&buffer[i],1,1,1,0);         
         }
      }
   }
}

For 2nd Board,just receiving and output to LEDs in port B
Code:
#include <30F4011.h>
#DEVICE ADC=10
#include <stdlib.h>
#include <can-dsPIC30.h>
#include <can-dsPIC30.c>

#FUSES FRC,NOWDT
#use delay(clock=4000000)

void main()
{
   struct rx_stat rxstat;
   unsigned int32 rx_id;
   unsigned int32 tx_id;
   unsigned int8 rx_len;
   unsigned int8 buffer[3];
   int8 i;
   set_tris_b(0x00);
   output_b(0x00);
   can_init();
   for (i=0;i<3;i++)
      {
         buffer[i] = 0;
      }
   while(1)
   {
      if(can_kbhit())
      {
         if(can_getd(rx_id, &buffer, rx_len, rxstat))
         {
            if(rx_id == 25)
            {
               output_b(buffer[1]);
               delay_ms(200);
               output_b(buffer[2]);
               delay_ms(200);
               output_b(buffer[0]);
               delay_ms(200);
            }           
         }
      }
   }
}
jgschmidt



Joined: 03 Dec 2008
Posts: 184
Location: Gresham, OR USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Mar 27, 2012 9:29 am     Reply with quote

Check the "PICC\Data Sheets" directory. You may have a manual in there for the CCS CANbus development kit. This is useful for learning about the CAN bus even if you don't have the kit. It has the code for making a bus monitor which I find critical for testing. It will show if your message even got onto the bus.

Personally, I use the Microchip Can Bus Monitor Demonstration board as a monitor and message injection tool.

I also found the following references to be useful in learning about the CAN bus:

http://www.copperhillmedia.com/wp-content/uploads/2010/04/CAN_Book_Preview.pdf - A Comprehensible Guide to Controller Area Network

http://www.ti.com/lit/an/sloa101a/sloa101a.pdf - from Texas Instruments

http://www.ti.com/lit/an/slla270/slla270.pdf - from Texas Instruments

http://ww1.microchip.com/downloads/en/AppNotes/00713a.pdf - from Microchip

http://ww1.microchip.com/downloads/en/AppNotes/00228a.pdf - from Microchip

Cheers,

Jürgen
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Mar 27, 2012 9:50 am     Reply with quote

Each CAN message has an ident and upto eight data bytes. You can't send a message to anywhere, instead you send a message with an ID and any node that wants to listen to that messages with that ID receives them. So you can have one sender and many listeners, and many senders sending to one (or more) listeners. In fact CAN is not particularly good for sending from A to B.

I think of it as a broadcast bus, a node can send a message. Its up to the other nodes to decide which message types (IDs) they want to listen to.

Your call:

can_putd(25,&buffer[i],1,1,1,0);

is sending a single byte message with ID 25(decimal). The data byte is the byte buffer[i]. The last two parameters are boolean and should Instead you may want to send all the bytes at once as a single message:

can_putd(25,buffer,2,1,FALSE,FALSE);

The CCS supplied CAN routines and hardware allow you to request three messages to be sent. They may NOT be sent in the order you want them to be sent. This is due to the way the CAN hardware buffers its data. In CAN there is no idea of ordering of messages. Every message is totally independant and there's no easy way, other than waiting a longish time between them, of ensuring they go out in any particular order. They will be sent when the CAN hardware gets around to sending them.

In the default configuration of the CAN hardware there are only two receive buffers. So if you've just received a CAN message, your software must read it before more than one other message arrives. This means that you will almost certainly need extra interrupt driven buffering for many applications. I impliment 16 additional receive buffers as my messages can come at about 1ms apart and my code may take longer than 10ms to do some operations.

In your code, it receives the first message with the first byte, then it does stuff for over 600ms. The second message will be buffered, but the third may get lost.

Start simply by sending a message every 100ms or so: ten per second. Make it anything up to 8 bytes. Try receiving that. Then try sending two messages every 100ms. See what happens.

Then think about what you need to do. How many messages do you need to send? I have a system here that sends something well over a hundred messages a second from about 8 different nodes. Most nodes listen to a subset of these messages. I have a CAN monitor app on my PC that I've written that has a USB - CAN adaptor of my own design, with a PIC inside of course that listens to all this traffic and displays a mimic of the entire system in real time. It all works: ten or more PICs all talking over one CAN bus all the time. So you can do good stuff with CAN!

RF Developer
hoangkhuong



Joined: 16 Mar 2012
Posts: 31

View user's profile Send private message

PostPosted: Tue Mar 27, 2012 10:21 am     Reply with quote

Thanks very much for your informative response. I'll try that.
Anyway, as your explanation contain one thing that I don't understand. In the call:
Code:

can_putd(25,&buffer[i],1,1,1,0);

The third parameter is the length of the message, so I want to send message as a byte only, then the 3rd parameter should be 1 instead of 2 as in your post, right ?

Also,the fifth parameter is TRUE, since it uses extended identifier, and as I read somewhere in the forum, they said it would be better to use extended format.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Wed Mar 28, 2012 2:00 am     Reply with quote

hoangkhuong wrote:
In the call:
Code:

can_putd(25,&buffer[i],1,1,1,0);

The third parameter is the length of the message, so I want to send message as a byte only, then the 3rd parameter should be 1 instead of 2 as in your post, right ?


Yes, that's right. I was trying to show you that you don't have to send single bytes. You can if you want. The third parameter is the number of data bytes to be sent in the message.

Quote:

Also,the fifth parameter is TRUE, since it uses extended identifier, and as I read somewhere in the forum, they said it would be better to use extended format.


Better? I don't use extended format. I've never needed to. Standard IDs are 11 bits, extended IDs, which mean longer frames on the bus, are 29 bits.

ID is intended to encode the message type and the message source. No two nodes are meant to send the same message IDs, and this is used to impliment bus arbitration in the event of two nodes sending at the same time. I confess my applications don't follow the rules properly and more than one node can send messages with the same ID - it doesn't make any attempt to encode the source in the ID, though it could.

If you've only got two nodes then normal IDs are good. I've got twelve and I'm still only using normal IDs!

RF Developer
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