|
|
View previous topic :: View next topic |
Author |
Message |
Paul Raine
Joined: 06 Jun 2006 Posts: 7 Location: UK
|
SPI Slave Select Pin |
Posted: Thu Jun 29, 2006 7:40 am |
|
|
Hi,
Does anyone have any tips on using the Slave Select pin when using SPI comms. If I use a 'soft' chip select, I correctly receive the data sent to the PIC. However, this causes problems with the PIC sending out data when other devices are being addressed becasue the SDO pin is not suppressed. However, when I try and control the PIC using the hardware SS, I don't receive any data. I've read a post that mentions an errata to a PIC highlighting a problem, bit there is nothing in the errata of the PIC I'm using (PIC18F4431). I was originally using I2C, but need higher transfer speeds.
Any help would be appreciated.
Many thanks
Paul |
|
|
epideath
Joined: 07 Jun 2006 Posts: 47
|
|
Posted: Thu Jun 29, 2006 8:27 am |
|
|
Do you have RA5 set as input? Is that input also set for digital I/O?
Not sure if that is handled by the spi setup routine.
Regards |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Jun 29, 2006 2:08 pm |
|
|
Quote: |
Does anyone have any tips on using the Slave Select pin when using SPI comms.
|
Not sure what are you asking, pls could be more specific regarding "Slave Select pin"?
Quote: |
However, this causes problems with the PIC sending out data when other devices are being addressed becasue the SDO pin is not suppressed.
|
How are you addressing "other devices"?
Pls could you post a short description of your hardware SPI connections?.
Sorry for any answer...
Humberto |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu Jun 29, 2006 4:29 pm |
|
|
An example program says more than a thousand words....
Right now we have to guess which errors you might have made. Give us a compilable example program and we can tell you where the error is.
Most common errors are:
- Not disabling an internal device sharing the same I/O pin (A/D converter)
- Some chips will configure the pin automatically as input while for other models you have to do it yourself.
- An invalid combination of parameters for the setup_spi() command.
Also tell us your compiler version. |
|
|
Paul Raine
Joined: 06 Jun 2006 Posts: 7 Location: UK
|
|
Posted: Fri Jun 30, 2006 1:41 am |
|
|
The PIC is 1 of 4 slave devices on the SPI bus, controlled by a Coldfire processor. Each device is addressed using an individual chip select line. If I use a software defined pin for selecting the PIC, it receives the data being sent, but clocks out data anytime the bus is active. However, if I use the hardware SS pin, it appears that no data is being received even though I can see data being clocked in using a scope. I have found out that the SS pin has to be taken high between every byte. When I do this, any subsequent data sent from the PIC is the last byte it received, which is correct, as it reamains in the SSPSR. If I maintain the SS pin low whilst all three bytes are sent, the interrupt will trigger once, but the data received is incorrect. Also, no data is clocked out after the first byte.
Regarding the PIN to use, while parts of the data sheet say PIN-RA5 (DS39616B-page 214), other sections say RC6 (DS39616B-page 211). Since data is being transmitted by the PIC (meaning the SDO pin is enabled) , I'm guessing RC6 is the correct pin.
Here is the code that runs the SPI
Code: |
/*****************************************************************************/
/* SPI Interrupt routine
*/
#INT_SSP
void SPIInterrupt()
{
nSPIBuffer[n] = spi_read();
n++;
SSPIF = 0;
}
/*****************************************************************************/
void ConfigureSPI()
{
setup_spi(SPI_SLAVE | SPI_XMIT_L_TO_H );
set_tris_c(0b01111111); // SDO, SS, SCK, SDI, X, X, X, X
}
/*****************************************************************************/
void Main()
{
DeviceConfigure();
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
enable_interrupts(INT_IC2QEI);
printf("\n\rDC Servo Controller V0.6\n\r");
SSPBUF = 0xAA; // Just to check that something comes out
while (1)
{
}
} |
At this stage all I'm trying to do is get 3 bytes into a buffer. However, the interrupt never triggers (tried a breakpoint) and checking n (declared as 0) after the data has been sent shows it to be 0 still. I've also noticed that a while loop waiting for spi_data_is_in() never exits.
Thanks for any help.
Compiler 3.249 |
|
|
Ttelmah Guest
|
|
Posted: Fri Jun 30, 2006 2:44 am |
|
|
On the pin, I'd email Microchip, and get a confirmation. However I think C5 is right. Unfortunately, large lumps of the data sheets are 'cut and paste' productions from other sheets, and occasionally faults like this appear.
On SS having to rise, this is shown in the timing diagrams.
You don't need to clear the interrupt flag yourself in the routine. This is already done for you by the compiler. If you don't want the compiler to do this, add 'noclear' to the interrupt declaration.
You are setting which edge the slave has to transmit it's reply, but not which edge it expects to 'read' on, and which is the 'idle' polarity (SPI_L_TO_H or SPI_H_TO_L). It sounds as though this may be 'defaulting' to the correct value, but probably safer to be explicit, and set it.
Though I prefer to use the CCS routines if possible, you may be running into a problem with them. Historically, their read and write functions for both SPI, and I2C, appear to be orientated more towards software polling, rather than an interrupt driven approach. My 'suspicion', is that the read routine polls before actually fetching the data. If the SS pin is held low, the interrupt doesn't occur, while if it returns high, it'll then probably be high once you enter the interrupt routine itself, and then the code may hang...
I'd try modifying the interrupt routine with:
Code: |
#DEFINE READ_SSP() (SSPBUF)
#byte SSPBUF = 0xFC9
/*****************************************************************************/
/* SPI Interrupt routine
*/
#INT_SSP
void SPIInterrupt()
{
nSPIBuffer[n] = READ_SSP();
n++;
}
|
and add either SPI_L_TO_H, or SPI_H_TO_L, to the setup line, to ensure that the slave is reading the data on the right edge, and see if things improve.
Best Wishes |
|
|
Paul Raine
Joined: 06 Jun 2006 Posts: 7 Location: UK
|
|
Posted: Fri Jun 30, 2006 4:11 am |
|
|
Thanks for your responses. I've distilled the code down to the bare minimum to try and remove any possible interactions with other functions. Basically, if I use SPI_SS_DISABLED, the code receives the data and if I remove this command then it doesn't. I'm assuming that since data is received with SS disabled, my clock polarities and edges are correct.
Code: | #include <18F4431.h>
#USE delay (clock=40000000) // 40MHz Clock
#FUSES HS,NOBROWNOUT,NOPROTECT,PUT,NOLVP,WDT128,NOWDT
#use RS232 (BAUD=19200, XMIT=PIN_C3, RCV=PIN_C2, PARITY=N, BITS=8)
/* Defines */
/* I2C/SPI Commands */
#define RESET (0xAA)
#define SET_PWM (0x01)
#define GET_POSITION (0x02)
#define GET_STATUS (0x03)
#define SET_TRIGGER_POINT (0x04)
#define SERVO_CONTROL (0x05)
#byte SSPBUF = 0xFC9
/* Global Variables */
int8 nSPIData;
boolean bDataIn = false;
/*****************************************************************************/
/* SPI Interrupt routine
*/
#INT_SSP
void SPIInterrupt()
{
nSPIData = SSPBUF;
bDataIn = true;
}
/*****************************************************************************/
void Main()
{
//setup_spi(SPI_SLAVE | SPI_XMIT_L_TO_H | SPI_SS_DISABLED ); // WORKS
setup_spi(SPI_SLAVE | SPI_XMIT_L_TO_H ); // DOES NOT WORK
set_tris_c(0b01111111); // SDO, SS, SCK, SDI, X, X, X, X
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
printf("\n\rSPI TEST V0.1\n\r");
while (1)
{
if (bDataIn == true)
{
printf("%u\n\r",nSPIData);
bDataIn = false;
}
}
} |
The following is taken from DS39616B-page 214: -
Quote: | When the SPI is in Slave mode with SS
pin control enabled (SSPCON<3:0> =
0100), the SPI module will reset if the SS
pin is set to VDD. |
Could it be that the SS pin going high resets the module before the interrupt flag is set? I've exceeded the minimum time needed between the last clock pulse and SS going high, but the interrupt does trigger if I send 2 bytes with the SS held low for the entire duration (even though the data received is wrong) therefore giving the module more time to resond.
Has anyone else successfully used the SS pin on an 18F4431?
I've also got a ticket with Microchip with this issue to see what they suggest.
Thanks again. |
|
|
Ttelmah Guest
|
|
Posted: Fri Jun 30, 2006 5:55 am |
|
|
Try an experiment with your transmitter.
Drop SS, send the byte, then wait for the actual transmission to occur (depends on your SPI clock rate), then wait another 20uSec, raise SS, and loop round to send the next byte.
Two possibilities wold seemto exist. One is SS low for the whole duration of the byte clocking out (data sheet shows this, and makes no mention of what would happen if it raised before the byte was complete, except the comment you quote about the hardware SPI being reset...). The second is, what happens if the SS line goes high before the data is actually 'read'. It will take about 3 to 4uSec, after the last clock edge, before the handler actually retrieves the byte..
Best Wishes |
|
|
Paul Raine
Joined: 06 Jun 2006 Posts: 7 Location: UK
|
|
Posted: Mon Jul 03, 2006 1:02 am |
|
|
After more testing into the problem, and hunting around the Microchip website, I've come to the conclusion that the problem is hardware and nothing to do with software. Microchip errata "SSP Module Silicon/Data Sheet Errata" (DS80132D) mentions the need for a 1K resistor in series with the SS pin, but says this may vary from processor to processor.
I will now be implementing a hardware work-around to get a reliable and repeatable solution.
Once again, thanks for your input. |
|
|
|
|
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
|