Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

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

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top