Go Down

Topic: SD examples and chip select definition (Read 6022 times) previous topic - next topic

ymasur

Using a SD card, I want to try the examples given with the libraries. As warning, it's often written "you have to define correctly the CS pin as output, event if it's not used as the CS pin..."
But, in all example sketch, a bad programming usage is used... here the "Files.ino" sketch fragment:
Code: [Select]

  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  pinMode(10, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }

The code above a no chance to be executed correctly, because CS is defined as 10 in pinmode, but as 4 in SD.begin!!
Why not using the correct reference to, set in Sd2Card.h, as SS_PIN in all occurrences? This is more clean and professionnal.
Have a good day,
//Yves
Regards,
// Yves

PaulS

The SS pin referred to in the comment is the SS pin for the Ethernet functionality. The value in the parentheses in the call to SD.begin() is defining which pin is used as the SS pin FOR THE SD CARD.

Different things. The SS pin (pin 10) needs to be defined as an OUTPUT to make SPI work, regardless of whether or not you are using pin 10 as the SS pin for anything.

Quote
The code above a no chance to be executed correctly, because CS is defined as 10 in pinmode, but as 4 in SD.begin!!

Have you actually run the code? What failed to be executed properly? You are talking apples and oranges.

fat16lib

The SD library has a long history and many of the examples are out of date or just plain wrong.

This comment is wrong.
Code: [Select]

  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  pinMode(10, OUTPUT);


The SD library always sets SS high as an output so no code is needed for that purpose.  Here is the code from Sd2Card.cpp in IDE version 1.01.
Code: [Select]

  // SS must be in output mode even it is not chip select
  pinMode(SS_PIN, OUTPUT);
  digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin


Future versions of the SD.h library will use the SPI.h library and it also makes SS as an output.  Here is code from the 1.5 SPI.h library.
Code: [Select]

  // Set SS to high so a connected chip will be "deselected" by default
  digitalWrite(SS, HIGH);

  // When the SS pin is set as OUTPUT, it can be used as
  // a general purpose output port (it doesn't influence
  // SPI operations).
  pinMode(SS, OUTPUT);


Here is the reason you may need to make some pins outputs and high.  If you have more than one device on the SPI bus, you must disable all devices other than the SD by making their chip select pin an output and high.

For the Ethernet shield, pin 10 is chip select for the Ethernet controller and pin 4 is chip select for the SD card.  So you should make pin 10 an output and set it high to disable the Ethernet controller, not because pin 10 is SS.

Much confusion results from the fact that on 328 Arduinos pin 10 is also SS.  On the Mega, people change the 10 to 53, the SS pin for the Mega, and then the SD on the Ethernet shield will not initialize.  The problem is that the Ethernet controller is no longer disabled on the Mega.

For the Ethernet shield you must always make pin 10 an output and high before initializing the SD card.  It has nothing to do with SS.



ninja2

An old thread, but the discussion above is exactly where my concern lies.

After reading up (again) on SPI I'm still not clear on difference between CS_pin and SS_PIN.

