I'm using SPI to interface with a micro SD card 2GB and get error respond in CMD16 response and also CMD17 response. Because of that, I can't also read bytes from SD card. Here is my code:
SD card Initialize function:
uint8_t SDCard_Initialize(void) {
uint8_t i;
//Send 80 pulses to active SD card
for(i = 0; i < 10; i++)
SPI_ByteTransfer(0xFF); //Each byte send = 8 pulses
GPIO_SPI->BRR = GPIO_CS; //Enable SD card CS pin
SDCard_SendCommand(CMD0, 0, 0x4A); //SD card go to Idle state
if(!SDCard_CheckRespond(0x01))
return 1; //Error code 1
for(i = 0; i < 10; i++) {
SDCard_SendCommand(CMD1, 0, 0xFF); //SD card active operations
if(SDCard_CheckRespond(0x00))
break;
}
if(i == 10)
return 2; //Error code 2
SDCard_SendCommand(CMD16, 512, 0xFF); //SD card active operations
if(!SDCard_CheckRespond(0x00))
return 3;
GPIO_SPI->BSRR = GPIO_CS; //Disable SD card CS pin
return 0;
}
SD Card send command function:
void SDCard_SendCommand(uint8_t cmd, uint32_t arg, uint8_t crc) {
uint8_t temp;
int8_t i;
SPI_ByteTransfer(cmd | 0x40); //Transmit 6bit command, transmission and start bit first
for(i = 3; i >= 0; i--) { //Transmit 32bit argument
temp = (arg >> (8 * i)) & 0x000000FF;
SPI_ByteTransfer(temp);
}
SPI_ByteTransfer((crc << 1) | 0x01); //Transmit 7bit CRC and stop bit
}
SD Card check respond function:
uint8_t SDCard_CheckRespond(uint8_t res) {
timeout = 0;
Timer_Initialize(3600, 1999); //Set timer trigger at 100milisecond
while(SPI_ByteTransfer(0xFF) != res) { //Loop until get correct respond or timeout
if(timeout) {
TIM_DeInit(TIM2);
return 0; //Return error if timeout
}
}
TIM_DeInit(TIM2);
SPI_ByteTransfer(0xFF); //Add 8 clock after receive respond
return 1;
}
The response from CMD16 that I got instead of 0x00 really strange: It can't be 0xC0 because the response's MSB in manual must be 0.
FF C0 7F FF FF FF FF FF FF FF
1 Answer 1
I've add 8 clock by sending 0xFF through SPI after receiving respond and now I get the correct respond. Don't add it with read block command, it could flush additional 1 byte from offset.
uint8_t SDCard_Initialize(void) {
uint8_t i;
//Send 80 pulses to active SD card
for(i = 0; i < 10; i++)
SPI_ByteTransfer(0xFF); //Each byte send = 8 pulses
GPIO_SPI->BRR = GPIO_CS; //Enable SD card CS pin
SDCard_SendCommand(CMD0, 0, 0x4A); //SD card go to Idle state
if(!SDCard_CheckRespond(0x01))
return 1; //Error code 1
/* ADD 8 CLOCK AFTER RECEIVE RESPONSE */
**SPI_ByteTransfer(0xFF);**
for(i = 0; i < 10; i++) {
SDCard_SendCommand(CMD1, 0, 0xFF); //SD card active operations
if(SDCard_CheckRespond(0x00))
break;
}
if(i == 10)
return 2; //Error code 2
/* ADD 8 CLOCK AFTER RECEIVE RESPONSE */
**SPI_ByteTransfer(0xFF);**
SDCard_SendCommand(CMD16, 512, 0xFF); //SD card active operations
if(!SDCard_CheckRespond(0x00))
return 3;
/* ADD 8 CLOCK AFTER RECEIVE RESPONSE */
**SPI_ByteTransfer(0xFF);**
GPIO_SPI->BSRR = GPIO_CS; //Disable SD card CS pin
return 0;
}
0x95
. Also, most 2GB cards follow the SD 2.0 standard, which uses different commands in initialization - closer to SDHC cards:CDM0
,CMD8
,ACMD41
. \$\endgroup\$