Chullaa
Advanced Member level 4
- Joined
- Aug 27, 2010
- Messages
- 113
- Helped
- 17
- Reputation
- 34
- Reaction score
- 17
- Trophy points
- 1,298
- Activity points
- 2,019
Hi i am trying to interface SD card with PIC16F877A. I am using CCS Complier and Proteus Vsm for simulatrion.
I am trying to communicate with card but still failed.
Here is the code and schematic.
I am trying to communicate with card but still failed.
Here is the code and schematic.
Code:
#include "H:\Data\7 Semester\UIT\UP\SD CARD\main.h"
//#include<pic.h> //head file.
//__CONFIG(0x1832);
#define cs portc2 //define sd pin.
//#use spi(DI=PIN_C4, DO=PIN_C5, CLK=PIN_C3, ENABLE=PIN_C2, BITS=16)
//0-9 display table.
const char TABLE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0X82,0XF8,0X80,0X90};
unsigned char loop,res;
void spi_init(); //spi init
void spi_low(); //produce low band func(sd card init use.)
void spi_high(); //produce high band func(sd card init use.)
unsigned char sd_reset(); //sd card init func
unsigned char SD_SendCommand(unsigned char cmd,unsigned long arg); //write sd card command func
unsigned char SPI_WriteByte(unsigned char val); //write one byte func.
unsigned char SPI_ReadByte(void); //receive one byte func.
unsigned char SD_WriteSingleBlock(unsigned long sector); //write sd card one blockfunc.
unsigned char SD_ReadSingleBlock(unsigned long sector); //read sd card one blockfunc.
void display(unsigned char temp); //result display func.
void delay();
#use spi(DI=PIN_C4, DO=PIN_C5, CLK=PIN_C3, ENABLE=PIN_C2, BITS=16)
//main
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(spi_master |spi_l_to_h |spi_clk_div_16 );
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
loop=1;
while(loop)
{
spi_init(); //system init.
res= sd_reset(); //sd card init.
if(res) break; //if init is abnormal,exit and don't perform the next func.
SD_WriteSingleBlock(1); //write sd card one block,and the block number is 1.
if(res) break;
SD_ReadSingleBlock(1); //read sd card one block,and the block number is 1.
if(res) break;
loop=0;
portc1=0;
while(1);
}
portc0=1;
while(1);
}
////////////////////////////////////////////////
//spi init
void spi_init()
{
TRISC=0xd0; //set SDI as input£¬other port c are output.
TRISD=0X00; //set port d as output.
TRISA=0X00; //set port a as output.
ADCON1=0X07; //set port a as ordinary i/o.
SSPCON=0x32; //high when idle.fosc/64
SSPSTAT=0x80; // rising edge,send data.
portc0=0;
portc1=0;
PORTA=0XFF;
}
////////////////////////////////////////////////
//set low band.
void spi_low()
{
SSPCON=0x32; //SPI clk use the system clk--fosc/64
}
////////////////////////////////////////////////
//set high band.
void spi_high()
{
SSPCON=0x31; //SPI clk use the system clk--fosc/64
}
///////////////////////////////////////////////
//write one byte.
unsigned char SPI_WriteByte(unsigned char val)
{
SSPBUF = val; //load to send buffer
while(!SSPIF); //wait to finish sending.
SSPIF=0; //clear send finish flag.
return SSPBUF; //read the receive buffer(even the data is unvalid,it is still need cleared.)
}
///////////////////////////////////////////////
//read one byte.
unsigned char SPI_ReadByte(void)
{
SSPBUF = 0xff; //load to send buffer to start receiving.
while(!SSPIF); //wait to finish receiving.
SSPIF=0; //clear receiving finish flag.
return SSPBUF; //read the receive buffer
}
////////////////////////////////////////////////
//send command func
unsigned char SD_SendCommand(unsigned char cmd,unsigned long arg)
{
unsigned char r1;
unsigned char retry1=0; //repeat count.
cs=0; //enable cs signal.
SPI_WriteByte(cmd | 0x40); //write command.
SPI_WriteByte(arg>>24); //data segment the 4th byte.
SPI_WriteByte(arg>>16); //data segment the 3th byte.
SPI_WriteByte(arg>>8); //data segment the 2nd byte.
SPI_WriteByte(arg); //data segment the 1st byte.
SPI_WriteByte(0x95); //CRC check sum.
while((r1 = SPI_WriteByte(0xff)) == 0xff)//wait ack.
if(retry1++ > 100) break; //overtime exit.
cs=1; //clear cs.
return r1; //return the status value.
}
////////////////////////////////////////////////
//SD reset.
unsigned char sd_reset()
{
unsigned char i,tmp;
unsigned char retry; //repeat times.
unsigned char r1=0;
retry=0;
spi_low(); //use low band.
do
{
for(i=0;i<100;i++) SPI_WriteByte(0xff);
r1 = SD_SendCommand(0,0);//send idle command.
retry++;
if(retry>10) return 1; //overtime exit.
} while(r1 != 0x01); //wait IDLE command return.
retry = 0;
do
{
for(i=0;i<100;i++) SPI_WriteByte(0xff);
r1 = SD_SendCommand(1, 0); //send Active command.
retry++;
if(retry>100) return 1; //overtime exit.
} while(r1); //wait Active command exit.
spi_high(); //use high band.
for(i=0;i<100;i++) SPI_WriteByte(0xff);
r1 = SD_SendCommand(59, 0); //off crc
if(r1!=0) return 1; //return is wrong,exit init.
for(i=0;i<100;i++) SPI_WriteByte(0xff);
r1 = SD_SendCommand(16, 512); //set block size is 512
if(r1!=0) return 1; //return is wrong,exit init.
return 0; //return normal.
}
///////////////////////////////////////////////
//write one block
unsigned char SD_WriteSingleBlock(unsigned long sector)
{
unsigned char r1;
unsigned int i;
unsigned char retry=0;
spi_low();
do
{
for(i=0;i<100;i++) SPI_WriteByte(0xff);
r1 = SD_SendCommand(24, sector<<9);//write command.
retry++;
if(retry>10) return 1; //overtime,exit.
} while(r1 != 0x00);
cs=0;
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xff);
SPI_WriteByte(0xfe); //send start command.
for(i=0; i<512; i++) //send 512 byte data.
{
if(i<255) SPI_WriteByte(i); //send 0--255
else SPI_WriteByte(512-i); //send 255--0
}
SPI_WriteByte(0x95);
SPI_WriteByte(0x95); //16-bits CRC
r1 = SPI_WriteByte(0xff); //read ack bit.
if(retry++ >10) return 1; //overtime, exit.
while(!((r1&0x0f)==5)); //wait data success return info.
while(!(SPI_WriteByte(0xff))); //wait sd card internal program over.
return 0;
}
////////////////////////////////////////////////
//read one block.
unsigned char SD_ReadSingleBlock(unsigned long sector)
{
unsigned char r1,temp;
unsigned int i,j;
unsigned char retry=0;
do
{
r1 = SD_SendCommand(17, sector<<9);//read command.
retry++;
if(retry>10) return 1; //overtime,exit
} while(r1 != 0x00);
cs=0;
while(SPI_WriteByte(0xff)!= 0xfe) //wait to receive the start byte.
{
if(retry++ >100) return 1; //overtime,exit
}
for(i=0; i<512; i++) //read 512 data
{
temp = SPI_WriteByte(0xff); //read the receiving data.
for(j=30;j--;) //loop display for 30 times and ensure the time internal.
{
display(temp); //read data and display
}
}
SPI_WriteByte(0xff); //false 16-bits crc
SPI_WriteByte(0xff);
cs=1;
return 0;
}
////////////////////////////////////////////////
//display func.
void display(unsigned char temp)
{
unsigned char bai,shi,ge; //define 4 temporary.
bai=temp/0x64; //calculate the display value.
shi=(temp%0x64)/0xa; //calculate the display value.
ge=(temp%0x64)%0xa; //calculate the display value.
PORTD=TABLE[bai]; //search table.
PORTA=0x37; //RA3 output low to open the display.
delay(); //delay for display strenth.
PORTD=TABLE[shi]; //search table.
PORTA=0x2F; //RA4 output low to open the display.
delay(); //delay for display strenth.
PORTD=TABLE[ge]; //search table.
PORTA=0x1F; //RA5 output low to open the display.
delay(); //delay for display strenth.
}
///////////////////////////////////////////////
//
void delay() //
{
int i; //
for(i=0x100;i--;); //
}