I'm using the  MEGA SPI port (50,51,52) to drive a sparkfun microSD shield
The UNO SPI pins 11,12,13 are re-directed in my design.
The CS_pin is on D8, the microSD default (i.e. SD.begin(CS_pin).
I don't define SS_PIN as it is set to pin53 and an output by the SD library (in sd2PinMap.h) automatically for a MEGA. The SD card is functioning correctly.

But I want to use pin 10 for a non-SD related task (backlight on an LCD) but as soon as SD is accessed the backlight fails.

Why is pin 10 unavailable, when the SS_PIN is 53 on MEGA?

thanks

chucktodd

An old thread, but the discussion above is exactly where my concern lies.

After reading up (again) on SPI I'm still not clear on difference between CS_pin and SS_PIN.

I'm using the  MEGA SPI port (50,51,52) to drive a sparkfun microSD shield
The UNO SPI pins 11,12,13 are re-directed in my design.
The CS_pin is on D8, the microSD default (i.e. SD.begin(CS_pin).
I don't define SS_PIN as it is set to pin53 and an output by the SD library (in sd2PinMap.h) automatically for a MEGA. The SD card is functioning correctly.

But I want to use pin 10 for a non-SD related task (backlight on an LCD) but as soon as SD is accessed the backlight fails.

Why is pin 10 unavailable, when the SS_PIN is 53 on MEGA?

thanks
The reason to make the SS pin Output, high has to do with the SPI hardware in the Chip.  if the SS pin is currently INPUT, when you start using the SPI functions the chip goes into SLAVE SPI mode instead MASTER SPI mode.  
The Master SPI device control the Clock. If the chip is in SLAVE SPI mode, The SPI.transfer() function will hang forever waiting for the 'Master' to provide the clock signal.

So anytime you use SPI, pinMode(SS,OUTPUT); must be executed.  The digitaWrite(SS,HIGH); is optional.  Personally I use SS(slave Select) as a CS_pin(chip Select) when ever I can.  That is what SS was to do.
Because you are using SPI Master mode the SS pin must be an output while any SPI transfers are executing.

A typical SPI transfer:
Code: [Select]

// SPI has already been initialzed with bit order, modes

// select specific SPI device, multiple device can be connected to SPI(MOSI,MISO,CLK)
// but each device needs its own SS pin, usually call CS_pin

digitalWrite(CS_pin, LOW); //  CS_pin may equal SS_Pin, this depends on your specific hardware config
uint8_t inbyte = SPI.transfer(outbyte); // send one byte out, receive one byte in
digitalWrite(CS_pin, HIGH);// finished with SPI transfer, de-select device. all done


 

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's.  It adds 1MB of RAM for those projects where 8KB is not enough.

ninja2

Chuck

That all makes sense, but why can't I use pin 10?

Here's a piece of code from sd2Card.h in the SD library:
Code: [Select]
/* SD Chip Select pin
 *
 * Warning if this pin is redefined the hardware SS will pin will be enabled
 * as an output by init().  An avr processor will not function as an SPI
 * master unless SS is set to output mode.
 */
/** The default chip select pin for the SD card is SS. */
uint8_t const  SD_CHIP_SELECT_PIN = SS_PIN;


I read this to say pin 53 on MEGA doubles as SS and CS, unless SD_CHIP_SELECT_PIN is redefined

I'm using Sparkfun microSD with and following:
Code: [Select]
#define CS_pin 8
if (!SD.begin(CS_pin)){
        Serial << "[SD init FAILED]\n";
        SD_OK = false;
        lcd.setCursor(0,1); lcd.print("[SD init FAILED]"); delay(2000);}
  else {root = SD.open("/"); Serial << "[SD OK]\n"; printDirectory(root, 0);}


(note my term CS_pin is not SD_CHIP_SELECT_PIN)

I assume pin 53 is "the hardware SS" and cannot be changed on a MEGA.
I've tested with and without following in my code and it makes no difference to SD functionality
Code: [Select]
# define SS_pin 53
pinMode(SS_pin, OUTPUT);


and either way pin 10 seems to be unavailable for other non-SD tasks.
(again my term SS_pin does not override SS_PIN in the library)

Now I don't bother making pin 53 an output, because it seems to be done for me.

Still not quite adding up!

chucktodd

Chuck

That all makes sense, but why can't I use pin 10?

and either way pin 10 seems to be unavailable for other non-SD tasks.
(again my term SS_pin does not override SS_PIN in the library)

Now I don't bother making pin 53 an output, because it seems to be done for me.

Still not quite adding up!
On the Mega2560, the SS pin is digital pin 53, for SPI to function correctly pinMode(53,OUTPUT); must be executed.  You can use pin 53 for any task as long as it it configured as an OUTPUT.  It can be LOW or HIGH The library does not care.
The SPI Library does two configuration step to the SS pin in SPI.begin();

First it check if SS pin is configured as input if it is an input is turns on the Pullup resister, If the pin is not connected to anything the Pullup resistor pull the pin HIGH.  ( every thing is happy as long as the pin is high).   This configuration work is incase you use the SPI in SLAVE mode, just incase.

The Second thing is it changes the pinMode of SS to output.  It does not change the value(HIGH,LOW) Just forces it to output.  Most people use SPI in Master mode, configuring to work makes peoples live better. 

That is the only time the SPI library messes with  SS.  If later in your program you change pinMode(SS) to INPUT AND use SPI AND SS is LOW the SPI hardware will automagically switch from MASTER Mode to SLAVE Mode and your SKETCH with Hang.

I use SS as a chip select in my latest Kickstarter Project Memory Panes

It works fine.
 
Here is the SPI.begin() function from the latest release.
Code: [Select]

void SPIClass::begin()
{
  uint8_t sreg = SREG;
  noInterrupts(); // Protect from a scheduler and prevent transactionBegin
  if (!initialized) {
    // Set SS to high so a connected chip will be "deselected" by default
    uint8_t port = digitalPinToPort(SS);
    uint8_t bit = digitalPinToBitMask(SS);
    volatile uint8_t *reg = portModeRegister(port);

    // if the SS pin is not already configured as an output
    // then set it high (to enable the internal pull-up resistor)
    if(!(*reg & bit)){
      digitalWrite(SS, HIGH);  ****************** this is where is sets the PULLUP Resistor ON
    }

    // When the SS pin is set as OUTPUT, it can be used as
    // a general purpose output port (it doesn't influence
    // SPI operations).
    pinMode(SS, OUTPUT);  ****************************  This is were is Sets pinMode

    // Warning: if the SS pin ever becomes a LOW INPUT then SPI
    // automatically switches to Slave, so the data direction of
    // the SS pin MUST be kept as OUTPUT.
    SPCR |= _BV(MSTR);
    SPCR |= _BV(SPE);

    // Set direction register for SCK and MOSI pin.
    // MISO pin automatically overrides to INPUT.
    // By doing this AFTER enabling SPI, we avoid accidentally
    // clocking in a single bit since the lines go directly
    // from "input" to SPI control.
    // http://code.google.com/p/arduino/issues/detail?id=888
    pinMode(SCK, OUTPUT);
    pinMode(MOSI, OUTPUT);
  }
  initialized++; // reference count
  SREG = sreg;
}


I don't understand what you meant by:

[quote author=ninja2 link=msg=2279182 date=1434500599

I assume pin 53 is "the hardware SS" and cannot be changed on a MEGA.
I've tested with and without following in my code and it makes no difference to SD functionality
Code: [Select]

# define SS_pin 53
pinMode(SS_pin, OUTPUT);

and either way pin 10 seems to be unavailable for other non-SD tasks.
(again my term SS_pin does not override SS_PIN in the library)

Now I don't bother making pin 53 an output, because it seems to be done for me.
[/quote]

How is pin 10 unavailable for other tasks?

The only way it would be unavailable is if it was used by some hardware.

What do you mean 'pin 10 seems unavailable'? Where is it unavailable?

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's.  It adds 1MB of RAM for those projects where 8KB is not enough.

Go Up