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.

[SOLVED] SST25VF016B cannot write data

Status
Not open for further replies.

Ser35

Newbie level 4
Joined
Dec 28, 2015
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
85
Hello,

My first post here. I am having trouble with a SPI flash, SST25VF016B, in that I am unable to save any data at all. It is driven by a PIC16F1719 microcontroller acting as the Master.

So far, I can execute the following commands: Read-ID, JEDEC-ID, WREN, WRSR, WRDI and Read the Status Register. I can modify the status register, and can confirm that it works using the Pickit 3 and MPLAB X.

When I read data at 'X-X-X H' address, I get the 0xFF value, not the one I am expecting after saving some data at that address.

Any ideas or suggestions that I can do to fix this? Thanks

Ser
 

Take this example. It 100% works with SST25VF016x. I tested.
Code:
/******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
* File Name          : spi_flash.c
* Author             : MCD Application Team
* Version            : V1.1
* Date               : 11/26/2007
* Description        : This file provides a set of functions needed to manage the
*                      communication between SPI peripheral and SPI M25P64 FLASH.
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "spi_flash.h"

/* Private typedef -----------------------------------------------------------*/
#define SPI_FLASH_PageSize 256

#define WRITE      0x02  /* Write to Memory instruction */
#define WRSR       0x01  /* Write Status Register instruction */ 
#define WREN       0x06  /* Write enable instruction */
#define WRDI			 0x04

#define READ       0x03  /* 25Mhz Read from Memory instruction */
#define HREAD      0x0B  /* 80Mhz Read from Memory instruction */
#define RDSR       0x05  /* Read Status Register instruction  */
#define RDID       0x9F  /* Read identification */
#define SE         0xD8  /* Sector Erase instruction */
#define BE         0xC7  /* Bulk Erase instruction */
#define EWSR			 0x50
#define EBSY			 0x70
#define DBSY			 0x80
#define AII			   0xAD

#define WIP_Flag   0x01  /* Write In Progress (WIP) flag */

#define Dummy_Byte 0xA5

/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/*******************************************************************************
* Function Name  : SPI_FLASH_Init
* Description    : Initializes the peripherals used by the SPI FLASH driver.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
   
  /* Enable SPI2, GPIOA and GPIOBclocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
	
  /* Configure SPI2 pins: SCK and MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	/* Configure SPI2 pin: MISO */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* Configure PB.2 as Output push-pull, used as Flash Chip select */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH;

  /* SPI2 configuration */ 
	SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode=SPI_Mode_Master;
	SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;
	SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;
	SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;
	SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;
	SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_2;
	SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;
	SPI_InitStructure.SPI_CRCPolynomial=7;
	SPI_Init(SPI2, &SPI_InitStructure);
  
  /* Enable SPI2  */
  SPI_Cmd(SPI2, ENABLE);   
}

/*******************************************************************************
* Function Name  : SPI_FLASH_SectorErase
* Description    : Erases the specified FLASH sector.
* Input          : SectorAddr: address of the sector to erase.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_SectorErase(u32 SectorAddr)
{
  /* Send write enable instruction */
  SPI_FLASH_WriteEnable();

  /* Sector Erase */ 
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW;
  /* Send Sector Erase instruction */
  SPI_FLASH_SendByte(SE);
  /* Send SectorAddr high nibble address byte */
  SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
  /* Send SectorAddr medium nibble address byte */
  SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
  /* Send SectorAddr low nibble address byte */
  SPI_FLASH_SendByte(SectorAddr & 0xFF);
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH;

  /* Wait the end of Flash writing */
  SPI_FLASH_WaitForWriteEnd();
}

/*******************************************************************************
* Function Name  : SPI_FLASH_BulkErase
* Description    : Erases the entire FLASH.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_BulkErase(void)
{
  /* Send write enable instruction */
  SPI_FLASH_WriteEnable();

  /* Bulk Erase */ 
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW;
  /* Send Bulk Erase instruction  */
  SPI_FLASH_SendByte(BE);
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH;

  /* Wait the end of Flash writing */
  SPI_FLASH_WaitForWriteEnd();
}

