cancel
Showing results for 
Search instead for 
Did you mean: 

Cannot get SPI communication with SD Card to work (but works on arduino)

estedebain
Associate

Hi everyone,

I'm trying to interface an SD card over SPI with an STM32F411. However, I cannot even initialize it. My current sequence is:

  1. Wait 20 ms after power-on.

  2. Send 10 clock cycles with CS high.

  3. Pull CS low and send CMD0 and wait for a reponse.

Instead, I only ever receive 0xFF instead of 0x01.

My SPI configuration looks like this:

estedebain_0-1756815049274.png

Here is the relevant code:

    MY_DEBUG_PRINTLN("Hello World");

    uint8_t txBuf[6];
    uint8_t resp = 0x00;
    uint8_t dummy = 0xFF;

    HAL_Delay(20);

    MY_DEBUG_PRINT("Raw SD SPI test:\n");

    // send 80 clocks with CS high
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
    for (int i = 0; i < 10; i++) {
        HAL_SPI_Transmit(&hspi2, &dummy, 1, HAL_MAX_DELAY);
    }
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);

    // CMD0 frame
    txBuf[0] = 0x40;
    txBuf[1] = 0x00;
    txBuf[2] = 0x00;
    txBuf[3] = 0x00;
    txBuf[4] = 0x00;
    txBuf[5] = 0x95;

    // send command
    HAL_SPI_Transmit(&hspi2, txBuf, 6, HAL_MAX_DELAY);

    // wait for response
    for (int i = 0; i < 30; i++) {
        HAL_SPI_TransmitReceive(&hspi2, &dummy, &resp, 1, HAL_MAX_DELAY);
        MY_DEBUG_PRINTF("resp = 0x%02X\r\n", resp);
        if ((resp & 0x80) == 0) break;
    }

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);

    MY_DEBUG_PRINTF("CMD0 resp = 0x%02X\r\n", resp);

Output:
Hello World
Raw SD SPI test:
resp = 0xFF

... (30 times)

resp = 0xFF

CMD0 resp = 0xFF

 

On arduino if I execute the "same" code it works:

  Serial.begin(115200);
  while (!Serial) {}

  Serial.println("Hello World");

  uint8_t txBuf[6];
  uint8_t resp = 0x00;
  uint8_t dummy = 0xFF;

  // SPI init
  SPI.begin();
  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE0));

  pinMode(SD_CS_PIN, OUTPUT);
  digitalWrite(SD_CS_PIN, HIGH);

  delay(20);

  Serial.println("Raw SD SPI test:");

  // send 80 clocks with CS high
  for (int i = 0; i < 10; i++) {
    SPI.transfer(dummy);
  }

  digitalWrite(SD_CS_PIN, LOW);

  // CMD0 frame
  txBuf[0] = 0x40; 
  txBuf[1] = 0x00;
  txBuf[2] = 0x00;
  txBuf[3] = 0x00;
  txBuf[4] = 0x00;
  txBuf[5] = 0x95;

  // send the command frame
  for (int i = 0; i < 6; i++) {
    SPI.transfer(txBuf[i]);
  }

  // wait for response (max 30 tries)
  for (int i = 0; i < 30; i++) {
    resp = SPI.transfer(dummy);
    Serial.print("resp = 0x");
    Serial.println(resp, HEX);
    if ((resp & 0x80) == 0) break;
  }

  digitalWrite(SD_CS_PIN, HIGH); 
  SPI.transfer(dummy);           

  Serial.print("CMD0 resp = 0x");
  Serial.println(resp, HEX);

  SPI.endTransaction();

Output is:

Hello World
Raw SD SPI test:
resp = 0xFF
resp = 0x1
CMD0 resp = 0x1

 

I am running out of Ideas :(.

1 ACCEPTED SOLUTION

Accepted Solutions

Hello Saket_om,

So in the end it randomly started working, after connecting it to an oscilloscope, the signals look similar. Maybe some jumper cable was broken? 

Thank you!

View solution in original post

2 REPLIES 2
Saket_Om
ST Employee

Hello @estedebain 

Did you try to check what happening on the bus using logic analyser? Is the SPI sending the CMD?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

Hello Saket_om,

So in the end it randomly started working, after connecting it to an oscilloscope, the signals look similar. Maybe some jumper cable was broken? 

Thank you!