调试spi-flash遇到问题了,型号是N25Q。读出来的数据都是0xFF

2019-07-20 19:40发布

现在能读取设备ID、寄存器的值,可是写进去的值读出来都是0xFF,已去除写保护。还有一的个问题是为什么原子哥在写数据时要从W25的最后地址位开始写,而不从0x000000开始写呢?以下是代码:
[mw_shl_code=c,true]void sFLASH_ReadStatusRegiter(uint32_t SectorAddr) //ed
{
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  //sFLASH_SendByte(sFLASH_CMD_READ_STATUS);     // 0x00      
  
  flashstatus1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
  sFLASH_CS_HIGH();
}

void TEST_SPIFLASH_writeandread(void)
{
   //sFLASH_Init();
  //要写入到W25Q16的字符串数组
  uint64_t FLASH_Addr;
  sFLASH_Init();                             //W25QXX初始化
  FLASH_Addr = 0x000100;                             //FLASH 大小为1Gb  0x000064
  
  //HAL_GPIO_WritePin(GPIOC,sFLASH_SPI_WP_PIN,GPIO_PIN_SET);
  //sFLASH_ReadStatusRegiter(FLASH_Addr);
  sFLASH_EraseSubSector(FLASH_Addr);Delayms(50);
  sFLASH_WritePage(TEXT_Buffer,FLASH_Addr,BufferSize);                              //从倒数第100个地址处开始,写入SIZE长度的数据
  Delayms(190);
  sFLASH_ReadBuffer(datatemp1,FLASH_Addr,BufferSize);                                      //从倒数第100个地址处开始,读出SIZE个字节
  
  sFLASH_EraseSubSector(FLASH_Addr);Delayms(100);
  sFLASH_WriteBuffer(TEXT_Buffer,FLASH_Addr,BufferSize);                                      //从倒数第100个地址处开始,写入SIZE长度的数据
  Delayms(290);
  sFLASH_ReadBuffer(datatemp2,FLASH_Addr,BufferSize);
  
  FLASH_Addr = 0x07FFF000;
  //sFLASH_EraseSubSector(FLASH_Addr+100);Delayms(50);
  W25QXX_Write((uint8_t*)TEXT_Buffer,FLASH_Addr,SIZE);
  Delayms(90);
  sFLASH_ReadBuffer(datatemp3,FLASH_Addr,SIZE);
  
  sFLASH_EraseSubSector(FLASH_Addr);Delayms(150);
  W25QXX_Write_Page((uint8_t*)TEXT_Buffer,FLASH_Addr,SIZE);
  Delayms(90);
  sFLASH_ReadBuffer(datatemp4,FLASH_Addr,SIZE);
}


void sFLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
  uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;

  Addr = WriteAddr % sFLASH_SPI_PAGESIZE;                //某页中的第Addr个地址
  count = sFLASH_SPI_PAGESIZE - Addr;                    //某页中还剩余count个地址空间
  NumOfPage =  NumByteToWrite / sFLASH_SPI_PAGESIZE;     //待写数据占用了页数
  NumOfSingle = NumByteToWrite % sFLASH_SPI_PAGESIZE;    //待写数据写了整数页大小的数据量后还剩多少字节要写

  if (Addr == 0) /*!< WriteAddr is sFLASH_PAGESIZE aligned  */    //待写的地址刚好在下页地址首地址
  {
    if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_PAGESIZE */ //待写入的数据小于一页的容量256
    {
      sFLASH_WritePage(pBuffer, WriteAddr, NumByteToWrite); //直接写一页就行
    }
    else /*!< NumByteToWrite > sFLASH_PAGESIZE */
    {
      while (NumOfPage--)                                   //不止一页,一页一页地写
      {
        sFLASH_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);
        WriteAddr +=  sFLASH_SPI_PAGESIZE;
        pBuffer += sFLASH_SPI_PAGESIZE;
      }

      sFLASH_WritePage(pBuffer, WriteAddr, NumOfSingle);
    }
  }
  else /*!< WriteAddr is not sFLASH_PAGESIZE aligned  */        //待写入的地址不在某页的首地址
  {
    if (NumOfPage == 0) /*!< NumByteToWrite < sFLASH_PAGESIZE */   
    {
      if (NumOfSingle > count) /*!< (NumByteToWrite + WriteAddr) > sFLASH_PAGESIZE */
      {                                 
        temp = NumOfSingle - count;

        sFLASH_WritePage(pBuffer, WriteAddr, count);
        WriteAddr +=  count;
        pBuffer += count;

        sFLASH_WritePage(pBuffer, WriteAddr, temp);
      }
      else
      {
        sFLASH_WritePage(pBuffer, WriteAddr, NumByteToWrite);
      }
    }
    else /*!< NumByteToWrite > sFLASH_PAGESIZE */       //待写入的数据>256字节
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / sFLASH_SPI_PAGESIZE;
      NumOfSingle = NumByteToWrite % sFLASH_SPI_PAGESIZE;

      sFLASH_WritePage(pBuffer, WriteAddr, count);
      WriteAddr +=  count;
      pBuffer += count;

      while (NumOfPage--)
      {
        sFLASH_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);
        WriteAddr +=  sFLASH_SPI_PAGESIZE;
        pBuffer += sFLASH_SPI_PAGESIZE;
      }

      if (NumOfSingle != 0)
      {
        sFLASH_WritePage(pBuffer, WriteAddr, NumOfSingle);
      }
    }
  }
}


