How should I Write data in a SD memory and read it through SPI ?

Status
Not open for further replies.
there is no help, I need code , I have tried with several ways : I wrote codes according data sheet of PIC but SD didn't response! I wrote codes according code vision example but unfortunately SD didn't response! now,...
 

Code:
portd.f1=0; // CS = 0
spi_write(0xff);  // used in some examples but not required
spi_write(64);    //cmd0
spi_write(0);     //argument
spi_write(0);     //argument
spi_write(0);     //argument
spi_write(0);     //argument
spi_write(149);   //crc valid only for mmc_go_idle_state
for (i=0;i<=8;i++) // 8 (NCR) + 1 (result read) 
{
  result=spi_read(0xff);
  if (result != 0xff) break;
}
portd.f1=1;  // CS = 1
 
Reactions: mf1364

    mf1364

    Points: 2
    Helpful Answer Positive Rating
thx for your great guidance, I had a hard ware problem too, you know, my SD adapter was corrupted ! so I was confusing for two weeks but yesterday I changed that SD adapter with another one and now I can receive response from SD on the oscilloscope :-D and this made a lot of energy for me, and I try to develop the project to next step. so because at last I want to write and read in the SD so I should send CMD1 after CMD0, as you know better than me the correct response for CMD0 is "1" and fortunately I could receive it so after that I sent Cmd1 but unfortunately I didn't receive "0" as response !!!!! do you have any idea ? I am sure there is a problem in my codes because I the hard ware is working for cmd0. could you please do me a favor and check my cods please ?
Code:
// */ ******CMD0 and CMD1****************

char r2=1;
char r1=0;
char bit=0;
char flag1=0;
char debounce = 30;
char count1=0;
unsigned  count=0;
char i=0;
char result;
char result1;
char result58;
char i1=0;






//////////////////////////////////////////6
void  mmccommand(){




delay_ms(1);
portd.f1=1;
   r1=1;
  while(r1<10){
  spi_write(255);
  r1++;

  }


portd.f1=0;
spi_write(64);
spi_write(0);
spi_write(0);
spi_write(0);
spi_write(0);
spi_write(149);                            //crc valid only for mmc_go_idle_state
//


for (i=0;i<=8;i++)
{
  result=spi_read(0xff);
  if (result != 255) break;

}
portd.f1=1;


}
/////////////////////////////////////////////
void  mmccommand1(){
char retry=1;

portd.f1=0;
spi_write(65);
spi_write(0);
spi_write(0);
spi_write(0);
spi_write(0);
spi_write(149);                            //crc valid only for mmc_go_idle_state



for (i=0;i<=8;i++) // 8 (NCR) + 1 (result read)
{
  result1=spi_read(0xff);
  if (result1 !=255) break;

}
portd.f1=1;

}

/////////////////////////////////////////////
void main() {



  Spi_Init_Advanced(MASTER_OSC_DIV64, DATA_SAMPLE_MIDDLE, CLK_IDLE_LOW, LOW_2_HIGH);


  trisd.f1 =0;           //CS
  portd.f1=1;

result=0;
result1=1;

while(1){

   while (result != 1) {
          mmccommand();
          result1=1;
          }

  i1=0;
  if (result==1){
     while(result1!=0) {
     i1++;
     mmccommand1();

     if(i1>125){
     result=0;
     break;
 }
     }
     }


result=0;

}
}
 
Last edited:

The initializations sequences I know don't send CMD1 as second command. As previously mentioned by others, newer implementations are proceeding with CMD8 to detect SDHC cards.
 

The initializations sequences I know don't send CMD1 as second command. As previously mentioned by others, newer implementations are proceeding with CMD8 to detect SDHC cards.

I don't agree with you, according the data sheet, CMD8 is reserved. so that is meaning I can't use it.
 

according the data sheet, CMD8 is reserved. so that is meaning I can't use it.
The purpose of CMD8 has been mentioned multiple times in the discussion. I'm getting tired of repeating the stuff.

The datasheet is a "pre SHDC" one. CMD8 is required if your code wants to handle SDHC cards.
 

