|
|
View previous topic :: View next topic |
Author |
Message |
boulder
Joined: 15 Mar 2008 Posts: 53
|
SPI Problem from PIC16F886 to MAXQ3180 |
Posted: Sat Mar 15, 2008 7:56 pm |
|
|
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
|
|
Posted: Sun Mar 16, 2008 8:44 am |
|
|
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
|
|
Posted: Sun Mar 16, 2008 3:09 pm |
|
|
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
|
|
Posted: Sun Mar 16, 2008 4:11 pm |
|
|
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
|
|
Posted: Sun Mar 16, 2008 4:30 pm |
|
|
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
|
|
Posted: Sun Mar 16, 2008 4:38 pm |
|
|
I have tried this with different mode, but I still have not luck. Thanks. |
|
|
boulder
Joined: 15 Mar 2008 Posts: 53
|
|
Posted: Sun Mar 16, 2008 4:48 pm |
|
|
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
|
|
Posted: Sun Mar 16, 2008 5:25 pm |
|
|
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
|
|
Posted: Sun Mar 16, 2008 9:33 pm |
|
|
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
|
|
Posted: Sun Mar 16, 2008 9:57 pm |
|
|
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
|
|
Posted: Mon Mar 17, 2008 3:05 pm |
|
|
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
|
|
Posted: Mon Mar 17, 2008 4:23 pm |
|
|
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
|
|
Posted: Mon Mar 17, 2008 6:41 pm |
|
|
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
|
|
Posted: Mon Mar 17, 2008 8:17 pm |
|
|
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:
|
|
|
boulder
Joined: 15 Mar 2008 Posts: 53
|
|
Posted: Tue Mar 18, 2008 10:07 am |
|
|
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. |
|
|
|
|
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
|