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

MCP2515 help

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



Joined: 15 Apr 2013
Posts: 6

View user's profile Send private message

MCP2515 help
PostPosted: Tue Oct 22, 2013 8:28 am     Reply with quote

Hi,

Am using a PIC1F876 controller and the MCP2515 IC. I have been trying to make the CAN bus work for almost 4 months now. But all the methods I have tried has not yielded me the results.

A brief description on my circuit. The PIC16F876 is connected to a 12 MHz crystal and to the MCP2515 via SPI. The MCP2551 is connected to a 4MHz crystal. I am using the CCS compiler (PCM V4.093).

I have used the CCS library files can-mcp251x.c. Here I have modified the SPI routines with the spi_write() and spi_read functions instead of the for loop used (I2C routines).

The below code is similar to the sample code provided in the link
http://www.ccsinfo.com/forum/viewtopic.php?t=29627
Code:

#include <16F876.h>
#device ICD=TRUE
#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=12000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#include <can-mcp251x.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];
setup_spi(SPI_MASTER | (SPI_L_TO_H | SPI_XMIT_L_TO_H) | SPI_CLK_DIV_16);
printf("\r\n Can Test Program - Node 1");
can_init();


#ifdef BOARD1   // For Board #1
tx_id=BOARD2_ID;
while(true)
  {
   buffer[0] = getc();   // 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 ?
        {
         putc(buffer[0]);  // If so, display the char
        }
      }
  }
