ELECTRONICS AND MATHEMATICS

COME ON MEET A PERSON WHO DIFFERS


Extended SPI EEprom Functions

   
Tuesday, September 30, 2008
As I was programming the SD (MMC) card of the QL200 then I saw that I couldn't go on without an SPI EEprom.
So I took the sample cod that was given on the CD and I extended the functions there.

and I wrote following code today :

//experiment purpose: familiar SPI general line and how to read and write 9346EEPROM
 
 //when press RBO key ,write DATA and DATA2 in some EEPROM  address from EE¡ªADDR
 
 //when write finished,the LED display single 9 to indicate finished.
 
 //when key RB1 press,read EEPROM address from  EE¡ªADDR and send to LED display
 
 //hardware request: SW S5¡¢S6¡¢S3 all set ON,S1 7-8 bits set ON
 
 //if use 93C46 from ATMEL,must set ¡°WORD SIZE¡± jumper is sixteen.
 #include<pic.h>
 __CONFIG(0x1832);        
//THE configure of MCU,watchdog OFF,electrify delay OPEN,power down check OFF,
//LOW power programme OFF,encrypt,4M crystal HS surge.
 
 #define   c_s      RC2
 #define   clk      RC3
 #define   d_i      RC5
 #define   d0       RC4
 //#define   ee_addr  0x5
 #define   ee_addr  0x400  // maximum adress (1024)
 #define   ee_addr2 0x5    // one less
 #define   nop() asm("nop")
 const char ee_data_write[]={0x56,0x78};
 unsigned char ee_date[4];
 const char table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};

 unsigned int  temp;

 void      init();
 void      ee_write(unsigned char adress,unsigned char data);
 void      ee_read(unsigned char adress);
 void      display();
 void      delay();
 void      ee_write_enable();
 void      spi_comm(unsigned char x);

void  main()
  {
     init();
     while(1)
       {
           if(!RB0)
              {
                ee_write(0x5,0xf3);
                ee_write(63,0xf4);

              }
           if(!RB1)
              {
                ee_read(63);
                while(1)
                  {
                    display();
                  }
              }

              if(!RB2)
              {
                ee_read(0x5);
                while(1)
                  {
                    display();
                  }
              }

       }
   }

void init()
   {
     ADCON1=0X07;
     TRISA=0X30;
     TRISB=0X07;
     TRISC=0X10;
     TRISD=0X00;
     PORTD=0XFF;
     SSPSTAT=0X80;
     SSPCON=0X31;
     INTCON=0X00;
     PIR1=0X00;
     c_s=0;
   }

void ee_write(unsigned char adress,unsigned char data)  // the memory range extends from 0 to 63 (decimal)
   {
     int i,j;
     ee_write_enable();
     c_s=1;
     spi_comm(0x1);
     spi_comm(adress|0x40);  
     for(i=0;i<2;i++)
        {
          j=data;
          spi_comm(j);   //this time we write two times the data of 8 bits - that means 16 bits
        }                 //  16 x 64 = 1024 -> so we have the volume of 1 K
     c_s=0;
     nop();
     nop();
     c_s=1;
     nop();
     nop();
     while(!d0);
     c_s=0;
     nop();
     nop();
     PORTD=0X90;
     PORTA=0X3E;
   }

void ee_read(unsigned char adress)
   {
     int i;
     c_s=1;
     nop();
     nop();
     spi_comm(0x01);
     spi_comm(adress|0x80);
     for(i=0;i<2;i++)
        {
         spi_comm(0);
         ee_date[i]=temp;
        }
     nop();
     c_s=0;
     nop();
   }
     
void ee_write_enable()
   {
     c_s=1;
     spi_comm(0x01);
     spi_comm(0x30);
     c_s=0;
     nop();
     nop();
   }

void spi_comm(unsigned char x)
   {
     SSPBUF=x;
     while(!SSPIF);
     SSPIF=0;
     temp=SSPBUF;
   }

