Skip to main content
Visitor II
September 2, 2025
Solved

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

  • September 2, 2025
  • 1 reply
  • 313 views

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 :(.

    This topic has been closed for replies.
    Best answer by estedebain

    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!

    1 reply

    Technical Moderator
    September 3, 2025

    Hello @estedebain 

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

    estedebainAuthorAnswer
    Visitor II
    September 3, 2025

    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!