[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

Cookies are required to use this site. You must accept them to continue using the site. Learn more…