Searching \ for ' [PIC] SPI communication problems' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page:
Search entire site for: 'SPI communication problems'.

No exact or substring matches. trying for part
PICList Thread
'[PICLIST] [PIC] SPI communication problems'
2002\05\08@100543 by Claudio Tagliola

Hi all,

I'm trying to communicate with my MCP2510 unit through SPI. I've checked
data in/out and clock, they are correctly wired. I'm working with the CCS
compiler, a 20 Mhz 16F874 and the MCP is working on a 8 Mhz crystal. I've
tried a lot of different SPI settings, but the 'best' results are with
Low-to-high sampling and an SPI clock of T2-div-64.

I'm trying to write a register in the MCP and read it back again. However,
what comes back is not what i've put in. This is the result so far (in hex):

00 -> 00
01 -> 00
02 -> 81
03 -> 01
04 -> 82
05 -> 02
06 -> 83
07 -> 03
08 -> 84
09 -> 04
0A -> 85

It looks like the data is shifted by one bit and that the high bit is

Pin connections between the MCP and PIC:

       MCP             PIC

       INT             RB0/INT
       CS              RB1
       RESET           RB2
       SCK             RC3/SCK
       SO              RC4/SDI
       SI              RC5/SDO

The code for the SPI read/write is as follows:

#define UBYTE                   unsigned int

UBYTE readMCPReg( UBYTE regaddr ) {
       output_low( MCP_CS );           // Select the MCP2510
       spi_write( READCMD );           // Send the Read command
       spi_write( regaddr );           // Send the register
       rreg = spi_read( 0 );           // Read back the register
       output_high( MCP_CS );          // Deselect the MCP2510
       return( rreg );

void writeMCPReg( UBYTE regaddr, UBYTE regvalue ) {
       output_low( MCP_CS );   // Select the MCP2510
       spi_write( WRITECMD );
       spi_write( regaddr );
       spi_write( regvalue );
       output_high( MCP_CS );  // Deselect the MCP2510

setup_spi( spi_master | spi_h_to_l | spi_clk_div_64 );

Finally my question: does anyone recognize this problem? I've been hacking
on this problem for a day and a half now, searched the net, recovered my
tek, measured it, recoded it, fumbled with bits, emptied my coke glass... I
just don't know anymore.


Claudio Tagliola

-- hint: The list server can filter out subtopics
(like ads or off topics) for you. See

2002\05\08@104941 by John Dammeyer

Hi Claudio,

Here are some code snippets from my CANRF activity board which uses a
16F877 and has an onboard MCP2510 plus of course the socket for the
CANRF module which has it's own MCP2510.

In the command line interpereter.

               case 'R' : // CRr --  Read specific register.
                       DecArg = GetHexWord();
                       DecArg = MsgBuf[0];

MP_READ is a a macro:
// Read cnt bytes from MCP2510.
void MCP_read();

#define MCP_READ(REG,LEN) \\

Then we have the real routines:
** MCP_read
*  FILENAME: mcp2510.c
*  USES: MsgBuf[], SPIDataBUffer[], CAN_Select
*  CALLS: SPI_WriteBuf();
*  DESCRIPTION: Read MCP_cnt bytes from MCP2510 MCP_adr into MsgBuf[].
*  RETURNS: Data now resides in MsgBuf
MCP_read(void) {
 BYTE i @ SPI_Result;
       SPIDataBuffer[0] = 0x03;
       SPIDataBuffer[1] = MCP_adr;
       SPI_WriteBuf(CAN_Select, MCP_cnt+2);
       for (i=2; i<MCP_cnt+2; i++) {
               MsgBuf[i-2] = SPIDataBuffer[i]; }

Note that CAN_Select is a variable initialized from EEROM at startup to
hold 0 or 1 depending on whether the code should look at the onboard
MCP2510 or the CANRF MCP2510.

Finally you need the SPI bus routines:

void SPI_WriteBuf(BYTE chan, BYTE cnt) {
       INTCON.GIE = 0;
       chan = 1 << chan;
       PORTD &= ~chan;
       for (spi_i=0; spi_i<cnt; spi_i++) {
               SSPBUF = SPIDataBuffer[spi_i];
               while (!SSPSTAT.BF)
               SPIDataBuffer[spi_i] = SSPBUF;
       PORTD |= chan;
       INTCON.GIE = 1;

Note there is no watchdog support here and the application could hang if
the SPI bus isn't initialized so you need to do this:

// Set up PIC for SPI bus transfers as master.
InitSPI(void) {
       SSPCON.SSPEN = 0;
       SSPSTAT.CKE = 1;
       SSPSTAT.SMP = 0;
       SSPCON = 0b00000001;  // Tx on rising edge, Rx on falling,
Fosc/16 master.
       SSPCON.SSPEN = 1;
       SPI_IntSave = 0;

Interrupts are off to avoid the problem of the MCP2510 interrupt routine
screwing around with the SPI bus at the same time.  There are more
clever ways but this one is simple.  Optimizing is useful after the
project works.

Hope it helps.

John Dammeyer

Wireless CAN with the CANRF module.
Automation Artisans Inc.
Ph. 1 250 544 4950

> {Original Message removed}

More... (looser matching)
- Last day of these posts
- In 2002 , 2003 only
- Today
- New search...