Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

SD Card Project

Status
Not open for further replies.
So far i think i got it to Initialize Without no issue.
Once you've got it initialized into SPI mode (meaning your send-command function works properly), the rest is very simple. All the error checking for reads and writes is a good idea, but for now you can simplify a bit and just read and write without all that.
 
Last edited:
omg i think i got it lol. I used the CD (card detect and the 100ms delay) to tell when card is in and delay then initialize the card and write the data then read into buffer and both contained the same data. Does that mean a success ?
 
omg i think i got it lol. I used the CD (card detect and the 100ms delay) to tell when card is in and delay then initialize the card and write the data then read into buffer and both contained the same data. Does that mean a success ?
Most likely. Read sector zero and see if you see the partition table (16 bytes) starting at offset $1be. The rest of that sector will be mostly $00's. Compare with what you would expect to see there. **broken link removed** with the beginnings of what you need to know.
 
how would i read it? What program?

EDIT: here is a dump. Does it look ok? I think i see how it is. But why is it in the begging? I dumped sectors 1.
 

Attachments

  • a.txt
    512 bytes · Views: 180
Last edited:
AtomSoft,

If you have a USB SD card reader, you can read sectors from the SD card with a program called DSKPROBE.EXE

Do a Google search, there should be many sites that offer it for downloading.

I understand that it is included with WindowsXP service pack2, check the support\tools directory.

I looked at your sector dump, it is two series of bytes increasing from 0x00 to 0xFF.

If that is what you wrote to the sector, it must have been a success.

The Master Boot Record is at sector 0.
The sectors from 1 to 63 (or more) are reserved, and usually contain no data, just zeros.
 
Yes that is i think what i wrote since i looped from 0 - 255. 2 times. But why are they so far apart? Aren't they supposed to be closer? And where would i write to to store data then? Only sector 0?

My Code:
Code:
#include <p18f2550.h>
#include <stdio.h>
#include <delays.h>

#pragma config WDT = OFF, FOSC = HS, LVP = OFF
typedef unsigned LBA; // logic block address, 32 bit wide

//Funtions
void main(void);
void initSD( void);
void delay_s(unsigned char);
void delay_ms(unsigned char);
void delay_us(unsigned char);

unsigned char writeSPI( unsigned char b);

int sendSDCmd( unsigned char c, unsigned a);
int initMedia( void);
int writeSECTOR( LBA a, char *p, char *p2);
int readSECTOR( LBA a, char *p, char *p2);

// I/O definitions
#define SDCS LATCbits.LATC6
#define SDCS_T TRISCbits.TRISC6
#define SDCD PORTCbits.RC0
#define SDCD_T TRISCbits.TRISC0
#define LED_T TRISBbits.TRISB2
#define LED LATBbits.LATB2

// Macros

#define readSPI() writeSPI( 0xFF)
#define clockSPI() writeSPI( 0xFF)
#define disableSD() SDCS = 1; clockSPI()
#define enableSD() SDCS = 0

// SD card commands
#define RESET 0 // a.k.a. GO_IDLE (CMD0)
#define INIT 1 // a.k.a. SEND_OP_COND (CMD1)

#define READ_SINGLE 17
#define WRITE_SINGLE 24

#define I_TIMEOUT 10000
#define RI_TIMEOUT 10000
#define R_TIMEOUT 25000
#define W_TIMEOUT 250000

#define FALSE 0
#define FAIL FALSE

#define E_COMMAND_ACK 0x80
#define E_INIT_TIMEOUT 0x81

#define DATA_START 0xFE
#define DATA_ACCEPT 0x05


#pragma udata data1
char data1[256];
#pragma udata buffer1
char buffer1[256];


