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

SPI Problem from PIC16F886 to MAXQ3180
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
boulder



Joined: 15 Mar 2008
Posts: 53

View user's profile Send private message

SPI Problem from PIC16F886 to MAXQ3180
PostPosted: Sat Mar 15, 2008 7:56 pm     Reply with quote

I am using PIC16F886 as MASTER to talk to MAXQ3180, SLAVE, with SPI interface. I have tried different ways to make them work, but I have no luck. My compiler is PCM_4.069. I wonder if my SPI setting is wrong. My code is bleow, could anyone give me an advice? Thanks.
Code:

#include "16F886.h"
#include <stdio.h>

#use delay(clock=4000000)
#use spi(MASTER, MODE=0, LSB_FIRST, BITS=8, BAUD=250000, STREAM=SPI_STREAM)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use fast_io(C)
#fuses INTRC, NOWDT, PUT, MCLR, NOPROTECT, NOCPD, NOBROWNOUT, NOIESO, NOFCMEN, NOLVP, NOWRT

   int i=0;
   int Sendtab[6]={0x10,0x26,0x00,0x00,0x00,0x00};
   int Receivetab[6];

void main()
{

   setup_oscillator( OSC_4MHZ );

   set_tris_c(0x10);                    //Set C4 input, DI.

   output_high(PIN_C1);                 //PIN_C1 is slave select pin

   output_low(PIN_C1);   //Slave Select

   for(i=0;i<6;i++)
   {
     spi_xfer(SPI_STREAM, Sendtab[i]);          //Send data
     Receivetab[i] = spi_xfer(SPI_STREAM, 0);   //Read data                   
   }

   output_high(PIN_C1);

   for(i=0;i<6;i++)
      printf("%x\n",Receivetab[i]);    //Print out data


   while(1);

}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Mar 16, 2008 8:44 am     Reply with quote

Your SPI configuration is incorrect. Check figure 5a of the MAXQ3180 datasheet, you should transmit MSB first, not the LSB first. This is the same as with all other SPI hardware I've used.

Now the SPI-mode... as you already might know there are a total of 4 different SPI configurations possible, these are referred to as SPI-mode 0 to 3. More information on this can be found at http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus.
The MAXQ3180 datasheet looks like to have an error, the text at page 12 is in conflict with Figure 5a and 5b. I think these are interchanged. Figure 5a should be the sequence for CKPHA=0 and 5b for CKPHA=1.
Either way, this means we can not determine the mode the device starts up in. You will have to try both mode 0 and 1. My guess is it starts up in mode 1.
boulder



Joined: 15 Mar 2008
Posts: 53

View user's profile Send private message

PostPosted: Sun Mar 16, 2008 3:09 pm     Reply with quote

Hi,
I have changed my code to MSB_FIRST and tried 4 different modes from 0 to 3, but I still cannot get any data out. The below is my code.
Code:

#include "16F886.h"
#include <stdio.h>

#use delay(clock=4000000)
#use spi(MASTER, MODE=0, MSB_FIRST, BITS=8, BAUD=250000, STREAM=SPI_STREAM)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use fast_io(C)
#fuses INTRC, NOWDT, PUT, MCLR, NOPROTECT, NOCPD, NOBROWNOUT, NOIESO, NOFCMEN, NOLVP, NOWRT

   int i=0;
   int Sendtab[6]={0x10,0x26,0x00,0x00,0x00,0x00};
   int Receivetab[6];

void main()
{

   setup_oscillator( OSC_4MHZ );

   set_tris_c(0x10);                    //Set C4 input, DI.

   output_high(PIN_C1);                 //PIN_C1 is slave select pin

   output_low(PIN_C1);   //Slave Select

   for(i=0;i<6;i++)
   {
     spi_xfer(SPI_STREAM, Sendtab[i]);          //Send data
     Receivetab[i] = spi_xfer(SPI_STREAM, 0);   //Read data                   
   }

   output_high(PIN_C1);

   for(i=0;i<6;i++)
      printf("%x\n",Receivetab[i]);    //Print out data


   while(1);

}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Mar 16, 2008 4:11 pm     Reply with quote

Code:
   for(i=0;i<6;i++)
   {
     spi_xfer(SPI_STREAM, Sendtab[i]);          //Send data
     Receivetab[i] = spi_xfer(SPI_STREAM, 0);   //Read data                   
   }