The purpose of CMD8 has been mentioned multiple times in the discussion. I'm getting tired of repeating the stuff.

The datasheet is a "pre SHDC" one. CMD8 is required if your code wants to handle SDHC cards.
Thx, cmd8 is using for both micro SD with the capacity of 2G and 8G ? because I am using both of them. could you please give me your datasheet? because It seems that your datasheet is fuller than mine. During this days I have tried several method for bring the SD from Idle state to active state for example while I couldn't reply from cmd1, I sent cmd55 and after that acmd41 but the SD returned illegal responses, I hope with your guidance can develop this step too. waiting for your reply...
 

Unfortunately, I don't have a SD-Card V2 specification including CMD8 and SDHC handling. I learned about it from existing libraries, e.g. the said Microchip application library.
 

Check out this code:
Code:
/*-----------------------------------------------------------------------*/

/* MMCv3/SDv1/SDv2 (in SPI mode) control module  (C)ChaN, 2009           */

/*-----------------------------------------------------------------------*/

/* Only rcvr_spi(), xmit_spi(), disk_timerproc() and some macros         */

/* are platform dependent.                                               */

/*-----------------------------------------------------------------------*/





#include <p24FJ64GA002.h>

#include "diskio.h"







/* Definitions for MMC/SDC command */

#define CMD0	(0x40+0)	/* GO_IDLE_STATE */

#define CMD1	(0x40+1)	/* SEND_OP_COND (MMC) */

#define ACMD41	(0xC0+41)	/* SEND_OP_COND (SDC) */

#define CMD8	(0x40+8)	/* SEND_IF_COND */

#define CMD9	(0x40+9)	/* SEND_CSD */

#define CMD10	(0x40+10)	/* SEND_CID */

#define CMD12	(0x40+12)	/* STOP_TRANSMISSION */

#define ACMD13	(0xC0+13)	/* SD_STATUS (SDC) */

#define CMD16	(0x40+16)	/* SET_BLOCKLEN */

#define CMD17	(0x40+17)	/* READ_SINGLE_BLOCK */

#define CMD18	(0x40+18)	/* READ_MULTIPLE_BLOCK */

#define CMD23	(0x40+23)	/* SET_BLOCK_COUNT (MMC) */

#define ACMD23	(0xC0+23)	/* SET_WR_BLK_ERASE_COUNT (SDC) */

#define CMD24	(0x40+24)	/* WRITE_BLOCK */

#define CMD25	(0x40+25)	/* WRITE_MULTIPLE_BLOCK */

#define CMD55	(0x40+55)	/* APP_CMD */

#define CMD58	(0x40+58)	/* READ_OCR */





/* Port Controls  (Platform dependent) */

#define SELECT()	 _LATB15 = 0	/* MMC CS = L */

#define DESELECT() _LATB15 = 1	/* MMC CS = H */



#define SOCKPORT	PORTB		/* Socket contact port */

#define SOCKWP	(1<<10)			/* Write protect switch (RB10) */

#define SOCKINS	(1<<11)			/* Card detect switch (RB11) */



#define	FCLK_SLOW()				/* Set slow clock (100k-400k) */

#define	FCLK_FAST()				/* Set fast clock (depends on the CSD) */







/*--------------------------------------------------------------------------



   Module Private Functions



---------------------------------------------------------------------------*/



static volatile

DSTATUS Stat = STA_NOINIT;	/* Disk status */



static volatile

UINT Timer1, Timer2;		/* 1000Hz decrement timer */



static

UINT CardType;







/*-----------------------------------------------------------------------*/

/* Exchange a byte between PIC and MMC via SPI  (Platform dependent)     */

/*-----------------------------------------------------------------------*/



#define xmit_spi(dat) 	xchg_spi(dat)

#define rcvr_spi()	xchg_spi(0xFF)

#define rcvr_spi_m(p)	SPI1BUF = 0xFF; while (!_SPIRBF); *(p) = (BYTE)SPI1BUF;



static