int writeSECTOR( LBA a, char *p, char *p2)
// a LBA of sector requested
// p pointer to sector buffer
// returns TRUE if successful
{
    unsigned r, i;
// 1. send WRITE command
    r = sendSDCmd( WRITE_SINGLE, ( a << 9));
    if ( r == 0) // check if command was accepted
    {
// 2. send data
        writeSPI( DATA_START);
// send 512 bytes of data
        for( i=0; i<256; i++)
            writeSPI( *p++);
        for( i=0; i<256; i++)
            writeSPI( *p2++);
// 3. send dummy CRC
        clockSPI();
        clockSPI();
// 4. check if data accepted
        r = readSPI();
        if ( (r & 0xf) == DATA_ACCEPT)
        {
// 5. wait for write completion
            for( i=0; i<W_TIMEOUT; i++)
            {
                r = readSPI();
                if ( r != 0 )
                    break;
            }
        } // accepted
        else
        r = FAIL;
   } // command accepted
// 6. remember to disable the card
    disableSD();
    return ( r); // return TRUE if successful
}

int readSECTOR( LBA a, char *p, char *p2)
// a LBA of sector requested
// p pointer to sector buffer
// returns TRUE if successful
{
    int r, i;
// 1. send READ command
    r = sendSDCmd( READ_SINGLE, ( a << 9));
    if ( r == 0) // check if command was accepted
    {
// 2. wait for a response
        for( i=0; i<R_TIMEOUT; i++)
        {
            r = readSPI();
            if ( r == DATA_START)
            break;
        }
// 3. if it did not timeout, read 512 byte of data
        if ( i != R_TIMEOUT)
        {
            i = 256;
            do{
                *p++ = readSPI();
            } while (--i>0);

            do{
                *p2++ = readSPI();
            } while (--i>0);
// 4. ignore CRC
        readSPI();
        readSPI();
    } // data arrived
} // command accepted
// 5. remember to disable the card
    disableSD();
    return ( r == DATA_START); // return TRUE if successful
}

void initSD( void)
{
    ADCON1 = 0x0F;
	TRISB = 0x01;
    TRISC = 0;

    LED_T = 0;
    SDCD_T = 1;
    SDCS = 1; // initially keep the SD card disabled
    SDCS_T = 0; // make Card select an output pin
    // init the SPI2 module for a slow (safe) clock speed first
	SSPSTAT = 0b00000000;		//SMP(7)=0, CKE(6)=0 (clock edge idle to active), others don't care
	SSPCON1 = 0b00010010;		//CKP(4)=1 clock polarity (idle high)
								//SSPM3:SSPM0(3:0)=010 spi clock FOSC/64 (<400kHz)
	SSPCON1bits.SSPEN=1;		//SSPEN(5)=1 enable SPI
} 

unsigned char writeSPI( unsigned char b)
{
    // send one byte of data and receive one back at the same time
    SSPBUF=b; // write to buffer for TX
    while( !SSPSTATbits.BF); // wait transfer complete
    return SSPBUF; // read the received value
}

int sendSDCmd( unsigned char c, unsigned a)
// c command code
// a byte address of data block
{
int i, r;
    // enable SD card
    enableSD();
    // send a comand packet (6 bytes)
    writeSPI( c | 0x40); // send command
    writeSPI( a>>24); // msb of the address
    writeSPI( a>>16);
    writeSPI( a>>8);
    writeSPI( a); // lsb
    writeSPI( 0x95); // send CMD0 CRC
    // now wait for a response, allow for up to 8 bytes delay
    for( i=0; i<8; i++)
    {
        r=readSPI();
        if ( r != 0xFF)
        break;
    }
    return ( r);
    // NOTE CSCD is still low!
}

