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.
Just look in the help menu, it has the config settings.
 
i got it lol since i wrote that actually lol. Um Here is my setup for some reason still wont initialize now.

ss_a-jpg.21680

as you can see i added a 3 color led (r/g/y)
Also changed and added:
Code:
retryit:
	r=initMedia();
	if(r){						//card init failed - 1 blink
        for(i=0;i<3;i++){
			LED=1;
			delay_ms(200);
			LED=0;
			delay_s(1);
		}
        goto retryit;
    }
Here is my code:
Code:
#include <p18f2550.h>
#include <stdio.h>
#include <delays.h>

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

// FUNCTION Prototypes

unsigned char var;
typedef unsigned long LBA;

void main(void);
void set_wren(void);
int initMedia(void);
int sendSDCmd(unsigned char c, LBA a);
void delay_s(unsigned char x);
void delay_ms(unsigned char x);
void delay_us(unsigned char x);
unsigned char writeSPI(unsigned char send);
int writeSector(LBA a,char *,char *);
int readSector(LBA a, char *, char *);

char data1[256];
char data2[256];
char buffer1[256];
char buffer2[256];

#define CSel LATCbits.LATC6
#define LED LATBbits.LATB2
#define LEDOk LATBbits.LATB3

//*******************************************


void main(void)
{
	LBA addr;
	int i,r;

	TRISB=0b00000001;
    TRISC = 0;

	CSel=1;						//init chip select (active low)
	LED=0;						//LED off
    LEDOk = 0;

	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
	for(i=0;i<256;i++){				//fill the buffers
		data1[i]=i;
		data2[i]=i;

    }
retryit:
	r=initMedia();
	if(r){						//card init failed - 1 blink
        for(i=0;i<3;i++){
			LED=1;
			delay_ms(200);
			LED=0;
			delay_s(1);
		}
        goto retryit;
    } 

    if(!r){                     //write card
        LEDOk = 1;
		addr = 10000;
		for(i=0;i<1000;i++){
			if(!writeSector(addr+i,data1,data2)){
				while(1){		//write failed - 2 blinks
					LED=1;
					delay_ms(200);
					LED=0;
					delay_ms(200);
					LED=1;
					delay_ms(150);
					LED=0;
					delay_s(2);
                    
				}
			}
		}
    }
		addr=10000;				//verify write
		for(i=0;i<1000;i++){
			if(!readSector(addr+i,buffer1,buffer2)){
				while(1){		//verify failed - 3 blinks
					LED=1;
					delay_ms(75);
					LED=0;
					delay_ms(75);
					LED=1;
					delay_ms(75);
					LED=0;
					delay_ms(75);
					LED=1;
					delay_ms(75);
					LED=0;
					delay_s(1);
				}
			}
        }
        LEDOk = 0;
    while(1);
}


int initMedia(void)
{
	int i,r;
	CSel=1;					//while card is not selected
	for(i=0;i<16;i++)			//send 80 clock cycles to start up
		writeSPI(0xff);
	CSel=0;					//then select the card
	r = sendSDCmd(0,0);			//send reset command to enter SPI mode
	CSel=1;					//disable SD
	writeSPI(0xff);
	if(r != 1)				//error check - need 1
		return 0x84;
	i = 10000;				//send init for up to 0.3s
	CSel=0;
	do{
		r = sendSDCmd(1,0);		//send init command
		CSel=1;				//disable SD
		writeSPI(0xff);
		if(r) break;
	}while(--i > 0);
	if(i==0)				//time out error 0x85
		return 0x85;

    SSPCON1 = 0x30;
	return 0;
}

int sendSDCmd(unsigned char c, LBA a)
{
	int i,r,x;
	CSel=0;						//send command packet (6 bytes)
	writeSPI(c|0x40);				//send command & frame bit
	writeSPI(a>>24);				//send 32-bit address
	writeSPI(a>>16);
	writeSPI(a>>8);
	writeSPI(a);
	writeSPI(0x95);	

	i=9;	
					//wait for response
	do{
		r=writeSPI(0xff);			//check if ready
		if(r != 0xff)
			break;
	}while(--i > 0);

	return(r);
}


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();
	} 
}
unsigned char writeSPI(unsigned char send)
{
	SSPBUF=send;
	while(!SSPSTATbits.BF);
	return SSPBUF;
}

int writeSector(LBA a,char *p1,char *p2)
{
	unsigned r,i;
	LED=1;						//turn on write LED
	r=sendSDCmd(24,(a<<9));
	if(r==0){
		writeSPI(0xfe);				//send Data Start byte
		for(i=0;i<256;i++)			//first 256 bytes
			writeSPI(*p1++);
		for(i=0;i<256;i++)			//second 256 bytes
			writeSPI(*p2++);
		writeSPI(0xff);				//send dummy CRC
		writeSPI(0xff);
		if((r=writeSPI(0xff) & 0x0f) == 0x05){	//check if data accepted
			for(i=10000;i>0;i--){
				if(r=writeSPI(0xff))
					break;
			}
		}
		else
			r=0;				//fail
	}
	CSel=1;writeSPI(0xff);				//disable SD
	LED = 0;					//LED off
	return(r);
}