BYTE xchg_spi (BYTE dat)

{

	SPI1BUF = dat;

	while (!_SPIRBF);

	return (BYTE)SPI1BUF;

}





/*-----------------------------------------------------------------------*/

/* Wait for card ready                                                   */

/*-----------------------------------------------------------------------*/



static

BYTE wait_ready (void)

{

	BYTE res;





	Timer2 = 500;	/* Wait for ready in timeout of 500ms */

	rcvr_spi();

	do

		res = rcvr_spi();

	while ((res != 0xFF) && Timer2);



	return res;

}







/*-----------------------------------------------------------------------*/

/* Deselect the card and release SPI bus                                 */

/*-----------------------------------------------------------------------*/



static

void release_spi (void)

{

	DESELECT();

	rcvr_spi();

}







/*-----------------------------------------------------------------------*/

/* Power Control  (Platform dependent)                                   */

/*-----------------------------------------------------------------------*/

/* When the target system does not support socket power control, there   */

/* is nothing to do in these functions and chk_power always returns 1.   */



static

void power_on (void)

{

							/* Enable SPI1 */

	SPI1CON1 = 0x013B;

	SPI1CON2 = 0x0000;

	_SPIEN = 1;

}



static

void power_off (void)

{

	SELECT();				/* Wait for card ready */

	wait_ready();

	release_spi();



	_SPIEN = 0;				/* Disable SPI1 */



	Stat |= STA_NOINIT;		/* Set STA_NOINIT */

}







/*-----------------------------------------------------------------------*/

/* Receive a data packet from MMC                                        */

/*-----------------------------------------------------------------------*/



static

BOOL rcvr_datablock (

	BYTE *buff,			/* Data buffer to store received data */

	UINT btr				/* Byte count (must be multiple of 4) */

)

{

	BYTE token;





	Timer1 = 100;

	do {								/* Wait for data packet in timeout of 100ms */

		token = rcvr_spi();

	} while ((token == 0xFF) && Timer1);



	if(token != 0xFE) return FALSE;		/* If not valid data token, retutn with error */



	do {								/* Receive the data block into buffer */

		rcvr_spi_m(buff++);

		rcvr_spi_m(buff++);

		rcvr_spi_m(buff++);

		rcvr_spi_m(buff++);

	} while (btr -= 4);

	rcvr_spi();						/* Discard CRC */

	rcvr_spi();



	return TRUE;						/* Return with success */

}







/*-----------------------------------------------------------------------*/

/* Send a data packet to MMC                                             */

/*-----------------------------------------------------------------------*/



#if _READONLY == 0

static

BOOL xmit_datablock (

	const BYTE *buff,		/* 512 byte data block to be transmitted */

	BYTE token			/* Data/Stop token */

)

{

	BYTE resp;

	UINT bc = 512;





	if (wait_ready() != 0xFF) return FALSE;



	xmit_spi(token);			/* Xmit data token */

	if (token != 0xFD) {	/* Is data token */

		do {						/* Xmit the 512 byte data block to MMC */

			xmit_spi(*buff++);

			xmit_spi(*buff++);

		} while (bc -= 2);

		xmit_spi(0xFF);				/* CRC (Dummy) */

		xmit_spi(0xFF);

		resp = rcvr_spi();			/* Receive data response */

		if ((resp & 0x1F) != 0x05)	/* If not accepted, return with error */

			return FALSE;

	}



	return TRUE;

}

#endif	/* _READONLY */







/*-----------------------------------------------------------------------*/

/* Send a command packet to MMC                                          */

/*-----------------------------------------------------------------------*/



static

BYTE send_cmd (

	BYTE cmd,		/* Command byte */

	DWORD arg		/* Argument */

)

