Go Down

Topic: SPI with multiple slaves (why is pin 10 only ss) (Read 63040 times) previous topic - next topic

conor

Nov 26, 2008, 06:13 pm Last Edit: Nov 26, 2008, 06:13 pm by conor Reason: 1
Hello all,

I have a couple of functioning SPI devices (SCP-1000 and Windbond something audio chip). Both work independently of each other however when attempting to integrate them there is a problem. Why on gods green earth can I not use a pin other then pin 10 for the slave select. Is that not the point of SPI to have multiple IC's running on the same bus/clk but activating them with different slave selects.

Precursor:

I have declared my second SS as an output and on a valid digital pin.


Help would be greatly appreciated!

Franklin

So, what happens when you try this? You might have to use a digital pin other than 10 for both devices if 10 is driven by software.
Stephen

conor

Franklin,

Right now I am trying to just get one device to work without using pin 10 as the slave select. When I attempt for example to use pin 9 and plug in the SS line nothing happens. Additionally I am testing on two diecimila boards and a mini with the same result.

Franklin

Which device are you trying? What does your code look like?
Stephen

conor

This is the relevant code for the windbond.
Code: [Select]


//define pins
#define DATAOUT     11   //mosi
#define DATAIN      12   //miso
#define SPICLOCK    13   //sck
#define SS          10 //ss

//opcodes
#define PU          0x01 //need this
#define CLR_INT     0x04 //need this
#define RD_STATUS   0x05 //need this
#define SET_PLAY    0x80 //need this




//Windbond memory locations


int onestart= 20;
int oneend= 26;
int twostart= 27;
int twoend= 32;
int threestart= 33;
int threeend= 38;
int fourstart= 40;
int fourend= 46;
int fivestart= 47;
int fiveend= 53;
int sixstart= 55;
int sixend= 59;
int sevenstart= 60;
int sevenend= 65;
int eightstart= 66;
int eightend= 70;
int ninestart= 71;
int nineend= 77;

int tenstart= 78;
int tenend= 83;
int elevenstart= 84;
int elevenend= 90;
int twelvestart= 91;
int twelveend= 96;
int thirteenstart= 97;
int thirteenend= 104;
int fourteenstart= 105;
int fourteenend= 112;
int fifteenstart= 114;
int fifteenend= 119;
int sixteenstart= 120;
int sixteenend= 125;
int seventeenstart= 126;
int seventeenend= 131;
int eighteenstart= 132;
int eighteenend= 138;
int nineteenstart= 139;
int nineteenend= 146;

int twentystart= 147;
int twentyend= 153;
int thirtystart= 154;
int thirtyend= 161;
int fourtystart= 162;
int fourtyend= 169;
int fiftystart= 170;
int fiftyend= 175;
int sixtystart= 176;
int sixtyend= 181;
int seventystart= 182;
int seventyend= 188;
int eightystart= 189;
int eightyend= 194;
int ninetystart= 195;
int ninetyend= 202;

int Hundredstart= 203;
int Hundredend= 210;

int Your_heartrate_is_start= 213;
int Your_heartrate_is_end= 225;

int Beats_per_minute_start= 226;
int Beats_per_minute_end= 240;

int current_temp_start= 242;
int current_temp_end=254;

int fahrenheit_start=258;
int fahrenheit_end=267;

int hundreds;
int tens;
int ones;

void setup() {

 byte clr;
 pinMode(DATAOUT, OUTPUT);
 pinMode(DATAIN, INPUT);
 pinMode(SPICLOCK,OUTPUT);
 pinMode(SS,OUTPUT);
 delay(100);
 
 digitalWrite(SS,HIGH); //disable device  
 SPCR = B01111111; //data lsb, clock high when idle, samples on falling
 clr=SPSR;
 clr=SPDR;
 delay(10);

 //start serial
 Serial.begin(57600);
 
 Serial.println("Powerup stage");
 digitalWrite(SS,LOW);
 spi_transfer(PU); // power up
 spi_transfer(0x00); // data byte
 digitalWrite(SS,HIGH);
 delay(100);  

 Serial.println("CLR_INT stage");
 digitalWrite(SS,LOW);
 spi_transfer(CLR_INT); // clear interupt and eom bit
 spi_transfer(0x00); // data byte
 digitalWrite(SS,HIGH);
 delay(100);

}


void loop() {



ekg();
}

void ekg(){
 
int heartrate = 23;

hundreds = heartrate/100;
tens = (heartrate/10) % 10;
ones = heartrate % 10;

 playloop(Your_heartrate_is_start,Your_heartrate_is_end);
 Serial.println("Your heartrate is...");
 //delay(1000);



received_hundreds();
 
 if(heartrate >= 100)
 {
 playloop(Hundredstart,Hundredend);
 Serial.println("Hundred");
 //delay(1000);
 }
tens_and_ones_checker();

 playloop(Beats_per_minute_start,Beats_per_minute_end);  
 Serial.println("beats per minute");
 //delay (1000);
   
ready_wait();

//delay (5000);

} //end main_program loop