/*******************************************************************************
* Function Name  : SPI_FLASH_PageWrite
* Description    : Writes more than one byte to the FLASH with a single WRITE
*                  cycle(Page WRITE sequence). The number of byte can't exceed
*                  the FLASH page size.
* Input          : - pBuffer : pointer to the buffer  containing the data to be 
*                    written to the FLASH.
*                  - WriteAddr : FLASH's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the FLASH,
*                    must be equal or less than "SPI_FLASH_PageSize" value. 
* Output         : None
* Return         : None
*******************************************************************************/
u8 SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
	u8 * pBufferStart;
	pBufferStart = pBuffer;
	SPI_FLASH_SendCMD(EWSR); //0x50
	
	SPI_FLASH_WriteReg(WRSR, 0x00); //0x01 0x00 write status CMD - disable write protection
	
	SPI_FLASH_SendCMD(EBSY); //0x70
	
  SPI_FLASH_SendCMD(WREN); //0x06 write enable
	 
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW;

	SPI_FLASH_SendByte(0xAD);
  /* Send WriteAddr high nibble address byte to write to */
  SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
  /* Send WriteAddr medium nibble address byte to write to */
  SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);  
  /* Send WriteAddr low nibble address byte to write to */
  SPI_FLASH_SendByte(WriteAddr & 0xFF);
	
  SPI_FLASH_SendByte(*pBuffer++);
	SPI_FLASH_SendByte(*pBuffer++);
	
  /* while there is data to be written on the FLASH */
  while(pBuffer < pBufferStart + NumByteToWrite) 
  {
		SPI_FLASH_CS_HIGH;
		SPI_FLASH_CS_LOW;
		while (SPI_FLASH_SendByte(0xFF) != 0xFF){};
			
		SPI_FLASH_CS_HIGH;
		SPI_FLASH_CS_LOW;	
			
		SPI_FLASH_SendByte(0xAD);
		SPI_FLASH_SendByte(*pBuffer++);
		SPI_FLASH_SendByte(*pBuffer++);		
  }
  /* Deselect the FLASH: Chip Select high */
	SPI_FLASH_CS_HIGH;
	SPI_FLASH_CS_LOW;		
	while (SPI_FLASH_SendByte(0xFF) != 0xFF){};		
  SPI_FLASH_CS_HIGH;
	
	SPI_FLASH_SendCMD(WRDI);
	
	SPI_FLASH_SendCMD(DBSY);
  
	return SPI_FLASH_WriteReg(RDSR, 0);
}

/*******************************************************************************
* Function Name  : SPI_FLASH_BufferWrite
* Description    : Writes block of data to the FLASH. In this function, the
*                  number of WRITE cycles are reduced, using Page WRITE sequence.
* Input          : - pBuffer : pointer to the buffer  containing the data to be 
*                    written to the FLASH.
*                  - WriteAddr : FLASH's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the FLASH.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
  u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;

  Addr = WriteAddr % SPI_FLASH_PageSize;
  count = SPI_FLASH_PageSize - Addr;
  NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
  NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
  
  if(Addr == 0) /* WriteAddr is SPI_FLASH_PageSize aligned  */
  {
    if(NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
    {
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
    }
    else /* NumByteToWrite > SPI_FLASH_PageSize */ 
    {
      while(NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;  
      }    
     
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
   }
  }
  else /* WriteAddr is not SPI_FLASH_PageSize aligned  */
  {
    if(NumOfPage== 0) /* NumByteToWrite < SPI_FLASH_PageSize */
    {
      if(NumOfSingle > count) /* (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize */
      {
        temp = NumOfSingle - count;
      
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
        WriteAddr +=  count;
        pBuffer += count; 
        
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
      }
      else
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
      }
    }
    else /* NumByteToWrite > SPI_FLASH_PageSize */
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
      NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
      
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
      WriteAddr +=  count;
      pBuffer += count;  
     
      while(NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;
      }
      
      if(NumOfSingle != 0)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      }
    }
  }
}