{

	BYTE n, res;





	if (cmd & 0x80) {	/* ACMD<n> is the command sequense of CMD55-CMD<n> */

		cmd &= 0x7F;

		res = send_cmd(CMD55, 0);

		if (res > 1) return res;

	}



	/* Select the card and wait for ready */

	DESELECT();

	SELECT();

	if (wait_ready() != 0xFF) return 0xFF;



	/* Send command packet */

	xmit_spi(cmd);						/* Start + Command index */

	xmit_spi((BYTE)(arg >> 24));		/* Argument[31..24] */

	xmit_spi((BYTE)(arg >> 16));		/* Argument[23..16] */

	xmit_spi((BYTE)(arg >> 8));			/* Argument[15..8] */

	xmit_spi((BYTE)arg);				/* Argument[7..0] */

	n = 0x01;							/* Dummy CRC + Stop */

	if (cmd == CMD0) n = 0x95;			/* Valid CRC for CMD0(0) */

	if (cmd == CMD8) n = 0x87;			/* Valid CRC for CMD8(0x1AA) */

	xmit_spi(n);



	/* Receive command response */

	if (cmd == CMD12) rcvr_spi();		/* Skip a stuff byte when stop reading */

	n = 10;								/* Wait for a valid response in timeout of 10 attempts */

	do

		res = rcvr_spi();

	while ((res & 0x80) && --n);



	return res;			/* Return with the response value */

}







/*--------------------------------------------------------------------------



   Public Functions



---------------------------------------------------------------------------*/





/*-----------------------------------------------------------------------*/

/* Initialize Disk Drive                                                 */

/*-----------------------------------------------------------------------*/



DSTATUS disk_initialize (

	BYTE drv		/* Physical drive nmuber (0) */

)

{

	BYTE n, cmd, ty, ocr[4];





	if (drv) return STA_NOINIT;			/* Supports only single drive */

	if (Stat & STA_NODISK) return Stat;	/* No card in the socket */



	power_on();							/* Force socket power on */

	FCLK_SLOW();

	for (n = 10; n; n--) rcvr_spi();	/* 80 dummy clocks */



	ty = 0;

	if (send_cmd(CMD0, 0) == 1) {			/* Enter Idle state */

		Timer1 = 1000;						/* Initialization timeout of 1000 msec */

		if (send_cmd(CMD8, 0x1AA) == 1) {	/* SDHC */

			for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();		/* Get trailing return value of R7 resp */

			if (ocr[2] == 0x01 && ocr[3] == 0xAA) {				/* The card can work at vdd range of 2.7-3.6V */

				while (Timer1 && send_cmd(ACMD41, 1UL << 30));	/* Wait for leaving idle state (ACMD41 with HCS bit) */

				if (Timer1 && send_cmd(CMD58, 0) == 0) {		/* Check CCS bit in the OCR */

					for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();

					ty = (ocr[0] & 0x40) ? CT_SD2|CT_BLOCK : CT_SD2;

				}

			}

		} else {							/* SDSC or MMC */

			if (send_cmd(ACMD41, 0) <= 1) 	{

				ty = CT_SD1; cmd = ACMD41;	/* SDSC */

			} else {

				ty = CT_MMC; cmd = CMD1;	/* MMC */

			}

			while (Timer1 && send_cmd(cmd, 0));			/* Wait for leaving idle state */

			if (!Timer1 || send_cmd(CMD16, 512) != 0)	/* Set R/W block length to 512 */

				ty = 0;

		}

	}

	CardType = ty;

	release_spi();



	if (ty) {			/* Initialization succeded */

		Stat &= ~STA_NOINIT;		/* Clear STA_NOINIT */

		FCLK_FAST();

	} else {			/* Initialization failed */

		power_off();

	}



	return Stat;

}







/*-----------------------------------------------------------------------*/

/* Get Disk Status                                                       */

/*-----------------------------------------------------------------------*/



DSTATUS disk_status (

	BYTE drv		/* Physical drive nmuber (0) */

)

{

	if (drv) return STA_NOINIT;		/* Supports only single drive */

	return Stat;

}







/*-----------------------------------------------------------------------*/

/* Read Sector(s)                                                        */

/*-----------------------------------------------------------------------*/



