stm32之W25Q

   W25Q是一款flash存储芯片。可以进行写数据、读数据、擦除。通过通信接口与MCU进行通信。其片选引脚,低电平有效

  其使用配合着SPI使用--可以单独配置spi底层函数,读取数据函数,也可以使用W25Q提供的stm32_eval_spi_flash.c里void sFLASH_Init(void)初始化配置。

其特点是:先擦除后写入。

  存储芯片大小:16M-bit  --2M Byte

    1页           --256字节

  1个扇区---16页        ---4K

  1块       ----16个扇区 --64K

  一个芯片 --32块      --2M

如何从一个字节空间存一个数据:第1块中第一个扇区的第一页第100个字节写一个数:0xAA

               0000 0000 0KKK KKKK SSSS PPPP BBBB BBBB

               0x0      0  0      1     1    64

                0x00001364 

MCU通过SPI给W25Q发送指令

  2.WQ25的编写---可以直接引用该芯片本身写好的程序---比如stm32_eval_spi_flash.c

  uint8_t Tx_Buffer[] = "I Love China";   //发送的内容
  uint8_t Rx_Buffer[64];      //接收的内容
  __IO uint32_t FlashID = 0;            //ID地址

·(1)读ID ---FlashID = sFLASH_ReadID();

 (2)判断ID是否正确if (FlashID == sFLASH_W25Q16_ID)

 (3)正确的话;printf("ID 正确 ");

 (4)擦除的内存空间0x00001364

  /* Erase SPI FLASH Sector to write on */
   sFLASH_EraseSector(0x00001364);

 (5)写数据

  /* Write Tx_Buffer data to SPI FLASH memory */
  sFLASH_WriteBuffer(Tx_Buffer, 0x032100, sizeof(Tx_Buffer));
  printf("tx_buff =%s ",Tx_Buffer);

 (6)读数据

  /* Read data from SPI FLASH memory */
  sFLASH_ReadBuffer(Rx_Buffer, 0x032100, sizeof(Tx_Buffer));
  printf("rx_buff =%s ",Rx_Buffer);

  (7)ID不正确的话:printf("验证ID失败 ");

.........无论是读还是写操作,都是先进行busy判断在进行片选拉高,busy的判断在判断写完成函数里sFLASH_WaitForWriteEnd();,但是在有的函数里会出现

    

 这样可以理解为两个函数可以合并成一个,其过程也可以这样理解:就是先拉低选择芯片,写入数据,拉高芯片,在查询芯片的状态,拉低,查看busy,在拉高
   

二。指令

  1.读ID

  (1)片选拉低: sFLASH_CS_LOW();

  (2)发送读ID指令:sFLASH_SendByte(0x9F);

  (3)发送数据: Temp0 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);

  (4)片选拉高:sFLASH_CS_HIGH();

  (5)返回读的值:Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

  2.扇区擦除

  (1)发送写使能指令:sFLASH_WriteEnable();//写使能

  (2)片选拉低

  (3)发送扇区擦除指令:sFLASH_SendByte(0x20);

  (4)发送扇区擦除地址:

            /*!< Send SectorAddr high nibble address byte */
            sFLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
            /*!< Send SectorAddr medium nibble address byte */
            sFLASH_SendByte((SectorAddr & 0xFF00) >> 8);

            /*!< Send SectorAddr low nibble address byte */
            sFLASH_SendByte(SectorAddr & 0xFF);

  (判断busy位)

  (5)片选拉高

  (6)等待写完成:sFLASH_WaitForWriteEnd();//里面含有判断busy,写入数据是需要时间的,W25Q通过busy的进行判断是否写完的

   3.写操作-------1~256字节空间--页编程

  (1)写使能:sFLASH_WriteEnable();

  (2)片选拉低

  (3)发送页写指令:sFLASH_SendByte(0x02);

  (4)发送页写地址--24位

    /*!< Send WriteAddr high nibble address byte to write to */
    sFLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
    /*!< Send WriteAddr medium nibble address byte to write to */
    sFLASH_SendByte((WriteAddr & 0xFF00) >> 8);
    /*!< Send WriteAddr low nibble address byte to write to */
    sFLASH_SendByte(WriteAddr & 0xFF);

  (5)判断写的数据大小-----状态位:

    while (NumByteToWrite--)    //NumByteToWrite--这个是写的字节数,有多少个数据写入
    {
      /*!< Send the current byte */
      sFLASH_SendByte(*pBuffer);
      /*!< Point on the next byte to be written */
      pBuffer++;
    }

  (6)片选拉高

  (5)等待写完成:sFLASH_WaitForWriteEnd();

  4.写操作---写buff

  (1)判断 Writedaddr 是 sflash pagesize 对齐

    if(Addr == 0)//页内地址

  (2)是的话,判断页数大小:if (NumOfPage == 0) 

  (2.1)是的话:页编程

  (2.2)不是的话 ,while (NumOfPage--)->页编程sFLASH_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);--->WriteAddr += sFLASH_SPI_PAGESIZE;pBuffer += sFLASH_SPI_PAGESIZE;

  (3)不是的话,,类似

  5.读操作--读buff

  (1)片选拉低

  (2)发送读指令: sFLASH_SendByte(0x03);

  (3)发送读地址--24位:21位地址,3个字节

    /*!< Send ReadAddr high nibble address byte to read from */
    sFLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
    /*!< Send ReadAddr medium nibble address byte to read from */
    sFLASH_SendByte((ReadAddr& 0xFF00) >> 8);
    /*!< Send ReadAddr low nibble address byte to read from */
    sFLASH_SendByte(ReadAddr & 0xFF);

  (//判断busy位)

  (4)判断要读的数据大小: while (NumByteToRead--)//判断busy位

  (5)while里读数据位

      /*!< Read a byte from the FLASH */
      *pBuffer = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
      /*!< Point to the next location where the byte read will be saved */
      pBuffer++;

  (6)片选拉高

原文地址:https://www.cnblogs.com/juan-4-14/p/12701616.html