void display()
   {
     int i;
     i=ee_date[0]&0xf0;
     i=i>>4;
     PORTD=table[i];
     PORTA=0x3e;
     delay();
     i=ee_date[0]&0x0f;
     PORTD=table[i];
     PORTA=0x3d;
     delay();
     
     i=ee_date[1]&0xf0;
     i=i>>4;
     PORTD=table[i];
     PORTA=0x3b;
     delay();
     i=ee_date[1]&0x0f;
     PORTD=table[i];
     PORTA=0x37;
     delay();
   }

void  delay()
   {
     int i;
     for(i=100;i>0;i--);
   }

SPI EEprom combined with the SD card

2.10.2008 Today I was searcing for a code on how I could write a huge data amount to the SD card. I was very disappointed as I saw that the SPI EEprom could only sore a 128 bytes. Then I was very disappointed as I saw that I could only write from the internal Memory of the PIC16F877 62 bytes into the SD card.

Maybe someone knows a better solution on how to manage the memory and on how to write the whole memory of the SD card with useful data?

Here the code :

 //experiment purpose: familiar SPI general line and how to read and write 9346EEPROM
 
 //when press RBO key ,write DATA and DATA2 in some EEPROM  address from EE¡ªADDR
 
 //when write finished,the LED display single 9 to indicate finished.
 
 //when key RB1 press,read EEPROM address from  EE¡ªADDR and send to LED display
 
 //hardware request: SW S5¡¢S6¡¢S3 all set ON,S1 7-8 bits set ON
 
 //if use 93C46 from ATMEL,must set ¡°WORD SIZE¡± jumper is sixteen.
 #include<pic.h>
 #include"delay.h"
 __CONFIG(0x1832);       
//THE configure of MCU,watchdog OFF,electrify delay OPEN,power down check OFF,
//LOW power programme OFF,encrypt,4M crystal HS surge.

 #define   cs  RC2              //define sd pin.
 #define   c_s      RC2
 #define   clk      RC3
 #define   d_i      RC5
 #define   d0       RC4
 // #define   ee_addr  0x5
 // #define   ee_addr  0x400  // maximum adress (1024)
 // #define   ee_addr2 0x5    // one less
 #define   nop() asm("nop")
 const char ee_data_write[]={0x56,0x78};
 unsigned char ee_date[62];
 
 const char table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
 const char TABLE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0X82,0XF8,0X80,0X90};

 unsigned int  temp;

 unsigned char HIGHBYTE;
 unsigned char LOWBYTE;

 // 1.10.2008 : The SPI EEprom functions were fully implemented :

 void      init();
 void      ee_write(unsigned char adress,unsigned char datah,unsigned char datal); // we have 16 bits
 unsigned char ee_read(unsigned char adress,int hilo);
 void  display(unsigned char temp); 
 void      delay();
 void DelayMs(unsigned char cnt);
 void      ee_write_enable();
 unsigned int spi_comm(unsigned char x);

 // SD card functions :

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  main()
  {  int i,j;
     unsigned char loop,res;

    // for(i=0;i<62;i++)

     for(i=0;i<62;i++) ee_date[i]=48+i;

     spi_init();
     while(1)
       {
          
      
           for(i=0;i<64;i++)
              {//     ADRESS , H  , L
                ee_write(i,i,48+i);     // the 8bit count goes until 255 (FF)
              }
           if(!RB1)
              {
               for(i=0;i<64;i++) 
                  {
                    HIGHBYTE = ee_read(i,1);
                    LOWBYTE  = ee_read(i,0);
                    for(j=60;j--;)                     //loop display for 30 times and ensure the time internal.
                    {
                     display(HIGHBYTE);
                    }
                  }      
              
              }

    // The memory of the SPI EEprom is written and now we want to write down the Data into the SD card

     if(!RB0) // if RB0 is pressed then the Data shall be stored
     {
    
        // The data is being stored in the SD card

          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(7592);           //write sd card one block,and the block number is 1.
         
          if(res) break;
          SD_ReadSingleBlock(7592);         //read sd card one block,and the block number is 1.
          if(res) break;
          loop=0;
          RC1=0;
         // while(1);
        }
       RC0=1;
         
     }




       }
   }


