sd card interfacing with spi pic

Status
Not open for further replies.

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.

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--;);     //
    }

 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…