#else  // For Board #2
tx_id=BOARD1_ID;
while(1)
  {
   if(can_kbhit())  // Message available ?
     {
      // 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
 
}

But with this code, when I try to transmit, I do not receive the data on the second bus.

I would like to know which part I have missed out. I am not able to break the ice in this case.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Oct 22, 2013 10:13 am     Reply with quote

The can-mcp251x.c I've got (PCWH V4.132) sets up the SPI for you. It has #use spi and spi_xfer(). There's no need to modify it. I'm also confused by you mentioning I2C and for loops.

If yours is a similar version of can-mcp251x.c then your setup_spi() is going to cause problems. With can-mcp251x.c if you need to use alternate pins you need to override the definitions of the pins before the include of can-mcp251x.c

Code:

      // These are the default defines from can-mcp251x.h.
      #define EXT_CAN_CS   PIN_B1
      #define EXT_CAN_SI   PIN_C1
      #define EXT_CAN_SO   PIN_C0
      #define EXT_CAN_SCK  PIN_C3

#include <can-mcp251x.c>


There is a lot that can go wrong. Your SPI connections to the mcp2510 must be right. The wiring to the CAN transceiver must be correct and the wiring and termination of the CAN bus itself must be right.

The CAN bus speed is set in can-mcp251x.c and will default to 125KBps when the mcp2510 is clocked at 20MHz, just as can-18xxx8.c and can-18F4580.c do. Like the SPI settings, this can be changed by overriding the default defines in can-mcp251x.h.

Many people have trouble just getting the PIC clock settings right. With the mcp2510 you have to get that working as well. :-(

Do you have a CAN bus monitor that you can use with a PC to make sure each node is working correctly on their own before connecting them together? You need to check this and get it working stage by stage. Make sure the PIC is running at the right speed, then ensure the 2510 is clocked correctly. Then check the SPI is working with the correct waveforms. Then check to see if the 2510 is driving the mcp2551 CAN interface IC. Then you can look on the CAN bus itself and check the voltages and waveforms/timing are right. Then you can connect one node to the monitor and make sure you can send & receive to the PC. Finally, when you've sorted out BOTH nodes separately, you can connect them together and see if you can send messages between them. By that stage, you should have the confidence to be able to get any number of nodes working and send messages all over the place.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Oct 22, 2013 1:03 pm     Reply with quote

RF_Developer wrote:
I'm also confused by you mentioning I2C and for loops.

He's using vs. 4.093. Older compiler versions did software SPI with
i/o pins in a loop in can-mcp251x.c. Here is a typical routine from that
file. It has several more routines written in this same style:
Code:

void mcp2510_command(int command) {
   int i;

   output_low(EXT_CAN_CS);

   for (i=0;i<8;i++) {
      output_bit(EXT_CAN_SI, shift_left(&command,1,0));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }

   output_high(EXT_CAN_CS);
}



praks1510 wrote:
I have used the CCS library files can-mcp251x.c. Here I have modified the SPI routines with the spi_write() and spi_read functions instead of the for loop used (I2C routines).

But all the methods I have tried has not yielded me the results.

Why don't you try to make the program work with the standard CAN bus
drivers first. Then after it's working, you can edit the driver files and
try to make it work with hardware SPI.


praks1510 wrote:
The MCP2551 is connected to a 4MHz crystal.

Are you sure ? MCP2551 is a CAN Bus transceiver chip. It doesn't
connect to a crystal. Do you really mean you have the PIC connected
to a 4 MHz crystal ?
praks1510



Joined: 15 Apr 2013
Posts: 6

View user's profile Send private message

PostPosted: Tue Oct 22, 2013 10:12 pm     Reply with quote

I have changed the SPI pins to my hardware as follows

Code:

#define EXT_CAN_CS   PIN_B4
   #define EXT_CAN_SI   PIN_C5
   #define EXT_CAN_SO   PIN_C4
   #define EXT_CAN_SCK  PIN_C3


Sorry the 4MHz crystal is connected to the MCP2515. Not the transceiver.

So by the reply I understand that the function

Code:

void mcp2510_command(int command) {
   int i;

   output_low(EXT_CAN_CS);

   for (i=0;i<8;i++) {
      output_bit(EXT_CAN_SI, shift_left(&command,1,0));
      output_high(EXT_CAN_SCK);
      output_low(EXT_CAN_SCK);
   }

   output_high(EXT_CAN_CS);
}


uses only SPI.
praks1510



Joined: 15 Apr 2013
Posts: 6

View user's profile Send private message

PostPosted: Tue Oct 22, 2013 10:15 pm     Reply with quote

And about the BUS monitor, is there any standard software available that can connect to any hardware to monitor the CAN traffic?
praks1510



Joined: 15 Apr 2013
Posts: 6

View user's profile Send private message

PostPosted: Tue Oct 22, 2013 10:34 pm     Reply with quote

Hi again.

I tried to use the default code and I get the same result. Am not able to establish the communication.

I have included my codes with this reply.

NODE 1

Code:
#include <16F876.h>
#device ICD=TRUE
#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=12000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#include <can-mcp2510.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];
//setup_spi(SPI_MASTER | (SPI_L_TO_H | SPI_XMIT_L_TO_H) | SPI_CLK_DIV_16);
printf("\r\n Can Test Program - Node 1");
can_init();
printf("\r\n Initialised. ");

#ifdef BOARD1   // For Board #1
tx_id=BOARD2_ID;
while(true)
  {
   buffer[0] = getc();   // 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 ?
        {
         putc(buffer[0]);  // If so, display the char
        }
      }
  }
#else  // For Board #2
tx_id=BOARD1_ID;
while(1)
  {
   if(can_kbhit())  // Message available ?
     {
      // 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
 
}


Now the CAN routines.

Code:
#if CAN_DO_DEBUG
 #define can_debug printf
#else
 #define can_debug
#endif

////////////////////////////////////////////////////////////////////////
//
// can_init()
//
// Initializes MCP2510 CAN peripheral.  Sets the RX filter and masks so the
// CAN peripheral will receive all incoming IDs.  Configures both RX buffers
// to only accept valid valid messages (as opposed to all messages, or all
// extended message, or all standard messages).
//
// The constants (CAN_USE_RX_DOUBLE_BUFFER, CAN_ENABLE_DRIVE_HIGH,
// CAN_ENABLE_CAN_CAPTURE, etc) are given a default define in the can-mcp2510.h file.
// These default values can be overwritten in the main code, but most
// applications will be fine with these defaults.
//
//////////////////////////////////////////////////////////////////////////////
void can_init(void) {


[Driver code deleted]

++++++++++++++++++++
CCS driver file mostly deleted.
Reason: Forum Rule #10
10. Don't post the CCS example code or drivers.
http://www.ccsinfo.com/forum/viewtopic.php?t=26245
- Forum Moderator
++++++++++++++++++++



It would be of great help if you could analyse my codes and let me know where I have gone wrong.

With the second node, I have used the same CAN codes and just a small correction with my main program. I have commented the following statement to indicate that it is the second node.

Code:
// Uncomment this line to compile code for Board #1.
// Comment it out to compile for Board #2.
//#define BOARD1   1
praks1510



Joined: 15 Apr 2013
Posts: 6

View user's profile Send private message

PostPosted: Wed Oct 23, 2013 1:06 am     Reply with quote

Hi again.

This time am here to tell you all that my hardware is working fine. I haven't changed the firmware. I have used the same CCS code drivers available with my compiler.
I have changed the 4MHz crystal connected to the MCP2515 to 20MHz to support the firmware. I did this to check on the hardware.

RF_Developer wrote
Quote:

The CAN bus speed is set in can-mcp251x.c and will default to 125KBps when the mcp2510 is clocked at 20MHz, just as can-18xxx8.c and can-18F4580.c do. Like the SPI settings, this can be changed by overriding the default defines in can-mcp251x.h.
praks1510



Joined: 15 Apr 2013
Posts: 6

View user's profile Send private message

PostPosted: Wed Oct 23, 2013 7:18 am     Reply with quote

Hi admin,

I would like to have the following doubt of mine cleared as well. In my hardware, I use a PIC16F876, the MCP2515 -> MCP2551 for the CAN traffic, connected via the SPI. I also use a MCP25S17 (I/O port expander) connected to the controller via the same SPI.

I have two different projects, one for the CAN and another for the port expander. Both the projects are working fine separately. Now that I have been trying to merge both the projects into the single one.

With Node 1 CAN Project I have included the MCP25S17 routines, where I have just initialised the IC and set the port values to the default value. Now when I send the message, the same is received on the Node 2 but the reply message from the Node 2 has got the same message but, the ID and length parameters are set to '0' (Zero).
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Oct 23, 2013 3:59 pm     Reply with quote

If your program doesn't work properly after adding new routines, then
comment out the new routines one by one, until the program starts
working again. Also comment out new variable declarations. Try to
find out which routine, or which variable declaration is causing the problem.
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