I got working on mine again this weekend. I'm having some strangeness and haven't yet got it working. I would like to compare code with what you come up with.Hey all while im waiting for payday to finish my charger project. i thought id start on my other project. SD Cards.
I'll find my list and post it again later today or tonight. There are some very good refs out there, along with a lot of useless crap.Any links or datasheets or anything that can help would be great.
SD sockets can be made out of an **broken link removed** or purchased for a couple bucks. The bought ones you just solder some pins on and plug into your breadboard. Cheap.Just joking. I sincerely wish I had the budget to buy some of these things. I'm always going to be a year behind you guys on these fun projects.
Even SparkFun sells sockets for only $4. I've seen them elsewhere for around $2.If anything i was thinking it would be easy to buy a TransFlash w/ SD adapter. https://www.dipmicro.com/store/index.php?act=viewProd&productId=385
and solder wires directly to the sd card(adapter) and use micro cards from there on.
So I got a **broken link removed** and played with the code for a long while. I think I almost have it working. But now I plug the 32MB card in and it works normally (meaning almost working). I don't know what was going on before. So buying the 2GB wasn't necessary. Ah well... It'll get used, I guess.The 32MB cards I have don't seem to work in SPI mode. They return illegal command codes every time. After thinking it was my code for quite a while I finally grabbed the 4GB card out of the camera and it works (almost) properly. So I'm shopping for another SD card just for experimenting. Think I'll get a 2GB. They're around $11.
#include "sdcard.h"
char data1[256];
char data2[256];
char buffer1[256];
char buffer2[256];
void main(void){
LBA addr;
int i,r;
trisd=0;
trisc=0b00010000;
CSel=1; //init chip select (active low)
LED=0; //LED off
osccon=0x72; //8MHz clock
osctune.6=0; //disable PLL
while(!osccon.IOFS); //wait for osc stable
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)
sspcon1.SSPEN=1; //SSPEN(5)=1 enable SPI
for(i=0;i<256;i++){ //fill the buffers
data1[i]=i;
data2[i]=i;
}
r=initMedia();
if(r){ //card init failed - 1 blink
while(1){
LED=1;
delay_ms(75);
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(75);
LED=0;
delay_ms(75);
LED=1;
delay_ms(75);
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(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);
}
}
if(memcmp(data1,buffer1,256)||memcmp(data2,buffer2,256)){ //verify
while(1){ //mismatch - 4 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_ms(75);
LED=1;
delay_ms(75);
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; //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 = 0b00010000; //speed up spi clock
sspcon1.SSPEN=1;
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); //send CRC
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(!sspstat.BF);
return sspbuf;
}
#include <system.h>
#include <memory.h>
#pragma CLOCK_FREQ 8000000
#pragma DATA _CONFIG1H, _OSC_INTIO67_1H
#pragma DATA _CONFIG2H, _WDT_OFF_2H
#pragma DATA _CONFIG3H, _MCLRE_ON_3H
#pragma DATA _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
#define CSel latd.2 //chip select line
#define LED latd.1
typedef unsigned long LBA;
int writeSector(LBA,char *,char *);
int readSector(LBA, char *,char *);
int initMedia(void);
int sendSDCmd(unsigned char,LBA);
unsigned char writeSPI(unsigned char);
Thanks Electro, but I make it a policy to always do it myself first, even if it's with mostly someone else's code. I don't care how long it takes. I like to learn how it works. Using libs teaches me nothing.Well i have one word for you MDDFS Lib. Its a library made officially by microchip and it dosent only handle the
#include <p18cxxx.h>
#include <stdio.h>
#include <delays.h>
#include <spi.h>
#pragma config WDT = OFF, OSC = HS, LVP = OFF
// FUNCTION Prototypes
void main(void);
void set_wren(void);
int initMedia(void);
int sendSDCmd(unsigned char c, unsigned long a);
void delay_s(unsigned char x);
void delay_ms(unsigned char x);
void delay_us(unsigned char x);
unsigned char var;
#define CSel LATDbits.LATD0
#define LED LATDbits.LATD1
//*******************************************
void main(void)
{
char i,r ;
LED = 0;
TRISDbits.TRISD0 = 0;
TRISDbits.TRISD1 = 0;
CSel = 1; //init chip select (active low)
OpenSPI(SPI_FOSC_64, MODE_00, SMPEND);
r=initMedia();
if(r){ //card init failed - 1 blink
while(1){
LED=1;
delay_ms(75);
LED=0;
delay_s(1);
}
}
while(1);
}
int initMedia(void)
{
char i,r;
CSel=1; //while card is not selected
for(i=0;i<16;i++) //send 80 clock cycles to start up
putcSPI(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
putcSPI(0xff);
if(r) break;
}while(--i > 0);
if(i==0) //time out error 0x85
return 0x85;
return 0;
}
int sendSDCmd(unsigned char c, unsigned long a)
{
int i,r;
CSel=0; //send command packet (6 bytes)
putcSPI(c|0x40); //send command & frame bit
putcSPI(a>>24); //send 32-bit address
putcSPI(a>>16);
putcSPI(a>>8);
putcSPI(a);
putcSPI(0x95); //send CRC
i=9;
//wait for response
do{
r=putcSPI(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();
}
}
I've seen a couple, but they're never quite detailed enough.This is so confusing. I have not seen not 1 flow chart type info to explain how to initialize the sd card.
I think you should be sampling in middle, not end.Input data sample at end of data out
Then you're semi close to where I am. Spending tons of time in the debugger, setting breakpoints all over the place to see what r is at different points.I tried to convert futz code well upto the init part, this is what i have but the LED blinks stating that the init failed:
pData[0]= 0x40;
pData[1]= 0x00;
pData[2]= 0x00;
pData[3]= 0x00;
pData[4]= 0x00;
pData[5]= 0x95;
A write_single command gets an R1 response, which is one byte. It's getting stored into an int, so it shows up in the debugger as two bytes of which the msbyte will always be zero. It could just as well be stored in an unsigned char, but I just typed in that part of the book code as is.OK i havent got it to write but compiles fine! Um in the WriteSector function r returns
r=sendSDCmd(24,(a<<9)); == (0x80)
Not sure but it receives it as 2 bytes. Does the byte length refer to like R2 (Response type R2) If so then the error is "Out of Range, CSD Overwrite"
Six byte packets:"SD commands are listed in the form CMDXX" How do i send that out?
Should i make a array like:
unsigned char pData[5];
and fill it with the bytes for the packet?
1. 01 is like start bits
2. How would i turn CMD0 into 6 bits?
3. What would be the args?
4. CRC i see is a constant because not really used in SPI (0x95) only for fist to set SPI.
5. 1 is the stop bit.
Thats my main concern right now. I kinda can follow the app notes but cant until i understand the above 2,3 and how to send it all.
int initMedia(void)
{
int i,r;
CSel=1;writeSPI(0xff); //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([COLOR="Red"]!r[/COLOR]) break;
}while(--i > 0);
if(i==0) //time out error 0x85
return 0x85;
sspcon1 = 0b00010000; //speed up spi clock
sspcon1.SSPEN=1;
return 0;
}
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?