/*******************************************************************************
* Function Name  : SPI_FLASH_BufferRead
* Description    : Reads a block of data from the FLASH.
* Input          : - pBuffer : pointer to the buffer that receives the data read 
*                    from the FLASH.
*                  - ReadAddr : FLASH's internal address to read from.
*                  - NumByteToRead : number of bytes to read from the FLASH.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
	SPI_FLASH_StartReadSequence(ReadAddr);
	
  while(NumByteToRead--) 
		*pBuffer++ = SPI_FLASH_SendByte(Dummy_Byte);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH;
}

/*******************************************************************************
* Function Name  : SPI_FLASH_ReadID
* Description    : Reads FLASH identification.
* Input          : None
* Output         : None
* Return         : FLASH identification
*******************************************************************************/
u32 SPI_FLASH_ReadID(void)
{
  u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;

  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW;
  
  /* Send "RDID " instruction */
  SPI_FLASH_SendByte(0x9F);

  /* Read a byte from the FLASH */
  Temp0 = SPI_FLASH_SendByte(Dummy_Byte);

  /* Read a byte from the FLASH */
  Temp1 = SPI_FLASH_SendByte(Dummy_Byte);

  /* Read a byte from the FLASH */
  Temp2 = SPI_FLASH_SendByte(Dummy_Byte);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH;
         
  Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

  return Temp;
}

/*******************************************************************************
* Function Name  : SPI_FLASH_StartReadSequence
* Description    : Initiates a read data byte (READ) sequence from the Flash.
*                  This is done by driving the /CS line low to select the device,
*                  then the READ instruction is transmitted followed by 3 bytes
*                  address. This function exit and keep the /CS line low, so the
*                  Flash still being selected. With this technique the whole
*                  content of the Flash is read with a single READ instruction.
* Input          : - ReadAddr : FLASH's internal address to read from.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_StartReadSequence(u32 ReadAddr)
{
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW;
  
  /* Send "Read from Memory " instruction */
  SPI_FLASH_SendByte(HREAD);

/* Send the 24-bit address of the address to read from -----------------------*/  
  /* Send ReadAddr high nibble address byte */
  SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
  /* Send ReadAddr medium nibble address byte */
  SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
  /* Send ReadAddr low nibble address byte */
  SPI_FLASH_SendByte(ReadAddr & 0xFF);
	
	SPI_FLASH_SendByte(0xFF);
}

/*******************************************************************************
* Function Name  : SPI_FLASH_ReadByte
* Description    : Reads a byte from the SPI Flash.
*                  This function must be used only if the Start_Read_Sequence
*                  function has been previously called.
* Input          : None
* Output         : None
* Return         : Byte Read from the SPI Flash.
*******************************************************************************/
u8 SPI_FLASH_ReadByte(void)
{
  return (SPI_FLASH_SendByte(Dummy_Byte));
}

/*******************************************************************************
* Function Name  : SPI_FLASH_SendByte
* Description    : Sends a byte through the SPI interface and return the byte 
*                  received from the SPI bus.
* Input          : byte : byte to send.
* Output         : None
* Return         : The value of the received byte.
*******************************************************************************/
u8 SPI_FLASH_SendByte(u8 byte)
{
    /* Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){};
	//while (!(SPI2->SR & 2));

  /* Send byte through the SPI1 peripheral */
 //SPI_I2S_SendData(SPIx, byte);
	SPI2->DR=byte;

  /* Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){};
	//while (!(SPI2->SR & 1));

  /* Return the byte read from the SPI bus */
  //return SPI_I2S_ReceiveData(SPIx);
	return SPI2->DR;
}

/*******************************************************************************
* Function Name  : SPI_FLASH_SendHalfWord
* Description    : Sends a Half Word through the SPI interface and return the  
*                  Half Word received from the SPI bus.
* Input          : Half Word : Half Word to send.
* Output         : None
* Return         : The value of the received Half Word.
*******************************************************************************/
u16 SPI_FLASH_SendHalfWord(u16 HalfWord)
{
  /* Loop while DR register in not emplty */
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);

  /* Send Half Word through the SPI2 peripheral */
  SPI_I2S_SendData(SPI2, HalfWord);

  /* Wait to receive a Half Word */
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

  /* Return the Half Word read from the SPI bus */
  return SPI_I2S_ReceiveData(SPI2);
}

