title: How to read from and write to EEPROM suing SPI communication
body: <p>I am using PIC32MX350F128L Microcontroller to read from and write to EEPROM(SST26VF032B) using SPI communication. SPI communication in this program is working, I have checked it by sending JEDEC code which is provided in the SST26VF032B datasheet. So when i send 0x9F i am getting 3 bytes of data as mentioned in the datasheet. When i run now i am sending a string of data to a specific address of eeprom  and getting 0xff in return. I am erasing the eeprom before writing into it. So i think i am getting 0xff after erasing the eeprom. The writing, reading operations are not working. If i send a string of value or a BYTE i am getting 0xff in return. So can u guys please suggest me where i am going wrong. I am using UART for debugging purpose to read values recieved through spi communication. The complete code is below, i am using MPLAB X.</p>
  
  <p>Best Regards</p>
  
  <p>Sandesh</p>
  
  <pre><code>#include &lt;xc.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;plib.h&gt;
  #include &lt;p32xxxx.h&gt;
  
  
  /* Configuration Bits */
  
  #pragma config FSRSSEL = PRIORITY_7     // Shadow Register Set Priority Select (SRS Priority 7)
  #pragma config PMDL1WAY = ON            // Peripheral Module Disable Configuration (Allow only one reconfiguration)
  #pragma config IOL1WAY = ON             // Peripheral Pin Select Configuration (Allow only one reconfiguration)
  
  // DEVCFG2
  #pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
  #pragma config FPLLMUL = MUL_20         // PLL Multiplier (20x Multiplier)
  #pragma config FPLLODIV = DIV_1        // System PLL Output Clock Divider (PLL Divide by 1)
  
  // DEVCFG1
  #pragma config FNOSC = PRIPLL             // Oscillator Selection Bits (Primary Osc (XT,HS,EC))
  #pragma config FSOSCEN = ON             // Secondary Oscillator Enable (Enabled)
  #pragma config IESO = ON                // Internal/External Switch Over (Enabled)
  #pragma config POSCMOD = HS            // Primary Oscillator Configuration (XT osc mode)
  #pragma config OSCIOFNC = ON            // CLKO Output Signal Active on the OSCO Pin (Enabled)
  #pragma config FPBDIV = DIV_1          // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/8)
  #pragma config FCKSM = CSECME           // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
  #pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
  #pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
  #pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
  #pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)
  
  // DEVCFG0
  #pragma config DEBUG = OFF              // Background Debugger Enable (Debugger is Disabled)
  #pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
  #pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
  #pragma config PWP = OFF                // Program Flash Write Protect (Disable)
  #pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
  #pragma config CP = OFF                 // Code Protect (Protection Disabled)
  
  /* MACRO DEFINITIONS */
  
  /* Defining the Slave Select Pin */
  #define SS      LATDbits.LATD9
  
  /* Defining the System Clock Frequency */
  #define SYSCLK  40000000
  
   /* Macro to get array size in bytes
   * note that array size can't be found after passing pointer to a function */
  #define LEN(x)  (sizeof(x) / sizeof(x[0]))
  
  /* SST26VF032B EEPROM instructions */
  
  /* Write Enable */
  #define WREN    0x06   
  
  /* Write Disable */
  #define WRDI    0x04   
  
  /* Initialize Start of Write Sequence */
  #define WRITE   0x02    
  
  /* Initialize Start of Read Sequence */
  #define READ    0x03  
  
  /*  Erase all sectors of Memory */
  #define CE      0xc7   
  
  /*  Read STATUS Register */
  #define RDSR    0x05   
  
  /* Function Prototypes */
  
  /* UART bit configuration */
  void Bitconfig_uart(void);
  
  /* SPI Initialization */
  void SPI1_Init(void);
  
  /* UART Initialization */
  void Init_uart(void);
  
  /* Send a Character Byte through UART */
  void UART5PutChar(char Ch);
  
  /* Function to Read and Write SPI1 buffer */
  int SPI1_transfer( int b);
  
  /* Function to check the Status of SPI */
  void waitBusy();
  
  /* Function to erase the contents in EEPROM */
  void eraseEEPROM();
  
  /* Function to Read data from EEPROM */
  void readEEPROM( int address, char* loadArray, int loadArray_size);
  
  /* Function to Write to EEPROM */
  void writeEEPROM( int address, char* storeArray, int storeArray_size);
  
  /* Global Variables Declaration */
  /* Declare variables to check the functionality of EEPROM */
  int i,j = 0;
  char st = 0x9F;
  char rec;
  int x,y,z;
  
  /*******************************************************************************
  * Function Name: main()
  ********************************************************************************
  * Summary:
  *  Initializes SPI
  *  Erase EEPROM
  *  Writes to EEPROM
  *  Read from EEPROM
  *
  * Parameters:
  *  None.
  *
  * Return:
  *  None.
  *
  *******************************************************************************/
  int main()
  {    
  
      int i;
      /* Clock Setting */
      SYSTEMConfigPerformance(SYSCLK);
  
      /* UART bit configuration */
      Bitconfig_uart();
  
      /* Set the Controller OScillator Register bits */
      //OSCCON = 0x00002200;
  
      /* Initialize a String to Write to EEPROM and an array to Read back contents */
      char writeData[] = "123456789ABCDEF";
  
      /* Array to read 35 bytes of data */
      char readData[15];
  
      /* SPI Initialization */
      SPI1_Init();
  
      /* UART Initialization */
      Init_uart();
  
      /* Erase contents of EEPROM */
      eraseEEPROM();
  
      /* Write contents of writeData array to address 180 */
      writeEEPROM( 0x1000, writeData, LEN(writeData));
  
      /*
       JEDEC Code (working) getting output as per datasheet (0x9F = 159)
      SS=0;
      SPI1_transfer(159);
      x=SPI1_transfer(0);
      UART5PutChar(x);
      y=SPI1_transfer(0);
      UART5PutChar(y);
      z=SPI1_transfer(0);
      UART5PutChar(z);
      */
      while(1)
      {   
          /* Read contents of EEPROM into readData array
           * start at address 180 and read up to 180+length(readData) */
          readEEPROM( 0x1000, readData, LEN(readData) );
      }
  } /* END main() */
  
  /*******************************************************************************
  * Function Name: SPI1_Init()
  ********************************************************************************
  * Summary:
  *  SPI1 Initialization
  *
  * Parameters:
  *  None.
  *
  * Return:
  *  None.
  *
  *******************************************************************************/
  void SPI1_Init(void)
  {
      /* Configure Peripheral Pin Select (PPS) for the SPI1 module
      * Note: SS will be toggled manually in code
      * SCK is hardwired to pin 55 */
  
      /* Output Pin Selection */
      RPE5R = 8;
      SDI1R = 3;
  
      /* RB4 (Slave Select 1) : output */
      TRISDbits.TRISD9 = 0;      
  
      /* SPI configuration */
  
      /* SPI1CON Register Configuration
       * MSTEN: Master Mode Enable bit = 1 (Master)
       * CKP (clock polarity control) = 0
       * CKE (clock edge control) = 1
       * ON: SPI Peripheral On bit
       * 8-bit, Master Mode */
      SPI1CON = 0x8120;
  
      /* SPI1BRG Register Configuration */
      SPI1BRG = 0x4D;
      //REFOCONbits.ON = 1;
     // REFOCONbits.DIVSWEN = 1;
  }
  
  /*******************************************************************************
  * Function Name: SPI1_transfer()
  ********************************************************************************
  * Summary:
  *  Write to and Read from SPI1 buffer
  *
  * Parameters:
  *  char b - Writes a Character to Buffer
  *
  * Return:
  *  Char - Returns the Character Read from EEPROM
  *
  *******************************************************************************/
  int SPI1_transfer( int b)
  {
      /* write to buffer for TX */
      SPI1BUF = b;    
  
      /* wait transfer complete */
      while(!SPI1STATbits.SPIRBF);       
  
      /* read the received value */
      return SPI1BUF;                    
  } /* END SPI1_transfer() */
  
  
  /*******************************************************************************
  * Function Name: waitBusy()
  ********************************************************************************
  * Summary:
  *  Checks if EEPROM is ready to be modified and waits if not ready
  *
  * Parameters:
  *  None.
  *
  * Return:
  *  None.
  *
  *******************************************************************************/
  void waitBusy()
  {
      char status = 0;
  
      do{
          /* Select EEPROM */
          SS = 0;
  
          /* Read EEPROM status register */
          SPI1_transfer(RDSR);       
  
          /* send dummy byte to receive incoming data */
          status = SPI1_transfer(0);  
  
          /* Release EEPROM */
          SS = 1;                           
      }
  
      /* write-in-progress while status&lt;0&gt; set to '1' */
      while( status &amp; 0x01);            
  
  } /* END waitBusy() */
  
  
  
  
  /*******************************************************************************
  * Function Name: readEEPROM()
  ********************************************************************************
  * Summary:
  * Reads data from EEPROM
  *
  * Parameters:
  * Inputs:  address - EEPROM address
  *          loadArray - array to load EEPROM data to
  *          loadArray_size - number of bytes of EEPROM data to load into array
  *
  * Return:
  *  None.
  *
  *******************************************************************************/
  void readEEPROM( int address, char* loadArray, int loadArray_size)
  {
      int i;
  
      /* Wait until EEPROM is not busy */
      waitBusy();
  
      /* Select EEPROM */
      SS = 0;                 
  
      /* Initiate Read */
      SPI1_transfer( READ);        
  
      /* Address must be 16-bits but we're transferring it in two 8-bit sessions */
      SPI1_transfer( address &gt;&gt; 16);
      SPI1_transfer( address &gt;&gt; 8);  
      SPI1_transfer( address);       
  
      /* Request and store loadArray_size number of bytes into loadArray */
      for( i=0 ; i&lt;loadArray_size ; i++)
      {
          /* send dummy byte to read 1 byte */
          loadArray[i] = SPI1_transfer( 0x00);   
      }
      /* Release EEPROM */
      SS = 1;                        
  
          /* UART Test */
          for(i=0;i&lt;35;i++)
          {
              UART5PutChar(loadArray[i]);
              for(j=0;j&lt;20000;j++)
              {}
          }
  
  } /* END readEEPROM() */
  
  /*******************************************************************************
  * Function Name: writeEEPROM()
  ********************************************************************************
  * Summary:
  * Write data to EEPROM
  *
  * Parameters:
  * Inputs:  address -  EEPROM address
  *          storeArray - array of which contents are stored in EEPROM
  *          storeArray_size - number of bytes in array to store into EEPROM
  *
  * Return:
  *  None.
  *
  *******************************************************************************/
  
  void writeEEPROM( int address, char* storeArray, int storeArray_size)
  {
      int i;
  
      /* Wait until EEPROM is not busy */
      waitBusy();
  
      /* Select EEPROM */
      SS = 0;
  
      /* Send WRITE_ENABLE command */
      SPI1_transfer( WREN);
  
      /* Release EEPROM */
      SS = 1;                
  
      /* Select EEPROM again after WREN cmd */
      SS = 0;
  
      /* Initiate Write */
      SPI1_transfer( WRITE);
  
      SPI1_transfer( address &gt;&gt; 16 );
      SPI1_transfer( address &gt;&gt; 8 );
      SPI1_transfer( address );
  
      /* write 1 byte at a time from array */
      /* MSB at lowest address (0 - first letter in string) */
      for( i=0 ; i&lt;storeArray_size; i++)
      {
              /* Initiate Write */
              SPI1_transfer( WRITE);
              SPI1_transfer( (address+i) &gt;&gt; 16 );
              SPI1_transfer( (address+i) &gt;&gt; 8 );
              SPI1_transfer( address+i );
  
          SPI1_transfer( storeArray[i]);
      }
      /* Release EEPROM */
      SS = 1;                       
  
  } /* END writeEEPROM() */
  
  /*******************************************************************************
  * Function Name: eraseEEPROM()
  ********************************************************************************
  * Summary:
  * Erase entire contents of EEPROM
  *
  * Parameters:
  *  None
  *
  * Return:
  *  None.
  *
  *******************************************************************************/
  void eraseEEPROM()
  {
      /* Wait until EEPROM is not busy */
      waitBusy();
  
      /* Select EEPROM */
      SS = 0;               
  
      /* Send WRITE_ENABLE command */
      SPI1_transfer( WREN);  
  
      /* Release EEPROM */
      SS = 1;                
  
      /* Select EEPROM again after WREN cmd */
      SS = 0;            
  
      /* send CHIP_ERASE command */
      SPI1_transfer( CE);   
  
      /* Release EEPROM */
      SS = 1;                
  
  } /* END eraseEEPROM() */
  
  /*******************************************************************************
  * Function Name: Init_uart()
  ********************************************g************************************
  * Summary:
  * Initialize UART4
  *
  * Parameters:
  *  None
  *
  * Return:
  *  None.
  *
  *******************************************************************************/
  void Init_uart()
  {
      /* Enable UART */
     U5MODEbits.ON = 1 ;
  
     /* set baud rate(9600) */
     U5BRG = 521;
  
     /* Set U4STA Register for Enabling tx and rx */
     U5STA=0x9400;
  
  }
  
  /*******************************************************************************
  * Function Name: UART4PutChar(unsigned char Ch)
  ********************************************************************************
  * Summary:
  * Send data from controller to putty GUI
  *
  * Parameters:
  * input
  * unsigned char Ch -  To Send a byte of data over UART
  *
  * Return:
  *  None.
  *
  *******************************************************************************/
  void UART5PutChar(char Ch)
  {
  while(U5STAbits.UTXBF == 1);
  U5TXREG=Ch;
  }
  
  /*******************************************************************************
  * Function Name: Bitconfig_uart()
  ********************************************************************************
  * Summary:
  * UART Pin Configuration
  *
  * Parameters:
  *  None
  *
  * Return:
  *  None.
  *
  *******************************************************************************/
  void Bitconfig_uart(void)
  {
      /* UART4 Initialization */
     // OSCCON=0x00002200;
  
      /* Set pins as digital */
      ANSELBbits.ANSB2 = 0;
      ANSELBbits.ANSB0 = 0;
  
      /* Set UART Tx pin as Output */
      TRISBbits.TRISB0 = 0;  //in controler tx
      TRISBbits.TRISB2 = 1; // in controller RX    
  
  
      /* Peripheral Pin select for UART4 */
      U5RXR=0x07;
      RPB0R=0x04;   
  }
  </code></pre>