char playloop(char register_start, char register_end)
{
   digitalWrite(SS,LOW); //Select SPI Device
   spi_transfer(SET_PLAY);
   spi_transfer(0);
   Serial.println("one - tested with playloop");
   spi_transfer(register_start%256); //Write byte to device
   spi_transfer((int)register_start/256);
   spi_transfer(register_end);
   spi_transfer((int)register_end/256);
   spi_transfer(0x00); //Send nothing, but we should get back the register value
   digitalWrite(SS,HIGH);
   delay(10);
 }




The sketch works fine with the SS defined on pin 10. However changing it to any other pin causes it to cease working.






kg4wsv

#5
Nov 26, 2008, 08:54 pm Last Edit: Nov 26, 2008, 08:56 pm by kg4wsv Reason: 1
I think the SS designation is for when the ATmega is the slave being selected.  I have used multiple devices with different vanilla digital outputs as SS with no problems at all.

A correctly designed SPI peripheral is required to put its output line (usually designated MISO, SO, or SDO) in a high impedance (hi-Z) state when the slave select is inactive. Some devices do not behave well and drive their output pin all the time, which precludes sharing the SPI bus as intended.

-j


fdufnews

In ATmega datasheet it is said that SS pin is only used while the processor is in slave mode. In that case when SS is driven low by an external master it puts MISO and SCLK in high Z. When the ATmega acts as a master there is no automatic management of the SS pin and the software manages the SS pin itself or any other one used as a Slave Select

conor

J and fdufnews, this makes sense however does not explain why only pin 10 is usable to drive my slave devices. I have probed the system while operating on both pin 10 and pin 9 as CS's. When testing with pin 10 as SS it initializes high when I digitalWrite, goes low to activate the slave and then back high once the communication is done. Pin 9 on the other initializes high, goes low once and then stays there. The only difference between the two tests is declaring #define SS 9 instead of 10 and moving the wire from 10 to 9. Hope this helps.

kg4wsv

Not sure what to tell you, except maybe examine your hookups very carefully.  I have followed the procedure you describe several times with 100% success.

-j


nkcelectronics

#9
Apr 15, 2009, 06:30 am Last Edit: Apr 15, 2009, 06:34 am by nkcelectronics Reason: 1
I found the answer to this mystery.  You need to set the physical SS pin to HIGH before setting the Arduino in SPI Master mode, and SS is physically wired to pin 10.  Once you set it in Master Mode, you can use pin 10 for other uses.  It is explained for a specific case and problem I had with the Arduino Ethernet Shield, while trying to make it work for the Arduino MEGA: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1239058804/0

In your code:
Code: [Select]
 
 digitalWrite(SS,HIGH); //disable device  
 SPCR = B01111111; //data lsb, clock high when idle, samples on falling


When SS is 9, you need to add the following:
Code: [Select]
 
 digitalWrite(SS,HIGH); //disable device
 digitalWrite(10, HIGH); //physical SS pin high before setting SPCR  
 SPCR = B01111111; //data lsb, clock high when idle, samples on falling

captnKrunch

That's insightful but I don't understand.  Using the SPI library, the SS_PIN is DEFINEd in the .h file.  Under this rule, how does one put multiple devices on the spi bus?  That is, each device will require its own select pin.  The library code doesn't manipulate the SS_PIN during transfers?  Is there any significant documentation on the spi library member someplace?  Thanks in advance.

scswift

I would like to know the answer to what captnkrunch asked as well.

davekw7x

#12
Oct 11, 2010, 03:31 pm Last Edit: Oct 11, 2010, 07:23 pm by davekw7x Reason: 1
@scswift:
Quote
I would like to know...


See the following more recent thread: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1284605439/6

Scroll down to post number 7.

I tried to explain the difference between the use of "SS" to set the mode of the SPI hardware interface (this pin can't be changed) and the use of pin 10 as a device "Chip Select" that is manipulated during SPI port data transfers (this pin can be any output pin that you want it to be).  Software must explicitly manipulate the device "Chip Select" pin to perform SPI data I/O cycles.  This is done for us in the Ethernet library, which uses Pin 10 as the Ethernet Chip Select.

Bottom line: Do not change the definition of SS in the core library header pins_arduino.h.

Either your library or your sketch must set the pin mode of the "SS" pin to be an output.  Your sketch or your library can use any pin you want to be the device Chip Select.  It can be pin 10 or it can be anything you want.  The Ethernet library uses pin 10 as the Ethernet Chip Select, and the user sketch doesn't have to worry about any assignment or Chip Select manipulation.

If you are using something other than pin 10 for your device Chip Select, then your software (the library or your sketch) still must set the the "SS" pin mode to be an output.

For a complete, official explanation see http://www.atmel.com/dyn/resources/prod_documents/doc2585.pdf

Regards,

Dave

Footnote:

For boards using an ATMega1280 or '2560, the actual pin definition of "SS" is not Arduino pin 10; it is something else, as you can see in pins_arduino.h.  By leaving pins_arduino.h unchanged, properly written code (sketches or libraries) can initialize the hardware "SS" pin with the same source code.  Choice of which pin to use for the SPI device Chip Select can still be pin 10 or it can be anything else you want it to be.  The only requirement (for properly designed SPI devices and for properly designed software) is that each device that resides on the Arduino SPI bus must have a different device Chip Select pin.

scswift

Thanks, that explanation cleared up a bunch of things for me.

Go Up