DRESULT disk_read (

	BYTE drv,			/* Physical drive nmuber (0) */

	BYTE *buff,			/* Pointer to the data buffer to store read data */

	DWORD sector,		/* Start sector number (LBA) */

	BYTE count			/* Sector count (1..255) */

)

{

	if (drv || !count) return RES_PARERR;

	if (Stat & STA_NOINIT) return RES_NOTRDY;



	if (!(CardType & CT_BLOCK)) sector *= 512;	/* Convert to byte address if needed */



	if (count == 1) {	/* Single block read */

		if ((send_cmd(CMD17, sector) == 0)	/* READ_SINGLE_BLOCK */

			&& rcvr_datablock(buff, 512))

			count = 0;

	}

	else {				/* Multiple block read */

		if (send_cmd(CMD18, sector) == 0) {	/* READ_MULTIPLE_BLOCK */

			do {

				if (!rcvr_datablock(buff, 512)) break;

				buff += 512;

			} while (--count);

			send_cmd(CMD12, 0);				/* STOP_TRANSMISSION */

		}

	}

	release_spi();



	return count ? RES_ERROR : RES_OK;

}







/*-----------------------------------------------------------------------*/

/* Write Sector(s)                                                       */

/*-----------------------------------------------------------------------*/



#if _READONLY == 0

DRESULT disk_write (

	BYTE drv,			/* Physical drive nmuber (0) */

	const BYTE *buff,	/* Pointer to the data to be written */

	DWORD sector,		/* Start sector number (LBA) */

	BYTE count			/* Sector count (1..255) */

)

{

	if (drv || !count) return RES_PARERR;

	if (Stat & STA_NOINIT) return RES_NOTRDY;

	if (Stat & STA_PROTECT) return RES_WRPRT;



	if (!(CardType & CT_BLOCK)) sector *= 512;	/* Convert to byte address if needed */



	if (count == 1) {	/* Single block write */

		if ((send_cmd(CMD24, sector) == 0)	/* WRITE_BLOCK */

			&& xmit_datablock(buff, 0xFE))

			count = 0;

	}

	else {				/* Multiple block write */

		if (CardType & CT_SDC) send_cmd(ACMD23, count);

		if (send_cmd(CMD25, sector) == 0) {	/* WRITE_MULTIPLE_BLOCK */

			do {

				if (!xmit_datablock(buff, 0xFC)) break;

				buff += 512;

			} while (--count);

			if (!xmit_datablock(0, 0xFD))	/* STOP_TRAN token */

				count = 1;

		}

	}

	release_spi();



	return count ? RES_ERROR : RES_OK;

}

#endif /* _READONLY */







/*-----------------------------------------------------------------------*/

/* Miscellaneous Functions                                               */

/*-----------------------------------------------------------------------*/



DRESULT disk_ioctl (

	BYTE drv,		/* Physical drive nmuber (0) */

	BYTE ctrl,		/* Control code */

	void *buff		/* Buffer to send/receive data block */

)

