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.So far i think i got it to Initialize Without no issue.
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.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 ?
#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();
}
}
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.how would i read it? What program?
No idea what you mean by "far apart" and "closer".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?
Again, no idea what you mean by that. You can write anywhere you want on the card.And where would i write to to store data then? Only sector 0?
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.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?
No idea what you mean by "far apart" and "closer"
More like unknown to ASCII. They're unprintable. Anything beyond 127 is not "official" ASCII, as they're more than 7-bits. And the first 32 aren't printable either. They're control codes/escape codes/etc.I see it does write back to back just that some characters are unknown by me
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).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.
and another 256 bytes: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
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
Most on-chip EEPROMs are 256 bytes. You could store half of it and use it twice.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.
Do they really?!! I hadn't looked. Very generous.The '2620/'4620 has 1024 bytes internal EEPROM...
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?