Sandisk SD card, SPI mode

Status
Not open for further replies.

GoldFish1

Newbie level 1
Joined
Jun 7, 2010
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Lebanon
Activity points
1,324
I want to communicate with a Sandisk SD card from a dsPIC30f4013 via SPI.
So do you have some code i can use?
Is there anything specific to do before reading or writing to a Sandisk?

Currently i'm receiving a response of 0xFF after any command i send, can u tell me what should i do?

This is the code i'm using. I downloaded it from the internet.

void SPIWrite(unsigned char data)
{
// DO NOT WAIT FOR SPITBF TO BE CLEAR HERE
// (for some reason, it doesn't work on this side of the write data).

// Write the data!
SPI1BUF = data;

// Wait until send buffer is ready for more data.
while(SPI1STATbits.SPITBF);
}

unsigned char SPIRead(void)
{
unsigned char data;

if(SPI1STATbits.SPIRBF)
{
// already have some data to return, don't initiate a read
data = SPI1BUF;

SPI1STATbits.SPIROV = 0;
return data;
}

// We don't have any data to read yet, so initiate a read
SPI1BUF = 0xFF; // write dummy data to initiate an SPI read
while(SPI1STATbits.SPITBF); // wait until the data is finished reading
data = SPI1BUF;

SPI1STATbits.SPIROV = 0;
return data;
}

void InitSPI(void)
{
SPI1STAT = 0x8000; // enable SPI port

// set SPI port to slowest setting
// master mode
// 8 bit
// Idle state for Clock is high level
// Primary prescaler 64:1
// Secondary prescaler 8:1
SPI1CON = 0x0060;
}

unsigned char SD_WriteCommand(unsigned char* cmd)
{
unsigned int i;
unsigned char response;
unsigned char savedSD_CS = SD_CS;

// SD Card Command Format
// (from Section 5.2.1 of SanDisk SD Card Product Manual v1.9).
// Frame 7 = 0
// Frame 6 = 1
// Command (6 bits)
// Address (32 bits)
// Frame 0 = 1

// Set the framing bits correctly (never change)
cmd[0] |= (1<<6);
cmd[0] &= ~(1<<7);
cmd[5] |= (1<<0);

for(i = 0; i < 6; ++i)
{
SPIWrite(*cmd);
cmd++;
}

// Wait for the response
i = 0;
do
{
response = SPIRead();

if(i > 100)
{
break;
}
i++;
} while(response == 0xFF);

SD_Disable();

// Following any command, the SD Card needs 8 clocks to finish up its work.
// (from SanDisk SD Card Product Manual v1.9 section 5.1.8)
SPIWrite(0xFF);

SD_CS = savedSD_CS;
return(response);
}

unsigned char InitSD()
{
unsigned int i = 0;
unsigned char status;

// Turn off SD Card
SD_Disable();
SD_PowerOff();

// Wait for power to really go down
for(i = 0; i; i++);
for(i = 0; i; i++);
for(i = 0; i; i++);
for(i = 0; i; i++);

// Turn on SD Card
SD_PowerOn();

// Wait for power to really come up
for(status = 0; status < 10; ++status)
{
for(i = 0; i; i++);
for(i = 0; i; i++);
for(i = 0; i; i++);
for(i = 0; i; i++);
}

// We need to give SD Card about a hundred clock cycles to boot up
for(i = 0; i < 16; ++i)
{
SPIWrite(0xFF); // write dummy data to pump clock signal line
}

SD_Enable();

// This is the only command required to have a valid CRC
// After this command, CRC values are ignore unless explicitly enabled using CMD59
unsigned char CMD0_GO_IDLE_STATE[] = {0x40,0x00,0x00,0x00,0x00,0x95};

// Wait for the SD Card to go into IDLE state
i = 0;
do
{
status = SD_WriteCommand(CMD0_GO_IDLE_STATE);

// fail and return
if(i++ > 50)
{
return 1;
}
} while( status != 0x01 );

// Wait for SD Card to initialize
unsigned char CMD1_SEND_OP_COND[] = {0x41,0x00,0x00,0x00,0x00,0xFF};

i = 0;
do
{
status = SD_WriteCommand(CMD1_SEND_OP_COND);
if(i++ > 50)
{
return 2;
}
} while( (status & R1_IN_IDLE_STATE) != 0 );

// Send CMD55, required to precede all "application specific" commands
unsigned char CMD55_APP_CMD[] = {55,0x00,0x00,0x00,0x00,0xFF};
status = SD_WriteCommand(CMD55_APP_CMD); // Do not check response here

// Send the ACMD41 command to initialize SD Card mode (not supported by MMC cards)
i = 0;
unsigned char ACMD41_SD_SEND_OP_COND[] = {41,0x00,0x00,0x00,0x00,0xFF};
do
{
status = SD_WriteCommand(ACMD41_SD_SEND_OP_COND);
// Might return 0x04 for Invalid Command if MMC card is connected

if(i++ > 50)
{
return 3;
}
} while( (status & R1_IN_IDLE_STATE) != 0 );

// Set the SPI bus to full speed now that SD Card is initialized in SPI mode
SD_Disable();
SPIFastClock();

return 0;
}

// SD Card defaults to 512 byte block size
#define BLOCK_SIZE 512
unsigned char SD_ReadBlock(unsigned long addr, unsigned char *buf)
{
unsigned int i;
unsigned char status;

unsigned char CMD17_READ_SINGLE_BLOCK[] = {17,0x00,0x00,0x00,0x00,0xFF};
CMD17_READ_SINGLE_BLOCK[1] = ((addr & 0xFF000000) >> 24);
CMD17_READ_SINGLE_BLOCK[2] = ((addr & 0x00FF0000) >> 16);
CMD17_READ_SINGLE_BLOCK[3] = ((addr & 0x0000FF00) >> 8);
CMD17_READ_SINGLE_BLOCK[4] = ((addr & 0x000000FF));

SD_Enable();

// Send the read command
status = SD_WriteCommand(CMD17_READ_SINGLE_BLOCK);
if(status != 0)
{
// ABORT: invalid response for read single command
return 1;
}

// Now wait for the "Start Block" token (0xFE)
// (see SanDisk SD Card Product Manual v1.9 section 5.2.4. Data Tokens)
do
{
status = SPIRead();
} while(status != 0xFE);

// Read off all the bytes in the block
for(i = 0; i < BLOCK_SIZE; ++i)
{
status = SPIRead();
*buf = status;
buf++;
}

// Read CRC bytes
status = SPIRead();
status = SPIRead();

SD_Disable();

// Following a read transaction, the SD Card needs 8 clocks after the end
// bit of the last data block to finish up its work.
// (from SanDisk SD Card Product Manual v1.9 section 5.1.8)
SPIWrite(0xFF);

return 0;
}
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…