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.
Oh and if you are using the SD card, try not to write to the first sectors on it, since that will crash the entire file system and you might have trouble formating it again.
 
i was thinking about it too. I most likely will tho. Oh yeah off topic i found a nintendo ds on the street but screens where broken so i took it for parts. I already have the touch screen showing good signals. (Analog test) Im going to add it to my glcd project. The issue is its not the same size so im limited to the touch screen size.
 
Last edited:
Oh and if you are using the SD card, try not to write to the first sectors on it, since that will crash the entire file system and you might have trouble formating it again.
I don't see how that would make the card unformattable. Definitely unreadable by a PC or camera though. :p I wrote a FAT hex editor in 6809 assembler for the TRS-80 Color Computer back in the 80's and then one for PC, so I have a real good idea how FAT works. That's the next phase of this project.
 
Last edited:
i still cant seem to compile due to memory thing with C18 this sux. I guess boostc is the way to go. Gota put on hold then :(
Just do what I said. Rewrite so you use the same buffers for read and write. You aren't doing both at the same time anyway (yet). Saves 512 bytes of RAM. Easy to do too.

Or order up a 18F4620. Such a nice fatty chip. :D
 
Last edited:
So many issues lol Now its halting when it tries to writeSPI
writeSPI(a>>8);

There isnt a break point there. What gives.
Phantom breakpoint. MPLAB buglet. Happens all the time. I save the source and header files somewhere and wipe the rest of the project. Start a new project and put the source/header back in and it's fixed.
 
Hello everyone!

I came across this thread while researching SD card projects. I've spent the last few weeks interfacing a PIC 18LF4620 to numerous SD cards. It's been exciting and frustrating.

My project uses the PIC with a MAX541 16 bit DAC to output audio wav files from the SD card. 22050 Hz at 16 bits sounds great. The PIC is using the internal 8Mhz oscillator with a 4X PLL == 32 MHz. Works fine at 3.3 volts, though I may be pushing it a bit.

Just a few tips and observations to help you avoid the pitfalls I've encountered...

If at all possible, use a low voltage microcontroller to interface directly with the SD card at 3.3 Volts to develop your code. When the code is bulletproof, then test it using a 5V micro to 3.3V SD voltage conversion.

Windows XP will format a raw SD card. Unfortunately, the MBR ( master boot record,partition information) is NOT written to sector 0. The LBR (FAT16 info) is written to sector 0. Use a camera or other device to format the card if your application is looking for an MBR.

Foust's abstract on an SD interface is great, but...

The SD documentation specifies that an extra byte be clocked to the card after the command response token. Foust's code suggests that the byte received is meaningless. When reading the CSD register, this byte can be the data start token, 0xFE.

On a lighter note, I just bought a 3 pack of PNY 2GB SD cards for about 21 bucks delivered. From Newegg. The PNY cards can handle a 1024 byte sector. Thought it might improve the transfer speed, but it actually slowed things down a bit. I'm currently reading about 280 KB/sec ( 8 MHz clock ).

Should be able to optimize the code to speed things up. Have to sleep now, My alarm goes off in 4 1/2 hours.
 
Hello everyone!

My project uses the PIC with a MAX541 16 bit DAC to output audio wav files from the SD card. 22050 Hz at 16 bits sounds great. The PIC is using the internal 8Mhz oscillator with a 4X PLL == 32 MHz. Works fine at 3.3 volts, though I may be pushing it a bit.
Hey Eurisko. :D Sounds like a very cool project.

I'm currently writing a hex sector editor for SD cards, using the 18F4620. I don't know what use it will be, (maybe I'll think of something) but I'm amusing myself. The display is Tera Term Pro doing VT100 at 115200 baud async.
 
Eurisko thanks for the tips. Ill be sure to get my hands on a low voltage 18LF4620 and a normal one. The delay i have is my job.. funds.. They messed up my paper work and i have to wait about 2 more weeks just to get my first check & second check. So at least i come home with about $600 which isnt bad.
 
Eurisko thanks for the tips. Ill be sure to get my hands on a low voltage 18LF4620 and a normal one...

AtomSoft, the 18LF4620 can handle supply voltages from 2.0 to 5.5 volts. No need to switch chips when going to 5 volts. :)

...I'm currently writing a hex sector editor for SD cards, using the 18F4620. I don't know what use it will be, (maybe I'll think of something) but I'm amusing myself.

futz, I wish I had one! I'm using DiskProbe to verify the SD card contents, but it is not reporting the full capacity of ANY of the SD cards I've tried, from 64MB to 2GB. Trying to access a sector beyond the reported capacity generates an error. The actual card capacity can be calculated from the CSD register, and DiskProbe gets it wrong every time.
 
Eurisko would a PIC18F87J10 be a good 3v chip as a starting point? Lots of ram no rom (well emulated rom) Since rom isnt needed here because i have enough on the SD. Um...

Can i write any size to a sd or does it has to be in junks?
 
AtomSoft,

It's a great chip, but that 80 pin TQFP package is a little too much for my breadboarding skills :eek:

It seems to have the same amount of onchip RAM as a 18F4620, and an abundance of I/O pins. I recommended the 18LF4620 simply because of its 4K RAM, 32K program memory and the wide operating voltage range.

Each SD card's CSD register will specify the maximum & minimum write blocks. I haven't personally seen any SD card that will permit a partial sector write.

Command 9 (send CSD) will instruct the card to send its card specific data. The data will consist of the start block token (0xFE), 16 bytes of CSD, then 2 CRC bytes. The data is a bit tricky to extract in assembler, since some of the bitfields span multiple bytes. It should be fairly easy to set up a C structure and just read the values in.
Bits are numbered from 127 to 0 (16 bytes)
The relevant fields are :
Bit 21 WRITE_BL_PARTIAL Boolean TRUE/FALSE
Bits 25:22 WRITE_BL_LEN valid values are 9, 10, or 11

The WRITE_BL_LEN field yields 2 ^ WRITE_BL_LEN,
(or 0x1<<WRITE_BL_LEN, if you prefer C style).

512 byte blocks are always accepted. I assume that any multiple of 512 bytes (up to 2 ^ WRITE_BL_LEN) is permitted, but have only been able to verify the 2^9 and 2^10 cards.

I know that this is difficult to read ( BORING) , but it will be worth it when your project comes to life. When I finally heard crisp, clear sound coming from that amazing little card, I was blown away.

Just how Watson must have felt when Bell made that first telephone call.

:D
 
Heh for some reason this is never boring for me. Just sometimes i get tired of thinking and may need a break. Im reading that book "Programming 32-bit microcontrollers in C" and lots of info im sure i can break down in time. Just now my time is sporadic since i work more. But im sure ill get it in time. I will buy the 18F4620 but the PIC18F87J10 will be used in another project once i learn this SD stuff and i know i would need more I/O pins. For like LCD Control and stuff. And Buttons (non multiplexed)
 
Ok i cleaned up the sd wiring and code. And will try it tonight. (Was reading the book so feel better a little) im still using the 2550 but mostly till i get a 4620. The main reason is heh i still at least need to learn spi more and how to initialize it right. Here are some pics of it cleaned up:
1-jpg.21845


2-jpg.21846


3-jpg.21847


4-jpg.21848
 

Attachments

  • 1.jpg
    1.jpg
    158.5 KB · Views: 493
  • 2.jpg
    2.jpg
    210.2 KB · Views: 465
  • 3.jpg
    3.jpg
    162.3 KB · Views: 492
  • 4.jpg
    4.jpg
    192.2 KB · Views: 460
So far i think i got it to Initialize Without no issue.

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

#pragma config WDT = OFF, FOSC = HS, LVP = OFF

//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);


// I/O definitions
#define SDCS LATCbits.LATC6
#define SDCS_T TRISCbits.TRISC6
#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 FAIL FALSE

#define E_COMMAND_ACK 0x80
#define E_INIT_TIMEOUT 0x81
typedef unsigned LBA; // logic block address, 32 bit wide

void initSD( void)
{
    ADCON1 = 0x0F;
	TRISB = 0x01;
    TRISC = 0;
    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;
    initSD();
    result = initMedia();
    while(result != 0) {
        result = initMedia();
    }
    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();
	} 
}
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top