SPI is a full duplex communications protocol, i.e. you are sending and transmitting data at the same time. In the above code you are intermittently sending a command byte and then a zero byte which is wrong. Try the following code instead:
Code:
   for(i=0;i<6;i++)
   {
     Receivetab[i] = spi_xfer(SPI_STREAM, Sendtab[i]);   //Send & read data
   }
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 16, 2008 4:30 pm     Reply with quote

Quote:
#use spi(MASTER, MODE=0, MSB_FIRST, BITS=8, BAUD=250000, STREAM=SPI_STREAM)

The line above uses software SPI. Is that your intention ?

With software SPI, you must specify the SDI, SDO, and \SS pins
as shown in bold below:
Quote:
#use spi(MASTER, MODE=0, MSB_FIRST, BITS=8, BAUD=250000, DI=PIN_C4, DO=PIN_C5, ENABLE=PIN_C1, STREAM=SPI_STREAM)


If you want to use hardware SPI, you must tell it to "Force HW" and
specify the \SS pin. You must also connect your device to the H/W SPI
pins on the PIC. I assume that this is your actual intention. Example:
Quote:
#use spi(MASTER, MODE=0, MSB_FIRST, BITS=8, BAUD=250000, FORCE_HW, ENABLE=PIN_C1, STREAM=SPI_STREAM)


Quote:

#use fast_io(C)
set_tris_c(0x10);

You don't need to setup the TRIS. The compiler will do it for you
if you don't use fast i/o mode. I suggest that you delete both of those
statements.

Quote:

output_high(PIN_C1); // PIN_C1 is slave select pin

output_low(PIN_C1);

output_high(PIN_C1);

You don't need these statements. The compiler will automatically
handle the \SS pin for you if you specify it with the ENABLE parameter
in the #use SPI() statement, as I have shown above. I suggest that
you delete all these statements.


What crystal frequency are you using for the MAXQ3180 ?
This is fairly complicated chip and it has a large number of "gotchas"
and restrictions on it. For example, the data sheet says:
Quote:

For proper communications operation, the SPI clock frequency
used by the master must be less than or equal to the MAXQ3180's
clock frequency divided by 8. For example, when the MAXQ3180
is running at 8MHz, the SPI clock frequency must be 1MHz or less.

You have selected 250 KHz as the SPI clock, so that will work,
provided that you're using an 8 MHz crystal on the MAXQ3180.

But also, the data sheet says there must be a delay between each
byte that is transmitted/received, and your code doesn't have that:
Quote:

In addition to limiting the overall SPI bus clock rate, the master
must also include a communications delay following each byte
transmit/receive cycle. This delay, which provides the MAXQ3180
with time to process the transmitted byte, should be a minimum
of 1 ADC scan slot. With default settings and running at 8MHz,
this delay time is 25 usec.


Quote:

spi_xfer(SPI_STREAM, Sendtab[i]); //Send data
Receivetab[i] = spi_xfer(SPI_STREAM, 0); //Read data

In SPI, receive data is shifted into the PIC at same time that transmit
data is shifted out. So I don't see the need for two statements above.
You should be able to do it with one spi_xfer() statement. Try the
following code instead:
Code:

for(i=0; i<6; i++)
   {
    Receivetab[i] = spi_xfer(SPI_STREAM, Sendtab[i]);
    delay_us(25);
   }
Guest








PostPosted: Sun Mar 16, 2008 4:38 pm     Reply with quote

I have tried this with different mode, but I still have not luck. Thanks.
boulder



Joined: 15 Mar 2008
Posts: 53

View user's profile Send private message

PostPosted: Sun Mar 16, 2008 4:48 pm     Reply with quote

I am using a compiler, PCM 4.069, it does not have an option, FORCE_HW, for #use spi(). I know that PCM4.023 has this option. Is there anyway I can use #use spi() for hardware SPI without FORCE_HW.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 16, 2008 5:25 pm     Reply with quote

Quote:
I am using a compiler, PCM 4.069, it does not have an option,
FORCE_HW, for #use spi().

Prove it. I compiled a #use spi() statement with FORCE_HW and it
compiles with no problem. The code in the .LST file looks good.
boulder



Joined: 15 Mar 2008
Posts: 53

View user's profile Send private message

PostPosted: Sun Mar 16, 2008 9:33 pm     Reply with quote

