## Problem interfacing SD card with ATmega32

9 posts / 0 new
Author
Message

Hello guys, until now this forum has helped me a lot in learning avr programming but i am stuck at interfacing SD card with ATmega32.
here is my code which is very simple.

I have initialized SPI and its settings are working good because i tested it on proteus using two ATmega32's. One has the code to send data through SPI, second has the code to read that data and display it on PORTC.

Now i have to initialize SD card. I am learning it all by myself so after reading couple of datasheets and tutorials here is my conclusion on how to initialize SD card:

1: Set SS' to 1
since its active low i tried to set it 0 as well still does not works

2: Send 80 Clock pulses
Now i really dont know what this means but i saw in a code that a guy simply send 0xFF, 10 times. So i am doing it as well still i dont have explanation for this

3: Set SS' to 0

4: Send 16 more clock pulses
i did it same way as previously.

5: Check for any errors
I think this is where the actual problem comes in, to check for errors i call my read function. This function initializes the SPI in read mode and reads the data through SPDR and later save it in variable recdata. Now when i put the value of recdata on PORTC, i get a 0xFF on portC.

6th step say to keep sending CMD1 until 0x01 is received, i have tried that as well but its not working either.

note 1: The .mmc i am using for simulation is a simple blank text file.
note 2: I have double checked the frequencies and it seems to be ok.

Would someone be kind enough to tell me which part am i doing wrong?

/*SD CARD INTERFACE*/

#include
#define F_CPU 6400000
#include

#define SS PB4
#define MOSI PB5
#define MISO PB6
#define SCK PB7

unsigned char recdata;
unsigned char temp=0;

int main(void)
{
DDRA=0xFF;
DDRD=0xFF;
DDRC=0xFF;
char a=0x01;

init();
}

void write(char data)
{

DDRB = (1<<MOSI)|(1<<SCK)|(1<<SS);
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
_delay_ms(20);
SPDR=data;
while(!(SPSR & (1<<SPIF)));
_delay_ms(20);

}

void writes(char *dat)
{
while(*dat)
write(*dat++);
}

{
DDRB = (1<<MISO);
SPCR = (1<<SPE);

while(!(SPSR & (1<<SPIF)));
recdata=SPDR;
_delay_ms(25);
return recdata;
}

void init (void)
{
char i;

PORTB |= (1<<SS);
for(i=0; i < 10; i++)
{
write(0xFF);
}

PORTB &= ~(1<<SS);
for(i=0; i < 2; i++)
{
write(0xFF);
}

write(0xFF);
write(0x40);
write(0x00);
write(0x00);
write(0x00);
write(0x00);
write(0x95);
write(0xFF);
_delay_ms(50);

PORTC=recdata;

}

## Attachment(s):

Quote:

Now i have to initialize SD card. I am learning it all by myself so after reading couple of datasheets and tutorials here is my conclusion on how to initialize SD card:

http://elm-chan.org/docs/mmc/mmc...

The section titled "Initialization Procedure for SPI Mode" then you can see how the author of that article actually implemented it in FatFs. The disk_init function in mmc.c looks like this:

DSTATUS disk_initialize (
BYTE pdrv		/* Physical drive nmuber (0) */
)
{
BYTE n, cmd, ty, ocr[4];

if (pdrv) return STA_NOINIT;		/* Supports only single drive */
power_off();						/* Turn off the socket power to reset the card */
if (Stat & STA_NODISK) return Stat;	/* No card in the socket */
power_on();							/* Turn on the socket power */
FCLK_SLOW();
for (n = 10; n; n--) xchg_spi(0xFF);	/* 80 dummy clocks */

ty = 0;
if (send_cmd(CMD0, 0) == 1) {			/* Enter Idle state */
Timer1 = 100;						/* Initialization timeout of 1000 msec */
if (send_cmd(CMD8, 0x1AA) == 1) {	/* SDv2? */
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);		/* 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] = xchg_spi(0xFF);
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;	/* SDv2 */
}
}
} else {							/* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1) 	{
ty = CT_SD1; cmd = ACMD41;	/* SDv1 */
} else {
ty = CT_MMC; cmd = CMD1;	/* MMCv3 */
}
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;
deselect();