/*******************************************************************************
* Function Name  : SPI_FLASH_WriteEnable
* Description    : Enables the write access to the FLASH.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_WriteEnable(void)
{
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW;
  
  /* Send "Write Enable" instruction */
  SPI_FLASH_SendByte(WREN);
  
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH;
}

void SPI_FLASH_SendCMD(u8 CMD)
{
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW;
  
  /* Send command instruction */
  SPI_FLASH_SendByte(CMD);
  
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH;
}

u8 SPI_FLASH_WriteReg(u8 Reg, u8 Value)
{
	u8 res;
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW;
  
  SPI_FLASH_SendByte(Reg);
	res = SPI_FLASH_SendByte(Value);
  
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH;
	
	return res;
}

/*******************************************************************************
* Function Name  : SPI_FLASH_WaitForWriteEnd
* Description    : Polls the status of the Write In Progress (WIP) flag in the  
*                  FLASH's status  register  and  loop  until write  opertaion
*                  has completed.  
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_WaitForWriteEnd(void)
{
  u8 FLASH_Status = 0;
  
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW;
  
  /* Send "Read Status Register" instruction */
  SPI_FLASH_SendByte(RDSR);
  
  /* Loop as long as the memory is busy with a write cycle */
  do
  {
    /* Send a dummy byte to generate the clock needed by the FLASH 
    and put the value of the status register in FLASH_Status variable */
    FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);

  } while((FLASH_Status & WIP_Flag) == SET); /* Write in progress */

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH;
}


/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/
 

SPI flash programming is pretty straightforward, but there may be a problem in your code though. Or you are inadvertently driving the write protect pin low.
 

Hello, thanks for the reply.

I checked the code posted by Easyrider83, and I cannot find the sequence for writing one byte (using 0x02 command).
Although I haven't tried the AII command for writing two bytes. Thank you for the code.

This is part of my code:

Code:
mySPI

    banksel SSP1STAT       ;bank select
    bsf	    SSP1STAT, SMP
    bsf	    SSP1STAT, CKE
    bcf	    SSP1CON1, CKP
    
    banksel SSP1CON1
    bsf	    SSP1CON1, 0   ;SCK : Fosc/16

    ;spi master Fosc/16 , fastest possible,  where Fosc = 32MHz
    ;SCK period: 2*( 4/Fosc +20ns) = 290ns or 3.448 MHz
    ;We need SCK at option Fosc/16 = 2MHz < 3.448 MHz


    banksel SSP1CON1
    bsf	    SSP1CON1, SSPEN
;...............................................
;send enable write enable command  
    call    write_enable
;...............................................
;Disable protection levels:    
 ;send write-status-register command  
    banksel LATD
    bcf	    LATD, LATD1	;CE# low 
    
    banksel byte_data
    movlw   0x01			;WRSR command	   
    movwf   byte_data

    call    SPI_Tx_Rx	   

    banksel byte_data
    movlw   b'0000000'	
    movwf   byte_data
    call    SPI_Tx_Rx      
    
    banksel LATD
    bsf	    LATD, LATD1	;CE# high // here WREL goes to zero
;................................................
;send enable write enable command  
    call    write_enable
;...............................................    
    call    poll_status_flash
;................................................
;send command for Byte write. WREN has already been enabled
    banksel byte_data		    
    movlw   0x02		    	;Byte-programming command	   
    movwf   byte_data		    
    call    SPI_Tx_Rx		    	    
				    
;send 3 byte of initial address
    banksel init_addr				    
    movf    init_addr+2, W	    ;high add. byte		    
    movwf   byte_data		    
    call    SPI_Tx_Rx		   
	
    banksel init_addr
    movf    init_addr+1, W	    ;mid add. byte	    
    movwf   byte_data		    
    call    SPI_Tx_Rx		    
	
    banksel init_addr
    movf    init_addr, W	    	   ;low add.	  byte  
    movwf   byte_data		    
    call    SPI_Tx_Rx		    

;send byte
    banksel audio_data
    movf    audio_data, W	  
  		    
    movwf   byte_data		    
    call    SPI_Tx_Rx		    
				    
    banksel LATD		    
    bsf	    LATD, LATD1	;CE# high   
;.....................................................
    call    poll_status_flash
;.....................................................