int readSector(LBA a, char *p1, char *p2)
{
	int r,i;
	LED = 1;					//turn on read LED
	r = sendSDCmd(17,(a<<9));
	if(r==0){					//check if command was accepted
		i=10000;				//wait for a response
		do{
			r = writeSPI(0xff);
			if(r==0xfe)
				break;
		}while(--i > 0);
		if(i){					//if no timeout, read 512 byte sector
			for(i=0;i<256;i++)
				*p1++ = writeSPI(0xff);
			for(i=0;i<256;i++)
				*p2++ = writeSPI(0xff);
			writeSPI(0xff);			//ignore CRC
			writeSPI(0xff);
		}
	}
	CSel=1;writeSPI(0xff);				//disable SD
	LED = 0;					//read LED off
	return(r == 0xfe);
}
 

Attachments

  • ss_a.jpg
    ss_a.jpg
    526.5 KB · Views: 512
Last edited:
well its Red and Green and when both on its like yellow/orange
Ah! That's a two color (bicolor) red/green LED. Gotcha.

I got it to initialize but now bad data write lol
Fun, huh? It all has to be just so or it doesn't work. I guess you don't have a copy of "Learning to Fly the PIC24"? Just about everything is pretty well explained in there.
 
seems to write now but stuck on read lol the issue has to be timing because i have it loop bCK ON FAIL until it passes and works
There's not much timing involved. "you will find that... SD/MMC connector, can easily sustain a clock rate as high as 8MHz." SPI is pretty fast. Basically just jiggle the clock line really quick and shift bits through the SPI shift register just as fast as it goes out/comes in. It's very reliable.

Writing 1000 sectors to flash takes quite a while. You need to be patient. Reading is a LOT faster. When my LED first turned on for writing, I thought the thing had crashed. It took forever! Then finally it blinked the success code, I halted it and looked at the buffers I had read and they were full! :D
 
Last edited:
the read data is supposed to be the same as the data1 i assume. The issue isnt writing its reading lol. I can write it out quick now. But reading sux. Ah man its 2am here time for bed i work in 10 hours.
 
Its weird it write and initializes ok But reading a no go?

If it writes and init's ok ten i assume wiring is ok.
You said before that writing was quick. Really? If so that probably means it's NOT writing. If you can't read, you can't confirm it anyway. But it really should take a while.

For a while there before I got things working mine made like it was writing, but when I followed it closely in the debugger I found that it actually wasn't, as the SD wasn't really initialized, though I thought it was. Watch the r variable.

EDIT: Oh, I see what your problem is! In every picture you post there's no SD card in the slot. It won't work unless there's one plugged in there. :D:D:D
 
Last edited:
After work ima buy :

Programming 32-bit Microcontrollers in C: Exploring the PIC32 (Embedded Technology) (Paperback)

Ill see ya later ill be back like 9-10hrs lol
 
lol i used the sd to take the pic lol It was there.
Oh ya, that's what you say now. :D

I grabbed your version of the code and changed it to suit 4620 and my setup. I set up a MCC18 project to compile it.

But I'm having the same linker trouble you were having earlier
Code:
Executing: "C:\Program Files\Microchip\MPASM Suite\MPLink.exe" /l"C:\MCC18\lib" "..\..\..\MCC18\lkr\18f4620.lkr" "sdcard.o" "C:\MCC18\lib\p18f4620.lib" /z__MPLAB_BUILD=1 /o"sdcard.cof" /M"sdcard.map" /W
MPLINK 4.16, Linker
Copyright (c) 2008 Microchip Technology Inc.
Error - section '.udata_sdcard.o' can not fit the section. Section '.udata_sdcard.o' length=0x00000401
Errors    : 1

Link step failed.
What's the meaning of this?

EDIT: Got that fixed. The cure is to define a udata for each buffer, otherwise the stupid linker attempts to stuff 1K of data into a single 256 byte bank. Dumb. BoostC's linker is smarter than that. There may be some benefit of doing it manually that I don't yet know about though...
Code:
unsigned char var;
#pragma udata data1
char data1[256];
#pragma udata data2
char data2[256];
#pragma udata buffer1
char buffer1[256];
#pragma udata buffer2
char buffer2[256];
 
Last edited:
You need to mod the linker give me asec ill mod it and post it