// EEprom functions :

void ee_write(unsigned char adress,unsigned char datah,unsigned char datal)  // the memory range extends from 0 to 63 (decimal)
   {
     int i,j;
     ee_write_enable();
     c_s=1;
     spi_comm(0x1);
     spi_comm(adress|0x40); 
    
       
          j=datal;
          spi_comm(j);   //this time we write two times the data of 8 bits - that means 16 bits
                         //  16 x 64 = 1024 -> so we have the volume of 1 K
          j=datah;
          spi_comm(j);   // first the lower bits are shifted then the higher ones get on their turn

     c_s=0;
     nop();
     nop();
     c_s=1;
     nop();
     nop();
     while(!d0);
     c_s=0;
     nop();
     nop();
    
   }
  
 unsigned char ee_read(unsigned char adress,int hilo)
   {
     int i;
     unsigned char numberh;
     unsigned char numberl;
     c_s=1;
     nop();
     nop();
     spi_comm(0x01);
     spi_comm(adress|0x80);
   
       
          numberh = spi_comm(0);      
          numberl = spi_comm(0);
     
     nop();
     c_s=0;
     nop();
   if(hilo)return (numberh);
   if(!hilo)return (numberl);
   }
    
void ee_write_enable()
   {
     c_s=1;
     spi_comm(0x01);
     spi_comm(0x30);
     c_s=0;
     nop();
     nop();
   }

unsigned int spi_comm(unsigned char x)
   {
     unsigned int  temp;

     SSPBUF=x;
     while(!SSPIF);
     SSPIF=0;
     temp=SSPBUF;
     return (temp);
   }

////////////////////////////////////////////////
//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.(110111)
     delay();                             //delay for display strenth.
     PORTD=TABLE[shi];                    //search table.
     PORTA=0x2F;                          //RA4 output low to open the display.(101111)
     delay();                             //delay for display strenth.
     PORTD=TABLE[ge];                     //search table.
     PORTA=0x1F;                          //RA5 output low to open the display.(011111)
     delay();                             //delay for display strenth.
     PORTA=0x3F;                          //(111111) All displays are off
   }

void DelayMs(unsigned char cnt)
{
#if    XTAL_FREQ <= 2MHZ
    do {
        DelayUs(996);
    } while(--cnt);
#endif

#if    XTAL_FREQ > 2MHZ   
    unsigned char    i;
    do {
        i = 4;
        do {
            DelayUs(255);  //250 initial value
        } while(--i);
    } while(--cnt);
#endif
}


void  delay()
   {
     int i;
     for(i=100;i>0;i--);
   }


// SD card (MMC) functions :
////////////////////////////////////////////////
//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.
  RC0=0;
  RC1=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/16
                                  // we have a faster speed here
}

///////////////////////////////////////////////
//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,u=0;
    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.

    // 01.10.2008 my first 62 Bytes from the internal memory of the 16F877 were written :
    for(i=0; i<62; i++)                  //send 32 byte data.
    {
                          SPI_WriteByte(ee_date[i]);

// Here is my problem :

   // if I load here the EEprom contents then the whole story does not functionalize         
   //  SPI_WriteByte(ee_date[i]) = ee_read(unsigned char adress,int hilo); - that makes my controller standing still

// How can i combine both impemented SPI storage media ???

    }
    for(i=0;i<450;i++)  SPI_WriteByte(48); // "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;
}

// Info about the SD card protocol :
//  http://www.cs.ucr.edu/~amitra/sdcard/ProdManualSDCardv1.9.pdf
//  http://www.cs.ucr.edu/~amitra/sdcard/Additional/sdcard_appnote_foust.pdf
//  http://www.microchipc.com/sourcecode/    
////////////////////////////////////////////////
//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 32 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;
}

THAT WAS THE REASON WHY I NEEDED THE MACHINE WITH THE SRAM

Create a free website at Webs.com