;read saved data
    
    banksel LATD		    
    bcf	    LATD, LATD1	;CE# low    

;send command for Read Byte.
    banksel byte_data		    
    movlw   0x03		    	;READ command	   
    movwf   byte_data		    
    call    SPI_Tx_Rx		    	    
				    
;send 3 byte of initial address
    movf    init_addr+2, W	   	;high ADD.	byte    
    movwf   byte_data		    
    call    SPI_Tx_Rx		    
				    
    movf    init_addr+1, W	    	 ;mid ADD.  byte 
    movwf   byte_data		    
    call    SPI_Tx_Rx		    
				    
    movf    init_addr, W	    		 ;low ADD. byte   
    movwf   byte_data		    
    call    SPI_Tx_Rx		    
				    
;read data				    
    movlw   0x00		    	    ;dummy byte
    movwf   byte_data		    

    call    SPI_Tx_Rx		    
    movwf   audio_data+1             ;save data

    
    banksel LATD		    
    bsf	    LATD, LATD1	;CE# high  

  return

;.....................................................
write_enable 
 
;send enable write enable command  
    banksel LATD
    bcf	    LATD, LATD1	;CE# low 
    
    banksel byte_data
    movlw   0x06			;WREN command	   
    movwf   byte_data

    call    SPI_Tx_Rx	   
    banksel LATD
    bsf	    LATD, LATD1	;CE# high
    nop
 
   return
;.......................................

SPI_Tx_Rx	
	 
;sends and receives 8-bits, command or data   

    banksel SSP1BUF	     ;PIC internal spi buffer
    movf    SSP1BUF ,W	     ;clear buffer
    
    banksel byte_data	    
    movf    byte_data, W    
    
    banksel SSP1BUF	    
    movwf   SSP1BUF	    ;copy and send
    
loop_BF		
  ;  banksel SSP1STAT	     
  ;  btfss   SSP1STAT, BF    
  banksel   PIR1
  btfss	PIR1 , SSP1IF
	goto loop_BF	       ;wait 
    
    bcf     PIR1 , SSP1IF    ;clear buffer full interrupt flag

    banksel SSP1BUF
    movf    SSP1BUF ,W	    

    banksel byte_data	    
    movwf   byte_data	    ;read and save
  
    return		    
;...........................................

poll_status_flash	
	    
    ;for writing a byte, it takes ~10us
loop_flash_status   
    banksel LATD		    
    bcf	    LATD, LATD1	;CE# low    
    
    banksel byte_data		    
    movlw   0x05		    	;RDSR command (status)	   
    movwf   byte_data		    
    
    call    SPI_Tx_Rx		    
    
    movlw   0x00		    	;dummy cycle	    
    movwf   byte_data		    
    
    call    SPI_Tx_Rx		    
    banksel LATD		    
    bsf	    LATD, LATD1	;CE# high   
    
   
    banksel byte_data		    
    btfsc   byte_data, 0x00	    
	goto	loop_flash_status      
				    
    return

The supply is VDD=3.3V +1A max, and the flash unit has the following:
  • CE# pin tied with a 10K pull-down resistor
  • HOLD# pin tied to VDD with a 10K res in series (pull-up)
  • WP# pin tied to VDD, no resistor.

Yes, I will check if the WP# goes low, FvM. I think there is something going on at the moment of writing data, but no clue so far.

Please take a look at the code I provided to see if there is something missing. I still get 0xFF.

Regards, Ser

- - - Updated - - -

Well, I found the reason why it was not working: I was not driving CE# low before sending the WRITE command 0x03.

OLD:
Code:
;send command for Byte write. WREN has already been enabled
    banksel byte_data		    
    movlw   0x02		    	;Byte-programming command	   
    movwf   byte_data		    
    call    SPI_Tx_Rx

NEW:
Code:
;send command for Byte write. WREN has already been enabled
    banksel LATD
    bcf	    LATD, LATD1	;CE# low 
    
    banksel byte_data		    
    movlw   0x02		    	;Byte-programming command	   
    movwf   byte_data		    
    call    SPI_Tx_Rx

Also I checked the WP# and it was logic High all the time, just to confirm.
Thanks agains :grin:
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top