Skip to main content
Associate
September 2, 2025
Solved

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

  • September 2, 2025
  • 1 reply
  • 314 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 :(.

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?

"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"
estedebainAuthorBest answer
Associate
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!