Which version of PCM are you using? I just tried it again , PCM_4.069 does not recognize FORCE_HW. And FORCE_HW is not on the list of #use spi in CCS Help. I just bought this version of compiler 3 days ago. Thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 16, 2008 9:57 pm     Reply with quote

Download the CCS manual. Look at page 137 in the Acrobat reader.
This is the section on #use spi. At the bottom of the blue table, it shows
FORCE_HW.
http://www.ccsinfo.com/downloads/CReferenceManual.pdf


Copy and paste the following program into your editor. It should
compile with no errors with vs. 4.069. Notice that it has "MSB_FIRST".
If you leave out that option, it will apparently default to LSB first and
it will not accept the FORCE_HW option. I believe that is what is
happening when you attempt to compile. Try this program instead:
Code:

#include <16F886.h>
#fuses INTRC_IO, NOWDT, PUT, MCLR, NOLVP
#use delay(clock=4000000)
#use spi(MASTER, MODE=0, MSB_FIRST, BITS=8, BAUD=250000, FORCE_HW, ENABLE=PIN_C1, STREAM=SPI_STREAM)   
//===========================================
void main()
{
int8 result;

result = spi_xfer(SPI_STREAM, 0x55);                   

while(1);
}
boulder



Joined: 15 Mar 2008
Posts: 53

View user's profile Send private message

PostPosted: Mon Mar 17, 2008 3:05 pm     Reply with quote

Thanks. I have no problem to compile it now. However, I modified the code a little bit, adding LEDs on my 28-pin demo board, I found out that the code could not get out the step,
Code:
result = spi_xfer(SPI_STREAM, 0x00);

The below is the code.
Code:

#include <16F886.h>
#fuses INTRC_IO, NOWDT, PUT, MCLR, NOLVP
#use delay(clock=4000000)
#use spi(MASTER, MODE=0, MSB_FIRST, BITS=8, BAUD=250000, FORCE_HW, ENABLE=PIN_C1, STREAM=SPI_STREAM)   
//===========================================
void main()
{
 int8 result;

 setup_oscillator( OSC_4MHZ );

 output_high(PIN_B0);                     //LED1

 result = spi_xfer(SPI_STREAM, 0x00);   
 
 output_high(PIN_B3);                    //LED2
           
 while(1);
}

LED1 is on, but LED2 is never on.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 17, 2008 4:23 pm     Reply with quote

Quote:
#use spi(MASTER, MODE=0, MSB_FIRST, BITS=8, BAUD=250000, FORCE_HW, ENABLE=PIN_C1, STREAM=SPI_STREAM)

There is some problem caused by putting the Enable pin on Port C.
Change it to a pin on Port B. Then it should start working.

I'll research this later. I don't have time to find the reason for it
this afternoon. I've got to work on other things.
boulder



Joined: 15 Mar 2008
Posts: 53

View user's profile Send private message

PostPosted: Mon Mar 17, 2008 6:41 pm     Reply with quote

After I changed Enable pin to PIN_B5, the does not get stuck anymore in the step,
Quote:
result = spi_xfer(SPI_STREAM, 0x00)
. But the data I read from slave is 0x00, I expect 0xC1. Also, bit 0 of SSPSTAT is 0, this means SSPBUF is empty, receive not complete.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 17, 2008 8:17 pm     Reply with quote

Do you an 8 MHz crystal (and load capacitors) connected to the
XTAL pins on the MAXQ3180 ?

What is connected to the \Reset pin on the MAXQ3180 ?
The data sheet says you can leave it unconnected. It has an internal
pull-up resistor.

Also, try adding a delay of 100 ms at the start of main(). This will give
the MAXQ3180 time to initialize before you start reading the registers.
Example:

Code:
delay_ms(100);
boulder



Joined: 15 Mar 2008
Posts: 53

View user's profile Send private message

PostPosted: Tue Mar 18, 2008 10:07 am     Reply with quote

Quote:
Do you an 8 MHz crystal (and load capacitors) connected to the
XTAL pins on the MAXQ3180 ?

Yes, there is an 8 MHz crystal and load capacitors.
Quote:
What is connected to the \Reset pin on the MAXQ3180 ?
The data sheet says you can leave it unconnected. It has an internal
pull-up resistor.

You are right, it is connected to a capacitor which is connected to a ground.

I added delay_ms(100) in my code, the read back data is still 0x00.


Thanks.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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