EDIT: TRY THIS:
Code:
// File: 18f4620.lkr
// Sample linker script for the PIC18F4620 processor
// Modded by AtomSoft

LIBPATH .

FILES c018i.o
FILES clib.lib
FILES p18f4620.lib

CODEPAGE   NAME=page       START=0x0               END=0xFFFF
CODEPAGE   NAME=idlocs     START=0x200000          END=0x200007       PROTECTED
CODEPAGE   NAME=config     START=0x300000          END=0x30000D       PROTECTED
CODEPAGE   NAME=devid      START=0x3FFFFE          END=0x3FFFFF       PROTECTED
CODEPAGE   NAME=eedata     START=0xF00000          END=0xF003FF       PROTECTED

ACCESSBANK NAME=accessram  START=0x0            END=0x7F
DATABANK   NAME=gpr0       START=0x80           END=0xF7F
//DATABANK   NAME=gpr1       START=0x100          END=0x1FF
//DATABANK   NAME=gpr2       START=0x200          END=0x2FF
//DATABANK   NAME=gpr3       START=0x300          END=0x3FF
//DATABANK   NAME=gpr4       START=0x400          END=0x4FF
//DATABANK   NAME=gpr5       START=0x500          END=0x5FF
//DATABANK   NAME=gpr6       START=0x600          END=0x6FF
//DATABANK   NAME=gpr7       START=0x700          END=0x7FF
//DATABANK   NAME=gpr8       START=0x800          END=0x8FF
//DATABANK   NAME=gpr9       START=0x900          END=0x9FF
//DATABANK   NAME=gpr10      START=0xA00          END=0xAFF
//DATABANK   NAME=gpr11      START=0xB00          END=0xBFF
//DATABANK   NAME=gpr12      START=0xC00          END=0xCFF
//DATABANK   NAME=gpr13      START=0xD00          END=0xDFF
//DATABANK   NAME=gpr14      START=0xE00          END=0xEFF
//DATABANK   NAME=gpr15      START=0xF00          END=0xF7F
ACCESSBANK NAME=accesssfr  START=0xF80          END=0xFFF          PROTECTED

SECTION    NAME=CONFIG     ROM=config

STACK SIZE=0x100 RAM=gpr0

