Cannot read/write winbond W25x16 SPI Flash

Thread Starter

devjeetmandal

Joined May 7, 2017
48
Hello Everyone,

I am trying to interface winbond SPI Flash w25q16 with STM32F103RC using CubeMX.
After doing some research i chosen these two links as for my reference.

Here is the link i am following:

https://electronics.stackexchange.com/questions/51229/how-do-i-write-to-spi-flash-memory

from Jeff Walther

and this link for sample program

https://github.com/mhollands/Winbond-W25Q32JV/blob/master/main.cpp

Here is my code:

C:
uint8_tCheck_Status_Flag(){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);//CS Low
HAL_Delay(10);

uint8_t txBuff[1],rxBuff[1];
txBuff[0]=0x05;//command for checking status
HAL_SPI_Transmit(&hspi1, txBuff,1,100);//send command
txBuff[0]=0x00;
HAL_SPI_Transmit(&hspi1, txBuff,1,100);//send dummy value
HAL_SPI_Receive(&hspi1, rxBuff,1,100);//receive status

return rxBuff[0];}

voidWrite_Enable(){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);//CS Low
HAL_Delay(10);

uint8_t txBuff[1],rxBuff[1];
txBuff[0]=0x06;//command for write enable
HAL_SPI_Transmit(&hspi1, txBuff,1,100);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);//CS High
HAL_Delay(10);


while((Check_Status_Flag()&0x02)!=0x00);}


voidSector_Erase(uint8_t addr1,uint8_t addr2,uint8_t addr3){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);//CS Low
HAL_Delay(10);

uint8_t txBuff[4],rxBuff[4];
txBuff[0]=0x20;//command for sector erase
txBuff[1]= addr1;//MSB of the address
txBuff[2]= addr2;//middle address
txBuff[3]= addr3;//LSB of the address
HAL_SPI_Transmit(&hspi1, txBuff,4,100);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);//CS High
HAL_Delay(10);

while((Check_Status_Flag()&0x01)!=0x00);}

voidWrite_Data(uint8_t addr1,uint8_t addr2,uint8_t addr3,uint8_t data){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);//CS Low
HAL_Delay(10);

uint8_t txBuff[5],rxBuff[5];
txBuff[0]=0x02;//command for write data
txBuff[1]= addr1;//MSB of the address
txBuff[2]= addr2;//middle address
txBuff[3]= addr3;//LSB of the address
txBuff[4]= data;
HAL_SPI_Transmit(&hspi1, txBuff,5,100);

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);//CS High
HAL_Delay(10);

while((Check_Status_Flag()&0x01)!=0x00);}

voidRead_Data(uint8_t addr1,uint8_t addr2,uint8_t addr3){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);//CS Low
HAL_Delay(10);

uint8_t txBuff[5],rxBuff[5];
txBuff[0]=0x03;//command for read data
txBuff[1]= addr1;//MSB of the address
txBuff[2]= addr2;//middle address
txBuff[3]= addr3;//LSB of the address
HAL_SPI_Transmit(&hspi1, txBuff,4,100);
HAL_SPI_Receive(&hspi1, rxBuff,4,100);//receiving 4 garbage

txBuff[0]=0x00;

HAL_SPI_Transmit(&hspi1, txBuff,1,100);//transmitting dummy
HAL_SPI_Receive(&hspi1, rxBuff,1,100);//receiving the data uint8_t data = rxBuff[0];//storing the data
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);//CS High
HAL_Delay(10);
if (rxBuff[0] == 0x11)
    //Blink LED

while((Check_Status_Flag()&0x01)!=0x00);}
And this is the main

Code:
int main(void){
HAL_Init();SystemClock_Config();

MX_GPIO_Init();
MX_SPI1_Init();


HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);//CS High
HAL_Delay(10);Write_Enable();Sector_Erase(0x00,0x10,0x00);Write_Enable();Write_Data(0x00,0x00,0x01,0x11);Read_Data(0x00,0x00,0x01);

