dzxc_wh 发表于 2021-7-27 10:57

关于25Q128芯片的扇区擦除

本帖最后由 pzsh 于 2021-8-12 11:53 编辑

目前在使用W25Q128(华邦产品,SO8封装)这个芯片,主控CPU为PIC18F4523,目前在使用过程中碰到了几个问题,希望高手给指点下:
1、整块擦除后的扇区写,扇区读功能正常。
2、读生产商ID以及芯片代码功能正常。
3、有问题的是扇区擦除命令,即擦除4K的命令。比如我使用命令SPI_FLASH_SECTOR_ERASE(3);时候,希望的是擦除页48-63,但是我发现页304-319页被擦除掉了。同样的SPI_FLASH_SECTOR_ERASE(5);的时候,本来只希望擦除页80-95,但是页336-351也被擦除掉了
4、我的扇区擦除指令为:
void SPI_FLASH_SECTOR_ERASE(unsigned long sector)      //块擦除
{
      sector *= SPI_FLASH_SECTOR_SIZE;
      SPI_FLASH_Write_Enable();
      flash_wait_busy();
          CS_FLASH_L();
      outbyte(SectorErase_4KB);
          //outbyte((sector >> 16) & 0xff);
          //outbyte((sector >> 8) & 0xff);
          //outbyte(sector & 0xff);

      outbyte((unsigned char)(sector >> 16));
          outbyte((unsigned char)(sector >> 8));
          outbyte((unsigned char)sector);
          CS_FLASH_H();
            flash_wait_busy();
}


void SPI_FLASH_Write_Enable(void)   
{
      CS_FLASH_L();                                 //使能器件   
            outbyte(CMD_WREN);                                                      //发送写使能
      CS_FLASH_H();                                 //取消片选                  
}


void flash_wait_busy(void)
{
      CS_FLASH_L();
      while( flash_read_status() & (0x01) );
      CS_FLASH_H();
}

4、有碰到过类似问题的前辈妈?如果有,请指点迷津。谢谢

dzxc_wh 发表于 2021-7-27 11:04

本帖最后由 dzxc_wh 于 2021-7-27 11:06 编辑

目前做的,就是只使用全片擦除指令,然后一页一页的写,说白了就是避开也扇区擦除,但是总是想着把这个原因找出来

dzxc_wh 发表于 2021-7-27 11:07

//读取SPI FLASH
//在指定地址开始读取指定长度的数据
//pBuffer:数据存储区
//ReadAddr:开始读取的地址(24bit)
//NumByteToRead:要读取的字节数(最大65535)
void SPI_Flash_Read(unsigned char* pBuffer,unsigned long ReadAddr,unsigned int NumByteToRead)   
{
        unsigned int i;                                                                                                      
        CS_FLASH_L();                                   //使能器件
        nop();   
            outbyte(0x03);                                                         //发送读取命令   
            outbyte((unsigned char)((ReadAddr)>>16));        //发送24bit地址   
            outbyte((unsigned char)((ReadAddr)>>8));   
            outbyte((unsigned char)ReadAddr);   
            for(i=0;i<NumByteToRead;i++)
        {
      pBuffer=inbyte();           //循环读数
    }
        CS_FLASH_H();                                   //取消片选                 
}


//SPI在一页(0~65535)内写入少于256个字节的数据
//在指定地址开始写入最大256字节的数据
//pBuffer:数据存储区
//WriteAddr:开始写入的地址(24bit)
//NumByteToWrite:要写入的字节数(最大256),该数不应该超过该页的剩余字节数!!!       
void SPI_Flash_Write_Page(unsigned char *pBuffer,unsigned long WriteAddr,unsigned int NumByteToWrite)
{
        unsigned int i;

        CS_FLASH_L();
        //nop();
        SPI_FLASH_Write_Enable();                          //SET WEL
        flash_wait_busy();
        CS_FLASH_L();                                   //使能器件   
            outbyte(0x02);                                                      //发送写页命令   
            outbyte((unsigned char)((WriteAddr)>>16));         //发送24bit地址   
            outbyte((unsigned char)((WriteAddr)>>8));   
            outbyte((unsigned char)WriteAddr);   
            for(i=0;i<NumByteToWrite;i++)
        {
                outbyte(pBuffer);                                        //循环写数
        }

        delay(50);                ///CS引脚必须在整数字节(8倍数时钟)之后拉高,以确保最后一个字节被锁定。如果没有这么做,则扇区擦除指令将不会执行。
                                        //22us > 12.8us

        CS_FLASH_H();                                   //取消片选
        flash_wait_busy();                                                           //等待写入结束
}

页的读写指令正常

dzxc_wh 发表于 2021-7-27 11:09

unsigned int W25QXX_ReadID(void)
{
        unsigned int Temp = 0;
        unsigned char Temp1,Temp2;

        CS_FLASH_L();                          
        outbyte(0x90);                  
        outbyte(0x00);           
        outbyte(0x00);           
        outbyte(0x00);
       
        Temp1 = inbyte();
        Temp2 = inbyte();
       
        Temp =Temp1 * 256 + Temp2;                  
        //Temp = Temp | (outbyte(0xFF)<<8);
        //Temp = Temp | (outbyte(0xFF));
       
        CS_FLASH_H();       
                  
        return Temp;
}