EDIT #2:
I got that book but from a friend and no cd :( kinda beat up but heh free for now lol ill buy it when i get paid

Gonna get it at barnes and noble:
http://search.barnesandnoble.com/Pr...rs-in-C/Lucio-Di-Jasio/e/9780750687096/?itm=1
 
Last edited:
You need to mod the linker give me asec ill mod it and post it
No you don't. Just define a udata for each large buffer. It's pretty well covered in the manual.

Don't start modifying linker scripts unless you really have to.

I got that book but from a friend and no cd :( kinda beat up but heh free for now lol ill buy it when i get paid
Cool. Free is good.

Your code works fine. Fixed some little things. You took out some stuff that should be in there, but I'm about to put that back in. I'll post it then.
 
Last edited:
Your 1 second delay is WAY too short. I didn't bother to fix it. The LED still blinks, and that's good enough. It just doesn't blink how I expected it to. On a 20MHz clock like yours you probably won't even see it blinking.

Of course it's been changed to suit 18F4620 with internal osc again, so you'll have to change that back.

Set a breakpoint on the red highlighted line before you run it so you can confirm that buffer1 and buffer2 are clear before you hit F9 again to write/read the SD. When the LED changes from continuous-on to success-flashes, halt it and look at buffer1 and buffer2 again in the watch window. :D
Code:
#include <p18f4620.h>
#include <delays.h>
#pragma config OSC = INTIO67, WDT = OFF, LVP = OFF

typedef unsigned long LBA;

void set_wren(void);
int initMedia(void);
int sendSDCmd(unsigned char,LBA);
void delay_s(unsigned char);
void delay_ms(unsigned char);
void delay_us(unsigned char);
unsigned char writeSPI(unsigned char);
int writeSector(LBA a,char *,char *);
int readSector(LBA a, char *, char *);

unsigned char var;
#pragma udata data1
char data1[256];
#pragma udata data2
char data2[256];
#pragma udata buffer1
char buffer1[256];
#pragma udata buffer2
char buffer2[256];

#define CSel LATDbits.LATD2
#define LED LATDbits.LATD1

void main(void)
{
	LBA addr;
	int i,r;
	TRISC=0b00010000;
    TRISD = 0;
	CSel=1;						//init chip select (active low)
	LED=0;						//LED off
	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
	for(i=0;i<256;i++){			//fill the buffers
		data1[i]=i;
		data2[i]=i;
		buffer1[i]=0;			//and clear the receive buffers
		buffer2[i]=0;
    }

	r=initMedia();
[COLOR="Red"]	if(r){						//card init failed - 1 blink
[/COLOR]		while(1){
			LED=1;
			delay_ms(200);
			LED=0;
			delay_s(1);
		}
    } 
    else{                     //write card
		addr = 10000;
		for(i=0;i<1000;i++){
			if(!writeSector(addr+i,data1,data2)){
				while(1){		//write failed - 2 blinks
					LED=1;
					delay_ms(200);
					LED=0;
					delay_ms(200);
					LED=1;
					delay_ms(200);
					LED=0;
					delay_s(1);
                    
				}
			}
		}
		addr=10000;				//verify write
		for(i=0;i<1000;i++){
			if(!readSector(addr+i,buffer1,buffer2)){
				while(1){		//verify failed - 3 blinks
					LED=1;
					delay_ms(200);
					LED=0;
					delay_ms(200);
					LED=1;
					delay_ms(200);
					LED=0;
					delay_ms(200);
					LED=1;
					delay_ms(200);
					LED=0;
					delay_s(1);
				}
			}
			if(memcmp(data1,buffer1,256)||memcmp(data2,buffer2,256)){	//verify
				while(1){					//mismatch - 4 blinks
					LED=1;
					delay_ms(150);
					LED=0;
					delay_ms(150);
					LED=1;
					delay_ms(150);
					LED=0;
					delay_ms(150);
					LED=1;
					delay_ms(150);
					LED=0;
					delay_ms(150);
					LED=1;
					delay_ms(150);
					LED=0;
					delay_s(1);
				}
			}
		}
	}
	while(1){							//success!
		LED=1;
		delay_s(1);
		LED=0;
		delay_s(1);
	}
}

int writeSector(LBA a,char *p1,char *p2)
{
	unsigned r,i;
	LED=1;						//turn on write LED
	r=sendSDCmd(24,(a<<9));
	if(r==0){
		writeSPI(0xfe);				//send Data Start byte
		for(i=0;i<256;i++)			//first 256 bytes
			writeSPI(*p1++);
		for(i=0;i<256;i++)			//second 256 bytes
			writeSPI(*p2++);
		writeSPI(0xff);				//send dummy CRC
		writeSPI(0xff);
		if((r=writeSPI(0xff) & 0x0f) == 0x05){	//check if data accepted
			for(i=10000;i>0;i--){
				if(r=writeSPI(0xff))
					break;
			}
		}
		else
			r=0;				//fail
	}
	CSel=1;writeSPI(0xff);				//disable SD
	LED = 0;					//LED off
	return(r);
}

int readSector(LBA a, char *p1, char *p2)
{
	int r,i;
	LED = 1;					//turn on read LED
	r = sendSDCmd(17,(a<<9));
	if(r==0){					//check if command was accepted
		i=10000;				//wait for a response
		do{
			r = writeSPI(0xff);
			if(r==0xfe)
				break;
		}while(--i > 0);
		if(i){					//if no timeout, read 512 byte sector
			for(i=0;i<256;i++)
				*p1++ = writeSPI(0xff);
			for(i=0;i<256;i++)
				*p2++ = writeSPI(0xff);
			writeSPI(0xff);			//ignore CRC
			writeSPI(0xff);
		}
	}
	CSel=1;writeSPI(0xff);				//disable SD
	LED = 0;					//read LED off
	return(r == 0xfe);
}

int initMedia(void)
{
	int i,r;
	CSel=1;						//while card is not selected
	for(i=0;i<16;i++)			//send 80 clock cycles to start up
		writeSPI(0xff);
	CSel=0;						//then select the card
	r = sendSDCmd(0,0);			//send reset command to enter SPI mode
	CSel=1;writeSPI(0xff);		//disable SD
	if(r != 1)					//error check - need 1
		return 0x84;
	i = 10000;					//send init for up to 0.3s
	CSel=0;
	do{
		r = sendSDCmd(1,0);		//send init command
		CSel=1;writeSPI(0xff);	//disable SD
		if(!r) break;
	}while(--i > 0);
	if(i==0)					//time out error 0x85
		return 0x85;
    SSPCON1 = 0x30;
	return 0;
}

int sendSDCmd(unsigned char c, LBA a)
{
	int i,r;
	CSel=0;						//send command packet (6 bytes)
	writeSPI(c|0x40);			//send command & frame bit
	writeSPI(a>>24);			//send 32-bit address
	writeSPI(a>>16);
	writeSPI(a>>8);
	writeSPI(a);
	writeSPI(0x95);	
	i=9;						//wait for response
	do{
		r=writeSPI(0xff);		//check if ready
		if(r != 0xff)
			break;
	}while(--i > 0);
	return(r);
}

unsigned char writeSPI(unsigned char send)
{
	SSPBUF=send;
	while(!SSPSTATbits.BF);
	return SSPBUF;
}

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();
	} 
}
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top