{

	DRESULT res;

	BYTE n, csd[16], *ptr = buff;

	DWORD csize;





	if (drv) return RES_PARERR;

	if (Stat & STA_NOINIT) return RES_NOTRDY;



	res = RES_ERROR;

	switch (ctrl) {

		case CTRL_SYNC :	/* Flush dirty buffer if present */

			SELECT();

			if (wait_ready() == 0xFF)

				res = RES_OK;

			break;



		case GET_SECTOR_COUNT :	/* Get number of sectors on the disk (WORD) */

			if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {

				if ((csd[0] >> 6) == 1) {	/* SDC ver 2.00 */

					csize = csd[9] + ((WORD)csd[8] << 8) + 1;

					*(DWORD*)buff = (DWORD)csize << 10;

				} else {					/* MMC or SDC ver 1.XX */

					n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;

					csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;

					*(DWORD*)buff = (DWORD)csize << (n - 9);

				}

				res = RES_OK;

			}

			break;



		case GET_SECTOR_SIZE :	/* Get sectors on the disk (WORD) */

			*(WORD*)buff = 512;

			res = RES_OK;

			break;



		case GET_BLOCK_SIZE :	/* Get erase block size in unit of sectors (DWORD) */

			if (CardType & CT_SD2) {	/* SDC ver 2.00 */

				if (send_cmd(ACMD13, 0) == 0) {		/* Read SD status */

					rcvr_spi();

					if (rcvr_datablock(csd, 16)) {				/* Read partial block */

						for (n = 64 - 16; n; n--) rcvr_spi();	/* Purge trailing data */

						*(DWORD*)buff = 16UL << (csd[10] >> 4);

						res = RES_OK;

					}

				}

			} else {					/* SDC ver 1.XX or MMC */

				if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {	/* Read CSD */

					if (CardType & CT_SD1) {		/* SDC ver 1.XX */

						*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);

					} else {					/* MMC */

						*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);

					}

					res = RES_OK;

				}

			}

			break;



		case MMC_GET_TYPE :		/* Get card type flags (1 byte) */

			*ptr = CardType;

			res = RES_OK;

			break;



		case MMC_GET_CSD :	/* Receive CSD as a data block (16 bytes) */

			if ((send_cmd(CMD9, 0) == 0)	/* READ_CSD */

				&& rcvr_datablock(buff, 16))

				res = RES_OK;

			break;



		case MMC_GET_CID :	/* Receive CID as a data block (16 bytes) */

			if ((send_cmd(CMD10, 0) == 0)	/* READ_CID */

				&& rcvr_datablock(buff, 16))

				res = RES_OK;

			break;



		case MMC_GET_OCR :	/* Receive OCR as an R3 resp (4 bytes) */

			if (send_cmd(CMD58, 0) == 0) {	/* READ_OCR */

				for (n = 0; n < 4; n++)

					*((BYTE*)buff+n) = rcvr_spi();

				res = RES_OK;

			}

			break;



		case MMC_GET_SDSTAT :	/* Receive SD statsu as a data block (64 bytes) */

			if (send_cmd(ACMD13, 0) == 0) {	/* SD_STATUS */

				rcvr_spi();

				if (rcvr_datablock(buff, 64))

					res = RES_OK;

			}

			break;



		default:

			res = RES_PARERR;

	}



	release_spi();



	return res;

}







/*-----------------------------------------------------------------------*/

/* Device Timer Interrupt Procedure  (Platform dependent)                */

/*-----------------------------------------------------------------------*/

/* This function must be called in period of 1ms                         */





void disk_timerproc (void)

{

	static WORD pv;

	WORD p;

	BYTE s;

	UINT n;





	n = Timer1;						/* 1000Hz decrement timer */

	if (n) Timer1 = --n;

	n = Timer2;

	if (n) Timer2 = --n;



	p = pv;

	pv = SOCKPORT & (SOCKWP | SOCKINS);	/* Sample socket switch */



	if (p == pv) {					/* Have contacts stabled? */

		s = Stat;



		if (p & SOCKWP)				/* WP is H (write protected) */

			s |= STA_PROTECT;

		else						/* WP is L (write enabled) */

			s &= ~STA_PROTECT;



		if (p & SOCKINS)			/* INS = H (Socket empty) */

			s |= (STA_NODISK | STA_NOINIT);

		else						/* INS = L (Card inserted) */

			s &= ~STA_NODISK;



		Stat = s;

	}

}
 

Unfortunately, I don't have a SD-Card V2 specification including CMD8 and SDHC handling. I learned about it from existing libraries, e.g. the said Microchip application library.
so how should use cmd8 ? because as you know I should send 4 bytes as a argument and one byte as crc and after that, what SD return as response ?

---------- Post added at 14:28 ---------- Previous post was at 13:27 ----------