if (ty) {			/* Initialization succeded */
Stat &= ~STA_NOINIT;		/* Clear STA_NOINIT */
FCLK_FAST();
} else {			/* Initialization failed */
power_off();
}

return Stat;
}

The difference between this code and your attempt is that this supports every form of MMC, SD, SDHC card available. This is one of the many reasons most people here don't try to write direct access SD/MMC code but just use FatFs.

Apart from anything else, if you manage to initialize it how are you going to read a "file" from it. Say there's a file called \some\path\to\readme.txt how do you located and then read that file?

FatFs can do all this for you (and all other filing operations like change directory, rename, reformat even).

Even if you don't want (FAT32) file level access to the data on the card the three core routines in mmc.c: disk_initialize(), disk_read() and disk_write() should give you low level access to read/write sectors.

clawson wrote:
Quote:

Now i have to initialize SD card. I am learning it all by myself so after reading couple of datasheets and tutorials here is my conclusion on how to initialize SD card:

http://elm-chan.org/docs/mmc/mmc...

The section titled "Initialization Procedure for SPI Mode" then you can see how the author of that article actually implemented it in FatFs. The disk_init function in mmc.c looks like this:

DSTATUS disk_initialize (
BYTE pdrv		/* Physical drive nmuber (0) */
)
{
BYTE n, cmd, ty, ocr[4];

if (pdrv) return STA_NOINIT;		/* Supports only single drive */
power_off();						/* Turn off the socket power to reset the card */
if (Stat & STA_NODISK) return Stat;	/* No card in the socket */
power_on();							/* Turn on the socket power */
FCLK_SLOW();
for (n = 10; n; n--) xchg_spi(0xFF);	/* 80 dummy clocks */

ty = 0;
if (send_cmd(CMD0, 0) == 1) {			/* Enter Idle state */
Timer1 = 100;						/* Initialization timeout of 1000 msec */
if (send_cmd(CMD8, 0x1AA) == 1) {	/* SDv2? */
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);		/* 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] = xchg_spi(0xFF);
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;	/* SDv2 */
}
}
} else {							/* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1) 	{
ty = CT_SD1; cmd = ACMD41;	/* SDv1 */
} else {
ty = CT_MMC; cmd = CMD1;	/* MMCv3 */
}
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;
deselect();

if (ty) {			/* Initialization succeded */
Stat &= ~STA_NOINIT;		/* Clear STA_NOINIT */
FCLK_FAST();
} else {			/* Initialization failed */
power_off();
}

return Stat;
}

The difference between this code and your attempt is that this supports every form of MMC, SD, SDHC card available. This is one of the many reasons most people here don't try to write direct access SD/MMC code but just use FatFs.

Apart from anything else, if you manage to initialize it how are you going to read a "file" from it. Say there's a file called \some\path\to\readme.txt how do you located and then read that file?

FatFs can do all this for you (and all other filing operations like change directory, rename, reformat even).

Even if you don't want (FAT32) file level access to the data on the card the three core routines in mmc.c: disk_initialize(), disk_read() and disk_write() should give you low level access to read/write sectors.

Thankyou for the response, well i have initialized the card but now i am having issues with WRITE BLOCK sequence.. it seems this direct programming is not going to take me anywhere and i must use FATfs.

Can you link me to the lastest version of this library? and do i need to edit it as i read in a tutorial which modified this library?

Google FatFs - what is the first hit?

Also, there are two tutorials in that forum on how to setup FATFS with AVRs.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

indianajones11 wrote:
Also, there are two tutorials in that forum on how to setup FATFS with AVRs.

thankyou one i have already read. but since its written in 2009 and now a far newer version of FATFS is released i am having a hard time modifying it.. Will search for the other one now

This is the one i found: https://www.avrfreaks.net/index.p...

Can you link me to the other one? i am unable to find it in search

http://elm-chan.org/fsw/ff/00ind...

Ross McKenzie ValuSoft Melbourne Australia

HellsGuardian wrote:
Can you link me to the other one? i am unable to find it in search

Go to the tutorial forum and enter "fatfs" in search at the bottom of the page.It's the one by thelorax and for a mega32 too. I would think the basics of getting FATFS running,using either tut., would still apply even with newer versions.

Edit: Moderators, the link to thelorax code now has a 404 error and is no longer available. Too bad there's no way to save a website page that has good/great info on it, if it ever goes down... :cry:

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1