void SPI_FLASH_BulkErase(void)                //整片擦除
{
            SPI_FLASH_Write_Enable();
        flash_wait_busy();
        CS_FLASH_L();
        outbyte(W25X_ChipErase);
        //delay(50);
        CS_FLASH_H();
            flash_wait_busy();
}


这两个也是正常的

m564522634 发表于 2021-7-27 16:17

这明显命令转换出错了,对照手册看下数据包正常不

dzxc_wh 发表于 2021-7-27 16:55

看过数据包,24位地址是对的

奔波儿熊 发表于 2021-7-27 17:00

你这是片外flash吧,应该去flash厂商那里问, 除非你是SPI有问题, 但是看描述,SPI通讯是没问题的。

dzxc_wh 发表于 2021-7-27 17:04

对头的,片外FLASH,SPI总线,128M-bit,华邦原厂

dzxc_wh 发表于 2021-7-27 17:19

我给华邦官网给技术支持发了个电子邮件,不知道会不会有人理我

li880wert 发表于 2021-7-27 18:41

一看就是程序问题,
48   页 0X3000
304   0x13000

dzxc_wh 发表于 2021-7-28 07:26

就算是软件问题,地址发出的不对,这里也应该是只擦除一个4K的空间,我的意思是擦除了不止一个4K的空间,问题是在这里

dzxc_wh 发表于 2021-7-28 07:41

特意仿真看了,当
SPI_FLASH_SECTOR_ERASE(3);
的时候,24位地址是0x003000,要发送的第一个字节是0x00,第2个字节是0x30,第3个字节是0x00
按数据手册的,高地址在前,低地址在后,应该是没问题

dzxc_wh 发表于 2021-7-28 07:53

0x00 00 30,0x00 01 30,0x00 02 30,0x00 03 30,0x00 04 30,0x00 05 30,0x00 06 30,这些页,以及后面跟着的15页,也都是被删除了,后面的地址应该还有

li880wert 发表于 2021-7-28 08:06

dzxc_wh 发表于 2021-7-28 07:53
0x00 00 30,0x00 01 30,0x00 02 30,0x00 03 30,0x00 04 30,0x00 05 30,0x00 06 30,这些页,以及后面 ...

命令搞错了,你这是块擦除了,有个4K擦除,有个32K擦除,还有个64K擦除,你想想你的命令哪不对

dzxc_wh 发表于 2021-7-28 08:14

我用的是4K的擦除命令,命令字是0x20

dzxc_wh 发表于 2021-7-28 08:16

我也是希望是我的软件出错了,但是就是没找出来哪里出错了

32021724 发表于 2021-7-28 08:27

应该是程序问题,逻辑分析仪看波形

dzxc_wh 发表于 2021-7-28 08:41

没那么高级的东西,只用双通道示波器两两看过CSSCKSDI,和时序图也能对得上

dzxc_wh 发表于 2021-7-28 08:43

哪位大哥有4K删除的源码的,可以贴出来,我看看跟我的有啥区别

TT1000 发表于 2021-7-28 09:33

最近刚好写过SPI_FLASH芯片(ZD25Q16B),不过不是楼主的型号,提供一下我的部分程序给楼主参考
/********************************************************************
SPI_FLASH芯片扇区擦除函数
********************************************************************/
void SPI_Flash_Erase_Sector(u8 x,u32 Addr)
{
        FRAM_CS_EN(x);
    SPI_ReadWriteByte(WREN);                 //写使能
    FRAM_CS_DIS(x);       
       
        FRAM_CS_EN(x);
        SPI_ReadWriteByte(SectorErase);                //擦除扇区命令
        SPI_ReadWriteByte((u8)(Addr>>16));        //高位地址
        SPI_ReadWriteByte((u8)(Addr>>8));        //中位地址
        SPI_ReadWriteByte((u8)(Addr));                //低位地址
        FRAM_CS_DIS(x);
        SPI_Flash_Wait_Busy(x);             //等待芯片空闲
       
        FRAM_CS_EN(x);
    SPI_ReadWriteByte(WRDI);                 //写禁能
    FRAM_CS_DIS(x);
}
/********************************************************************
等待SPI_FLASH芯片空闲
********************************************************************/       
void SPI_Flash_Wait_Busy(u8 x)
{
        u8 WaitFlag=0;
       
        WaitTime=0;                                //等待时间
        WaitFlag=1;
        while(WaitFlag)
        {//等待芯片空闲
                if((SPI_Flash_ReadSR(x)&0x01)!=0x01)
                {//芯片忙状态标志位为0,则认为空闲
                        WaitTime=0;                //等待时间
                        WaitFlag=0;
                }               
                if(WaitTime>10)
                {//10ms还没空闲则认为有问题,退出该循环
                        WaitTime=0;                //等待时间
                        WaitFlag=0;
                }
        }
}

其中 x代表选择的芯片,我用了两片。
我看楼主操作完成之后没有写禁止的命令,我不知道华邦的是不是可以不要。
楼主可以确认
1、相应的命令字是否正确。
2、地址发出去的是否是你想发的地址。
3、可以先整片擦除,对扇区0,1进行写,然后用扇区擦除命令擦除0扇区,看是否0扇区被擦除了,1扇区是否没被擦除,因为0扇区地址为0,肯定不会搞错,通过这个验证看看有什么规律没。
希望楼主能找到原因,找到后发表一下,让我们以后好避免。
页: [1] 2
查看完整版本: 关于25Q128芯片的扇区擦除