int initMedia( void)
// returns 0 if successful
// E_COMMAND_ACK failed to acknowledge reset command
// E_INIT_TIMEOUT failed to initialize
{
    int i, r;
// 1. with the card NOT selected
    disableSD();
// 2. send 80 clock cycles start up
    for ( i=0; i<10; i++)
    clockSPI();
// 3. now select the card
    enableSD();
// 4. send a single RESET command
    r = sendSDCmd( RESET, 0); disableSD();
    if ( r != 1) // must return Idle
    return E_COMMAND_ACK; // comand rejected
// 5. send repeatedly INIT until Idle terminates
    for (i=0; i<I_TIMEOUT; i++)
    {
        r = sendSDCmd( INIT, 0); disableSD();
        if ( !r)
        break;
    }
    if ( i == RI_TIMEOUT)
        return E_INIT_TIMEOUT; // init timed out
// 6. increase speed
    SSPCON1bits.SSPEN=0; // disable the SPI module
    SSPCON1 = 0x30;
    SSPCON1bits.SSPEN=1; // enable SPI
    return 0;
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

void main(void)
{
    int result,i,addr;
    initSD();

    while(SDCD);
    delay_ms(100);

    
    result = initMedia();
    while(result != 0) result = initMedia();

    for(i=0;i<256;i++)
        data1[i] = i;
retryW:
        delay_ms(100);
    	addr = 10000;
		for(i=0;i<1000;i++){
			if(!writeSECTOR(addr+i,data1,data1))
					goto retryW;
		}
LED = 1;
retryV:
        delay_ms(100);
		addr=10000;				//verify write
		for(i=0;i<1000;i++){
			if(!readSECTOR(addr+i,buffer1,buffer1))
					goto retryV;
        }

	if(memcmp(data1,buffer1,256)){	//verify
		while(1);					//mismatch - 4 blinks
	}

    while(1);
}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

void delay_s(unsigned char x)
{
    char var1;
	for(var1=0;var1<x;var1++)
	{				
        Delay10KTCYx(200);
	} 
}

void delay_ms(unsigned char x)
{
    char var1;
	for(var1=0;var1<x;var1++)
	{				
        Delay1KTCYx(2);
	} 
}

void delay_us(unsigned char x)
{
    char var1;
	for(var1=0;var1<x;var1++)
	{				
        //Delay10TCYx(2);
        Delay1TCY();
        Delay1TCY();
	} 
}

EDIT:
Why when i plug in the mem card i get like a error asking me that its not formated. Where should my data go then?
 
Last edited:
how would i read it? What program?
Use your code. Init the SD and then read sector 0. Then use MPLAB's watch window to view your read buffers. Change the properties for them from ASCII to hex so they make sense.

Once I get my editor ready enough for public viewing, you can have a copy of that and use it to look with. It works now, but it's not real nice to use yet.
 
Last edited:
Yes that is i think what i wrote since i looped from 0 - 255. 2 times. But why are they so far apart? Aren't they supposed to be closer?
No idea what you mean by "far apart" and "closer". :confused:
EDIT: Is it possible that you don't know about ASCII? This link is one of my favorite ASCII tables. See how numbers 0 to 32 are all control characters and stuff beyond 127 is other strange stuff? They often don't print anything onscreen (or print gibberish), so you see gaps.

I thought you had already done asynchronous serial comm (RS232)? If you had, you'd already know about ASCII.

Anyway, if you're going to use my hex editor you'll have to learn to do async serial (it's EASY!), because I use a VT100 terminal program (Tera Term Pro) as a display and the PC's keyboard as input.

And where would i write to to store data then? Only sector 0?
Again, no idea what you mean by that. You can write anywhere you want on the card.

Why when i plug in the mem card i get like a error asking me that its not formated. Where should my data go then?
You mean when you plug it into the camera after writing to it with the PIC? If so, that's because you're probably wiping out part of a FAT or directory, or a file, when you write to the card. No worries. That's gonna happen when you write to random places on the card. Reformat it and continue.

Eventually you'll either get a card for raw use, meaning for PIC writing only, or you'll build code to write in proper FAT16 ways that won't trash the directory/FAT structure on the card.
 
Last edited:
Here's an advance look at my hex editor for SD cards and 18F4620. It displays one 512-byte sector at a time. Left side is hex and right side is ASCII.

This is a what a typical sector 0 (MBR - Master Boot Record) looks like. Look at the 16 bytes starting at $1be for the partition table for the card.

Don't forget that FAT was invented on PC, so all multi-byte values in here are little-endian (LSB first). Get used to it.

**broken link removed**


Here's the Boot Record (first sector of the partition) for this little 32MB card. Even though it's labeled as FAT12, it's actually FAT16.

**broken link removed**


And here is the root directory

**broken link removed**
 
Last edited:
I know about ASCII um.. let me make the question clearer.

No idea what you mean by "far apart" and "closer"

Since im writing 512 bytes back to back arent they supposed to be lined up closer?

Example if i write 256 A's 2 times (to make 512) is it not supposed to be like back to back?

AAAAAAAA...
AAAAAAAA...

and not like

AAAAAAAA...
jhfondljnfdln094u....(garbage)
AAAAAAAA...

Thats what it seems like.

EDIT: SORRY! i can be so stupid sometimes lol. Probable am tired. Um I see it does write back to back just that some characters are unknown by me lol. I checked the actual hex values and all line up! Im going to try and write some useful information on it later after work. and see if i can get the info out. Like small bmp hexs and stuff. If i can then ill try that Fat16 Stuff so i can load actual BMPs on the card and try to get the hex info out.
 
Last edited:
Im going to try and write some useful information on it later after work. and see if i can get the info out. Like small bmp hexs and stuff. If i can then ill try that Fat16 Stuff so i can load actual BMPs on the card and try to get the hex info out.
Why not write some ASCII text to the card. A few paragraphs (512 characters) of some easily recognizable text. Then when you look at the buffers in your watch window in the default ASCII mode you can tell at a glance if it got written and read back properly. Be sure you're looking at the read buffer (not the write buffer). :p

EDIT: Here's 256 bytes of text:
Why not write some ASCII text to the card. A few paragraphs (512 characters) of some easily recognizable text. Then when you look at the buffers in your watch window in the default ASCII mode you can tell at a glance if it got written and read back properl
and another 256 bytes:
Um I see it does write back to back just that some characters are unknown by me lol. I checked the actual hex values and all line up! Im going to try and write some useful information on it later after work. and see if i can get the info out. Like small bm
 
Last edited:
I'm toying with this idea. Don't laugh.

Have some spoken messages (error waves, prompt waves) on the SD card, then the PIC can just TELL me what the problem is with my code. I'll have to teach it how to say numbers, 0 - 255 to start.

Would be nice if it had a feminine voice, I'd hate to have to listen to mine.

Maybe even a talking alarm clock. Gets louder and angrier the longer I stay in bed. I think I've just described my wife...
 
heh that would be nice. Sorry i have been working too much this week and havent had time to actually do this. But i will have time on friday. Also i am going to order those 4620's today... when they come in the real fun begins.
 
Oh i almost forgot Futz... can i just store the whole thing (512) in eeprom and then send it from eeprom to the card? Seems like i can but want to make sure as not to waste valuable time.
 
The '2620/'4620 has 1024 bytes internal EEPROM...
Do they really?!! I hadn't looked. Very generous.

Anyway, it's only a temporary fix for Atomsoft. EEPROM isn't very well suited to use as a buffer.

Like it or not, if you're going to do FAT16 file operations (or even a lot of raw use) on an SD card, you pretty much need a chip with as much RAM as possible.
 
Last edited:
BORED: i know this probably has been thought of but since you can run code in eeprom why not make like a parser? true it will be a tad slower but in cases where it doesnt matter wouldnt that be cool?

By parser i mean like code to read eeprom and then determin what command and arguments to give out to that.

Reply:
Um thats cool. I just need it to test if im sending ok nothing more. Once its a fact that i can read/write 100% -/+ 10% lol i will be happy enough to get into the Fat16 and other FileSystems. Anyone know where i can get info on file structures?

Like BMP Files and JPG, GIF, TXT and so on... (BMP , JPEG & TXT are of most importance)
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top