while(1){

}

}
SPI init
C:
staticvoid MX_SPI1_Init(void){

/* SPI1 parameter configuration*/
hspi1.Instance= SPI1;
hspi1.Init.Mode= SPI_MODE_MASTER;
hspi1.Init.Direction= SPI_DIRECTION_2LINES;
hspi1.Init.DataSize= SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity= SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase= SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler= SPI_BAUDRATEPRESCALER_64;
hspi1.Init.FirstBit= SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode= SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation= SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial=10;if(HAL_SPI_Init(&hspi1)!= HAL_OK){_Error_Handler(__FILE__, __LINE__);}

}

I am comparing the value after reading and blinking the LED. But i am not getting any result. I don't know where i am going wrong.
Any help will be appreciated

Thanks in advance.
 

Sensacell

Joined Jun 19, 2012
3,449
Is the hardware working? are you seeing data and clock on the SPI lines?

It's more than just some code.
IF you don't analyze it from a holistic systems point of view, you will have a very hard time getting it to work.

It's like getting into a car in a junkyard and expecting it to start.
Is there an engine in the car? a battery? gasoline? You must verify each element.
 

MrChips

Joined Oct 2, 2009
30,810
Does your program compile without errors?

Your code is disjointed and missing parts.
Show the complete program as one file.
 

Thread Starter

devjeetmandal

Joined May 7, 2017
48
Yes my code compiles without any errors.
Actually most of the parts are defined by CubeMX that's why i just posted the things i have included in that code.


Here is my whole main.c

C:
#include "main.h"
#include "stm32f1xx_hal.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */


void Blink_Led()
{
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
   HAL_Delay(1000);
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
   HAL_Delay(1000);
}


uint8_t Check_Status_Flag()
{
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);     //CS Low
   HAL_Delay(10);
  
   uint8_t txBuff[1],rxBuff[1];
   txBuff[0] = 0x05;         //command for checking status
   HAL_SPI_Transmit(&hspi1, txBuff, 1, 100);       //send command
   txBuff[0] = 0x00;
   HAL_SPI_Transmit(&hspi1, txBuff, 1, 100);       //send dummy value
   HAL_SPI_Receive(&hspi1, rxBuff, 1, 100);       //receive status
  
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);     //CS Low
   HAL_Delay(10);
   return rxBuff[0];
}

void Write_Enable()
{
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);     //CS Low
   HAL_Delay(10);
  
   uint8_t txBuff[1],rxBuff[1];
   txBuff[0] = 0x06;       //command for write enable
   HAL_SPI_Transmit(&hspi1, txBuff, 1, 100);
  
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);     //CS High
   HAL_Delay(10);
  
  
   while ((Check_Status_Flag() & 0x02) != 0x00);
  
}


void Sector_Erase(uint8_t addr1, uint8_t addr2, uint8_t addr3)
{
   while ((Check_Status_Flag() & 0x01) != 0x00);
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);     //CS Low
   HAL_Delay(10);
  
   uint8_t txBuff[4],rxBuff[4];
   txBuff[0] = 0x20;       //command for sector erase
   txBuff[1] = addr1;     //MSB of the address
   txBuff[2] = addr2;      //middle address
   txBuff[3] = addr3;       //LSB of the address
   HAL_SPI_Transmit(&hspi1, txBuff, 4, 100);
  
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);     //CS High
   HAL_Delay(10);
  
  
}

void Write_Data(uint8_t addr1, uint8_t addr2, uint8_t addr3, uint8_t data)
{
   while ((Check_Status_Flag() & 0x01) != 0x00);
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);     //CS Low
   HAL_Delay(10);
  
   uint8_t txBuff[5],rxBuff[5];
   txBuff[0] = 0x02;       //command for write data
   txBuff[1] = addr1;     //MSB of the address
   txBuff[2] = addr2;      //middle address
   txBuff[3] = addr3;       //LSB of the address
   txBuff[4] = data;
   HAL_SPI_Transmit(&hspi1, txBuff, 5, 100);
  
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);     //CS High
   HAL_Delay(10);
  
   Blink_Led();
}