uint8_t W25QXX_BUFFER[4096];                 
void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
{
   uint32_t secpos;
   uint16_t secoff;
   uint16_t secremain;          
   uint16_t i;   
   uint8_t * W25QXX_BUF;          
   W25QXX_BUF=W25QXX_BUFFER;             
   secpos=WriteAddr/4096;                                       //小扇区地址 4KB  
   secoff=WriteAddr%4096;                                       //在扇区内的偏移
   secremain=4096-secoff;                                       //扇区剩余空间大小   
   
   if(NumByteToWrite<=secremain){secremain = NumByteToWrite;}  //不大于4096个字节
        while(1)
        {       
                sFLASH_ReadBuffer(W25QXX_BUF,secpos*4096,4096); //读出整个扇区的内容
                for(i=0;i<secremain;i++)//校验数据
                {
                        if(W25QXX_BUF[secoff+i]!=0XFF)break;   //需要擦除            
                }
                if(i<secremain)//需要擦除
                {
                        sFLASH_EraseSubSector(secpos);       //擦除这个扇区
                        for(i=0;i<secremain;i++)           //复制
                        {
                                W25QXX_BUF[i+secoff]=pBuffer;          
                        }
                        W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区  

                }else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.                                   
                if(NumByteToWrite==secremain)break;//写入结束了
                else//写入未结束
                {
                        secpos++;//扇区地址增1
                        secoff=0;//偏移位置为0          

                           pBuffer+=secremain;  //指针偏移
                        WriteAddr+=secremain;//写地址偏移          
                           NumByteToWrite-=secremain;                        //字节数递减
                        if(NumByteToWrite>4096)secremain=4096;                //下一个扇区还是写不完
                        else secremain=NumByteToWrite;                        //下一个扇区可以写完了
                }         
        };         
}

void sFLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
  /*!< Enable the write access to the FLASH */
  sFLASH_WriteEnable();
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  /*!< Send "Write to Memory " instruction */
  sFLASH_SendByte(sFLASH_CMD_PAGE_PROGRAM);
  /*!< 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);
  /*!< while there is data to be written on the FLASH */
  while (NumByteToWrite--)
  {
    /*!< Send the current byte */
    sFLASH_SendByte(*pBuffer);
    /*!< Point on the next byte to be written */
    pBuffer++;
  }
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_CS_HIGH();
  /*!< Wait the end of Flash writing */
  sFLASH_WaitForWriteEnd();
}

void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
    uint16_t i;  
    sFLASH_WriteEnable();                 //SET WEL
    sFLASH_CS_LOW();                            //使能器件   
    sFLASH_SendByte(sFLASH_CMD_PAGE_PROGRAM);      //发送写页命令   
    sFLASH_SendByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址   
    sFLASH_SendByte((uint8_t)((WriteAddr)>>8));   
    sFLASH_SendByte((uint8_t)WriteAddr);   
    for(i=0;i<NumByteToWrite;i++)sFLASH_SendByte(pBuffer);//循环写数  
    sFLASH_CS_HIGH();                          //取消片选
    sFLASH_WaitForWriteEnd();                        //等待写入结束
}


