Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

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

1.jpg
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top