void Read_Data(uint8_t addr1, uint8_t addr2, uint8_t addr3)
{
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);     //CS Low
   HAL_Delay(10);
  
   uint8_t txBuff[5],rxBuff[5];
   txBuff[0] = 0x03 | 0x80;       //command for read data
   txBuff[1] = addr1;     //MSB of the address
   txBuff[2] = addr2;      //middle address
   txBuff[3] = addr3;       //LSB of the address
   HAL_SPI_Transmit(&hspi1, txBuff, 4, 100);
   txBuff[0] = 0x00;
   txBuff[1] = 0x00;
   txBuff[2] = 0x00;
   txBuff[3] = 0x00;
   txBuff[4] = 0x00;
   HAL_SPI_Transmit(&hspi1, txBuff, 5, 100);     //transmitting dummy
   HAL_SPI_Receive(&hspi1, rxBuff, 5, 100);     //receiving the data
   uint8_t data = rxBuff[4];                     //storing the data
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);     //CS High
   HAL_Delay(10);
  
   if (data == 0x11)
   {
     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);         //LED high
   }
   else
   {
     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);       //LED Low
   }
  
   //while ((Check_Status_Flag() & 0x01) != 0x00);
}


/**
  * @brief  The application entry point.
  *
  * @retval None
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
   HAL_SPI_Init(&hspi1);
   RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
  /* USER CODE BEGIN 2 */
  
   Blink_Led();
  
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);     //CS High
   HAL_Delay(10);
   Write_Enable();
   Sector_Erase(0x00, 0x10, 0x00);
   Write_Enable();
   Write_Data(0x00, 0x00, 0x01, 0x11);
   Read_Data(0x00, 0x00, 0x01);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  /**Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
  _Error_Handler(__FILE__, __LINE__);
  }

  /**Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
  _Error_Handler(__FILE__, __LINE__);
  }

  /**Configure the Systick interrupt time
  */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

  /**Configure the Systick
  */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* SPI1 init function */
static void MX_SPI1_Init(void)
{

  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
  _Error_Handler(__FILE__, __LINE__);
  }

}

/** Configure pins as
  * Analog
  * Input
  * Output
  * EVENT_OUT
  * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

   /*Configure GPIO pin Output Level */
   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);  
  
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA4 */
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : PD2 */
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
  
   /*Configure GPIO pin : PA8 */
  GPIO_InitStruct.Pin = GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


}

I have made few changes in Read Data function after posting this question. But then also it's not working. I just need steps required to read write SPI flash an how my SPI channel is behaving. Like i know if i send a data in SPI channel i will receive a data. But how to capture that data. How to properly send the address in SPI channel.??
 
Last edited:

MrChips

Joined Oct 2, 2009
30,810
OK. You've written the code. It compiles and it is downloaded to the MCU.
Now comes the next step. Debug your code.

What is it supposed to do? What does it do? What does it not do?
Only you can answer those questions.
 

Thread Starter

devjeetmandal

Joined May 7, 2017
48
Is the hardware working? are you seeing data and clock on the SPI lines?

It's more than just some code.
IF you don't analyze it from a holistic systems point of view, you will have a very hard time getting it to work.

It's like getting into a car in a junkyard and expecting it to start.
Is there an engine in the car? a battery? gasoline? You must verify each element.
Ok so i don't have anything to check serial data and clock in the spi lines.But in "Write_Enable()" function I have checked this
"while ((Check_Status_Flag() & 0x02) != 0x00);" i.e. i have checked the status register and placed it in a loop until WEL(write enable latch) is cleared. So i put a blink led after this and it blinks. Is that mean my hardware is OK?
 

Thread Starter

devjeetmandal

Joined May 7, 2017
48
OK. You've written the code. It compiles and it is downloaded to the MCU.
Now comes the next step. Debug your code.

What is it supposed to do? What does it do? What does it not do?
Only you can answer those questions.
In debug mode if i place "data" in Read_Data() function in watch window, it says Cannot Evaluate.
 

Thread Starter

devjeetmandal

Joined May 7, 2017
48
In case of w25q16 winbond spi flash, how to get the device id.
In datasheet it is written like this

new.PNG

Now what command should i send and how many bytes i will receive?????
Can anyone please tell me this??????
 

Sensacell

Joined Jun 19, 2012
3,449
I would not dream of trying to get this working without a way to check the physical signals.

Doing so is a GIANT waste of time and energy.
You could spend DAYS pouring over the code, meanwhile, nothing is happening.

Get a scope and check it.
 
Top