void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
{                                           
        uint16_t pageremain;          
        pageremain=256-WriteAddr%256;                            //单页剩余的字节数                             
        if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
        while(1)
        {          
              sFLASH_WritePage(pBuffer,WriteAddr,pageremain);
              if(NumByteToWrite==pageremain)break;//写入结束了
              else //NumByteToWrite>pageremain
                {
                        pBuffer+=pageremain;
                        WriteAddr+=pageremain;       
                        NumByteToWrite-=pageremain;                          //减去已经写入了的字节数
                        if(NumByteToWrite>256)pageremain=256;              //一次可以写入256个字节
                        else pageremain=NumByteToWrite;                   //不够256个字节了
                }
        };            
}



void sFLASH_ReadBuffer(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)    /*ed*/
{
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  /*!< Send "Read from Memory " instruction */
  sFLASH_SendByte(sFLASH_CMD_READ);     /* 24位地址 */
  /*!< 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);

  while (NumByteToRead--) /*!< while there is data to be read */
  {
    /*!< 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++;
  }
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_CS_HIGH();
}




/* @brief  Erases the specified FLASH subsector(4KB=4096).    ed
  * @param  SectorAddr: address of the subsector to erase.
  * @retval None
*/
void sFLASH_EraseSubSector(uint32_t SectorAddr)
{
  /*!< Send write enable instruction */
  sFLASH_WriteEnable();
  /*!< Sector Erase */
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  /*!< Send Sector Erase instruction */
  sFLASH_SendByte(sFLASH_CMD_SUBSECTOR_ERASE);
  /*!< Send SectorAddr high nibble address byte */   //发送24位地址
  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);
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_CS_HIGH();
  /*!< Wait the end of Flash writing */
  sFLASH_WaitForWriteEnd();                   //等待擦除完成
  
}




/*--------------------------------------------*/
/*---------N25Q FLASH 读取设备ID 函数---------*/
uint32_t N25Q_ReadDeviceID(void)   
{
  uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  /*!< Send "RDID " instruction */
  sFLASH_SendByte(SFLASH_CMD_DEVICEID);
  /*!< Read a byte from the FLASH */
  Temp0 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
  /*!< Read a byte from the FLASH */
  Temp1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
  /*!< Read a byte from the FLASH */
  Temp2 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_CS_HIGH();
  Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
  return Temp;
}

/**
  * @brief  Reads FLASH identification.
  * @param  None
  * @retval FLASH identification
  */
uint32_t sFLASH_ReadID(void)
{
  uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  /*!< Send "RDID " instruction */
  sFLASH_SendByte(SFLASH_CMD_DEVICEID);
  /*!< Read a byte from the FLASH */
  Temp0 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
  /*!< Read a byte from the FLASH */
  Temp1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
  /*!< Read a byte from the FLASH */
  Temp2 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_CS_HIGH();
  Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
  return Temp;
}

uint32_t FLASH_READID(void)
{
  
  uint32_t DeviceID2=0,DeviceID1=0;
  sFLASH_Init();                                // 初始化了SPI-FLASH
  DeviceID1 = N25Q_ReadDeviceID();              //第一次结果就是不对,不知道为啥
  DeviceID2 = sFLASH_ReadID();                    //第二次结果是正确的
  return DeviceID2;
}

/********************************初始化程序***********************************/

void sFLASH_gpio_Init(void)                 
{
  GPIO_InitTypeDef GPIO_InitStructure;
  /*--##-1- Enable peripherals and GPIO Clocks--*/
  __SPI4_CLK_ENABLE();    /*!< Enable the SPI clock */
  __GPIOE_CLK_ENABLE();   /*!< Enable GPIO clocks   */
  __GPIOC_CLK_ENABLE();   /*!< Enable GPIO clocks   */
  //HAL_GPIO_StructInit(GPIOE, &GPIO_InitStructure);     //配置缺省值
  
  /*--##-2 - Configure peripheral GPIO --*/
  
  GPIO_InitStructure.Pin       = sFLASH_SPI_SCK_PIN|sFLASH_SPI_MISO_PIN|sFLASH_SPI_MOSI_PIN;
  GPIO_InitStructure.Mode      = GPIO_MODE_AF_PP;            //复用推挽输出
  GPIO_InitStructure.Pull      = GPIO_PULLUP;                //上拉输入??SCK为1
  GPIO_InitStructure.Speed     = GPIO_SPEED_FAST;
  GPIO_InitStructure.Alternate = GPIO_AF5_SPI4;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
  
  /*!< Configure sFLASH Card NSS pin in output pushpull mode ********************/
  GPIO_InitStructure.Pin       = sFLASH_NSS_PIN;
  GPIO_InitStructure.Mode      = GPIO_MODE_OUTPUT_PP;             //通用推挽输出
  GPIO_InitStructure.Pull      = GPIO_NOPULL;
  GPIO_InitStructure.Speed     = GPIO_SPEED_FAST;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
  
  /* ( W# )Write protect Control Input*  PC5  */
  GPIO_InitStructure.Pin       = sFLASH_SPI_WP_PIN;
  GPIO_InitStructure.Mode      = GPIO_MODE_OUTPUT_PP;            //通用推挽输出
  GPIO_InitStructure.Pull      = GPIO_PULLUP;                    //带上拉,让其一直无效
  GPIO_InitStructure.Speed     = GPIO_SPEED_FAST;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
  HAL_GPIO_WritePin(GPIOC,sFLASH_SPI_WP_PIN,GPIO_PIN_SET);       //置高,无效

  /* ( HOLD# ) HOLD Control Input*  PC6  */
  GPIO_InitStructure.Pin       = sFLASH_SPI_HOLD_PIN;
  GPIO_InitStructure.Mode      = GPIO_MODE_OUTPUT_PP;            //通用推挽输出
  GPIO_InitStructure.Pull      = GPIO_PULLUP;               
  GPIO_InitStructure.Speed     = GPIO_SPEED_FAST;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
  HAL_GPIO_WritePin(GPIOC,sFLASH_SPI_HOLD_PIN,GPIO_PIN_SET);     //置高,无效
}
void SPI_SetSpeed(uint8_t SPI_BaudRateprescaler)
{
SPI4->CR1 &= 0xFFC7;                                   /* 位3-5清零,用来设置波特率 */
SPI4->CR1 |= SPI_BaudRateprescaler;
SPI4->CR1|=(1<<6);
}

void sFLASH_Init(void)
{
  /*--##-4 - Configure peripheral SPI --*/
  SPI_HandleTypeDef  SPI_InitStructure;
  //__SPI4_CLK_ENABLE();    /*!< Enable the SPI clock */
  sFLASH_gpio_Init();
  
  //HAL_SPI_DeInit(&SPI_InitStructure);
  sFLASH_CS_HIGH();         /*!< Deselect the FLASH: Chip Select high 取消片选*/

  /*!< SPI configuration */
  SPI_InitStructure.Instance  = SPI4;
  SPI_InitStructure.Init.Mode = SPI_MODE_MASTER;
  SPI_InitStructure.Init.NSS  = SPI_NSS_SOFT;
  SPI_InitStructure.Init.Direction = SPI_DIRECTION_2LINES;
  SPI_InitStructure.Init.DataSize = SPI_DATASIZE_8BIT;          // ??
  
  SPI_InitStructure.Init.CLKPolarity = SPI_POLARITY_HIGH;       // CPOL==1
  SPI_InitStructure.Init.CLKPhase = SPI_PHASE_2EDGE;            // CPOH==1

  //SPI_SetSpeed(SPI_BAUDRATEPRESCALER_256);
  
  SPI_InitStructure.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; // ??
  SPI_InitStructure.Init.FirstBit = SPI_FIRSTBIT_MSB;
  SPI_InitStructure.Init.TIMode = SPI_TIMODE_DISABLE;
  SPI_InitStructure.Init.CRCPolynomial = 7;
  
  HAL_SPI_Init(&SPI_InitStructure);   
  
  /*!< 5 Enable the sFLASH_SPI  */
  SPI4->CR1|=(1<<6);                    //使能SPI  
  sFLASH_CS_LOW();
  sFLASH_SendByte(0xff);                //启动传输
}

/***************** (C) COPYRIGHT STMicroelectronics ********END OF FILE*****/
[/mw_shl_code]写保护。



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。