thx, for your codes but in frankly speaking I don't have enough knowledge for changing your codes to the acceptable codes for mikroc compiler, and if you have followed the topics you will understand my problem, yes finally I want to read and write into SD but at first I decided to run this project step by step so at first I sent cmd0, and the SD replied me 0x01 as a response and that was correct according the datasheet and after that I should send cmd1 for bring SD from idle sate to active state but the responses were illegal so as you know, others said: use cmd8, but in my datasheet is mentioned that cmd8 is reserved !!! so now I ask you if you can please correct my previous codes or give me codes just bring the SD from ideal state to active state, and ready for writing and reading. If you have a full datasheet of micro SD and SDHC please put the link here.unfortunately in all of my datasheet cmd8 is reserved!!!! meanwhile I have two memory one of them is 2G and one of them is 8G are both of them SDHC ?
 

That is not my code...;-) It is from http://elm-chan.org/fsw/ff/00index_e.html

Any way, I didn't initialized an SD card, I did only MMC. After doing MMC based stuff, I simply tried for SD by some modification in my MMC code, but doesn't worked.. Then I didn't played on it since I don't have enough time...

Also I am not an expert in this topic, but what I tried to provide you is a part of the source code of elm-chan.... If you have enough time to read it, then you may be able to correct your code, I hope so...
 

This short guide tell what to do:
The free "simplified" offcial SD card specification has all necessary information with more details.
 
Thx, I have visited the above website several time but I didn't found any useful part that can help me except the hardware wiring and assembly. if you think I have missed a special part of this website don't hesitate, and just tell me.

---------- Post added at 09:12 ---------- Previous post was at 08:42 ----------

This short guide tell what to do:
The free "simplified" offcial SD card specification has all necessary information with more details.


Thx for the PDF, before I try to download your PDF, i tried cmd1 with a 512Mb capacity and fortunately, the SD returned the legal response "0", now there is a question for me, did I do right ?and just for SDHC I should use CMD8 ? and for SD with capacities below 2G it doesn't need to use CMD8? also after cmd1 I sent cmd59 for turning off The CRC checking to simplify communication, and I received "0" as response, in the following, I sent cmd24 to start writing but unfortunately I didn't receive any response from SD !!! Do you have any suggestion ?
 

I think, I already mentioned earlier that I'm not presently involved in writing low level SD codes because I'm satisfied with the available libraries, e.g. from Microchip. But I try to stay informed to be able to debug the codes.

All recent SD libraries are performing CMD8 after CMD0 to detect SDHC cards. The detection sequence is described in detail in my latest links.
 


Thx, I will try with cmd8 again. please check that am I right? Do SDHC cards involve the cards with capacity more than 2G ?I want to know how would I distinguish that my cards are SD or SDHC ?also am I right ? That the procedure for reading and writing in a card as you said is : CMD0, CMD8, CMD59 for turning off CRC checking, cmd16 for setting block length , and at last using cmd24 for writing in the block ?meanwhile do you think the reply that I got from cmd1 (look my previous comment) for a 512Mb card is correct ? and one question more, what is the response of SD for CMD24?(I didn't find in the datasheet!!)
 
Last edited:

There is no idea?
 

Hi every body, I am using two SD card one of them is 512Mbyte, and the other is 2Gbyte and as you know both of them are SDSC(SD) kind so should have same response but I am so confusing, why they have different response to the same command ? you know I send CMD0 as first command and after that send CMD1 as second command, but why the card with 512Mbyte capacity return 0 as response for CMD1 but the card with 2Gbyte return 1 as response !!!!! does any body have any ideas ? some guys advice me to use cmd8 after cmd0 but cmd8 is using for SDHC with capacity more than 4Gbyte. please reply me as soon as possible
 

Did you notice the possible delay for getting a ready state with CMD1?
 
Did you notice the possible delay for getting a ready state with CMD1?
Thx, that was good point I just put "spi_write(255) between CMD0 and CMD1 and my problem solved and after that I used cmd59 and SD return "0" that is right. and after that I sent cmd24 and the SD return "0" that is right response and after that I sent "254" to understand the SD, that I want to write 512 byte as a sector, and after that I wrote 512bytes, and the SD return "229" that means data is accepted. after that I sent cmd17 for reading this sector and SD returned "0" as response as you know that is right. and after that I expected to receive 254 but I received "255" and "0" do you have any idea ?if you want I can put my codes here
 

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…