I have written code to read/write 512 bytes to SD/card. I can reset the card (send reset command), initialize but not write 512 bytes. I have a question, When I do sectorWrite(), do I start writing from sector 0? my mmc card is 2g, fat16 formatted. I am using PIC18F4550. here is my entire code. Can you guys see any problem. Thanks
Rich (BB code):
=======================================================
#include "PicStar1000.h" /* PicStar library header file */
#include "p18cxxx.h"
#include <spi.h>
typedef unsigned long _ulong;
#define SIZE 32
#define SD_CS PORTBbits.RB2
#define SD_CS_TRIS TRISBbits.TRISB2
#define SD_CD PORTAbits.RA0
#define SD_CD_TRIS TRISAbits.TRISA0
#define GO_IDLE_STATE 0 //CMD0
#define SEND_OP_COND 1 //CMD1
#define SETBLOCKLEN 16 //CMD16
#define BLOCKLEN_512 512
#define CRC_ON_OFF 59 //CMD59
#define WRITE_SINGLE_BLOCK 24 //CMD24
#define READ_SINGLE_BLOCK 17 //CMD17
#define DATA_START_BYTE 0xFE
#define DATA_ACCEPTED 0x05
//Globals
long lDelay = 48000000;
char data[SIZE];
char buffer[SIZE];
/*
TRISCbits.TRISC7 = 0;
//SCK (Master mode) must have TRISB<1>bit cleared
TRISBbits.TRISB1 = 0;
//SCK (SLave mode) must have TRISB<1>bit set (ignored)
//SS must have TRISA<5>bit set
TRISAbits.TRISA5 = 1;
//0 = idle state for clock is a low level
SSPCON1bits.CKP = 1;
//bit 3 - 0 0010 = SPI Master mode, clock = F0sc/64
SSPCON1bits.SSPM0 = 0;
SSPCON1bits.SSPM1 = 0;
SSPCON1bits.SSPM2 = 1;
SSPCON1bits.SSPM3 = 0;
//SSPCON1 bit 5 SSPEN set 1 - Enables serial port, configures SCK, SDO, SDI and SS as serial port pins
SSPCON1bits.SSPEN=1; //SSPEN(5)=1 enable SPI
*/
void initSpi(void)
{
SD_CS = 1; //Initialize SPI chip select line
//CS pin set it to output
SD_CS_TRIS = 0;
OpenSPI(SPI_FOSC_64, MODE_11, SMPMID);
}
unsigned char writeSPI(unsigned char buffer)
{
SSPBUF = buffer;
while(!SSPSTATbits.BF);
return SSPBUF;
}
int sendCmd(unsigned char c, _ulong a )
{
int i,r;
//All th SD Card commands are 6 bytes long and transmitted MSB first
//After programming operation is completed, host must check the results of the programming using SEND_STATUS (CMD13)
//Commands
// CMD1 (SEND_OP_COND)
// ACMD41 (SD_SEND_OP_COND)
// CMD59 (CRC_ON_OFF)
// CMD58 (READ_OCR)
SD_CS = 0; //Starting an operation by Chip select active low
writeSPI(c|0x40);
writeSPI(a >> 24);
writeSPI(a >> 16);
writeSPI(a>>8);
writeSPI(a);
writeSPI(0x95); //Send CRC
//Response back from card
while((r = ReadSPI()) == 0xFF);
/*
i = 9;
do
{
//r = ReadSPI();
r = writeSPI(0xFF);
if( r!= 0xFF) break;
} while(--i > 0 );
*/
return r;
}
int initMedia(void)
{
int i,r;
SD_CS = 1; //It will enter SPI mode if the CS signal is asserted(negative)
writeSPI(0xFF);
//Send 80 clock cycles to start up
for(i = 0; i < 10; i++)
{
writeSPI(0xFF);
}
SD_CS = 0;
//Reset command CMD0 40 00 00 00 00 95. All SD commands are 6 bytes long.
r = sendCmd( GO_IDLE_STATE, 0x0);
//Disable SD it may be busy
SD_CS = 1;
writeSPI(0xFF);
/*
if( r != 1 )
{
return 0x84;
}
*/
i = 10000;
//Init command
SD_CS = 0;
do
{
r = sendCmd(SEND_OP_COND,0);
//Disable SD
SD_CS = 0;
writeSPI(0xFF);
if( !r) break;
} while(--i > 0 );
if( i == 0 )
{
return 0x85; //time out error
}
OpenSPI(SPI_FOSC_4, MODE_11, SMPMID);//Increase clock speed
sendCmd(CRC_ON_OFF,0x0); //Turn off CRC if possible
sendCmd(SETBLOCKLEN, BLOCKLEN_512);//Set block length 512
return 0;
}
//Valid write command CMD24
//Valid block length is 512
// DataIn Command - Response - Start block token (1 byte)|Data block - Response/busy - Next Command
int writeSector(_ulong a,char *p)
{
unsigned r,i;
int index;
r = sendCmd( WRITE_SINGLE_BLOCK ,(a<<9));
if(r==0)
{
writeSPI( DATA_START_BYTE ); //send Data Start byte
/*
for(i=0;i<SIZE;i++) //first 256 bytes
writeSPI(*p1++);
for(i=0;i<SIZE;i++) //second 256 bytes
writeSPI(*p2++);
*/
//Instead of 2 256 byes send 16 * 32 = 512 bytes
for( i = 0; i < 512; i++)
{
//writeSPI(*p);
writeSPI(1);
}
writeSPI(0xFF); //send 2 bytes of dummy CRC
writeSPI(0xFF);
if((r = writeSPI(0xFF) & 0x0F) == DATA_ACCEPTED)
{
index = 0;
do
{
r = writeSPI(0xFF);
index++;
}while( (r == 0x00) && (index != 0));
if(index == 0 )
{
r = 0; //timeout
}
writeSPI(0xFF); //Clk cycles ...wait
}
else
{
r=0; //fail
}
}
SD_CS = 1; //Chip select
return(r);
}
//Valid read command CMD17
//DataIn (Host to card) --Command --- DataOut -- Response -- - DataBlock|CRC - Next Command
int readSector(_ulong a, char *p)
{
int r,i,j, index;
r = sendCmd( READ_SINGLE_BLOCK,(a<<9));
if(r==0)
{
i=10000;
do{
r = writeSPI(0xFF);
if(r==0xFE)
{
break;
}
} while(--i > 0);
if(i)
{ //if no timeout, read 512 byte sector
/*
for(i=0;i<SIZE;i++)
*p1++ = writeSPI(0xff);
for(i=0;i<SIZE;i++)
*p2++ = writeSPI(0xff);
*/
for( i = 0; i < 16; i++)
{
for(j=0;j < 32;j++)
{
*p = ReadSPI();//writeSPI(0xFF);
}
}
writeSPI(0xFF); //ignore CRC
writeSPI(0xFF);
}
}
SD_CS = 1; //Chip select
writeSPI(0xFF); //disable SD
return(r == 0xFE);
}
void main()
{
int i,r;
_ulong addr;
PsInitHw(0);
initSpi();
DelClks(lDelay/10);//Delay for 100 ms
r = initMedia();
if( r )
{
//Error card init failed
return;
}
//Fill send buffer and receive buffer
for(i=0;i<SIZE;i++)
{ //fill the send buffers
data=i;
buffer=0;
}
//Write card
i = 0;
addr = 10000;
//for(i=0;i<1000;i++)
//{
if(!writeSector(addr+i,data))
{
/*
while(1)
{ //write failed - 2 blinks
DelClks(lDelay );
}*/
}
//}
addr=10000;
//Delay
DelClks(lDelay/5); //200 ms delay
//Read
//for(i=0;i<1000;i++)
//{
if(!readSector(addr+i,buffer))
{
/*
while(1)
{ //verify failed - 3 blinks
DelClks(lDelay );
}*/
}
//}
//Delay
DelClks(lDelay);
CloseSPI();
KeyWait();
}
Last edited by a moderator: