打印
[PIC®/AVR®/dsPIC®产品]

关于25Q128芯片的扇区擦除

[复制链接]
11292|37
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
dzxc_wh|  楼主 | 2021-7-27 10:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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[i]=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[i]);                                        //循环写数
        }

        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();
}


这两个也是正常的

使用特权

评论回复
5
m564522634| | 2021-7-27 16:17 | 只看该作者
这明显命令转换出错了,对照手册看下数据包正常不

使用特权

评论回复
6
dzxc_wh|  楼主 | 2021-7-27 16:55 | 只看该作者
看过数据包,24位地址是对的

使用特权

评论回复
7
奔波儿熊| | 2021-7-27 17:00 | 只看该作者
你这是片外flash吧,应该去flash厂商那里问, 除非你是SPI有问题, 但是看描述,SPI通讯是没问题的。

使用特权

评论回复
8
dzxc_wh|  楼主 | 2021-7-27 17:04 | 只看该作者
对头的,片外FLASH,SPI总线,128M-bit,华邦原厂

使用特权

评论回复
9
dzxc_wh|  楼主 | 2021-7-27 17:19 | 只看该作者
我给华邦官网给技术支持发了个电子邮件,不知道会不会有人理我

使用特权

评论回复
10
li880wert| | 2021-7-27 18:41 | 只看该作者
一看就是程序问题,
48   页 0X3000
304     0x13000

使用特权

评论回复
11
dzxc_wh|  楼主 | 2021-7-28 07:26 | 只看该作者
就算是软件问题,地址发出的不对,这里也应该是只擦除一个4K的空间,我的意思是擦除了不止一个4K的空间,问题是在这里

使用特权

评论回复
12
dzxc_wh|  楼主 | 2021-7-28 07:41 | 只看该作者
特意仿真看了,当
SPI_FLASH_SECTOR_ERASE(3);
的时候,24位地址是0x003000,要发送的第一个字节是0x00,第2个字节是0x30,第3个字节是0x00
按数据手册的,高地址在前,低地址在后,应该是没问题

使用特权

评论回复
13
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页,也都是被删除了,后面的地址应该还有

使用特权

评论回复
14
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擦除,你想想你的命令哪不对

使用特权

评论回复
15
dzxc_wh|  楼主 | 2021-7-28 08:14 | 只看该作者
我用的是4K的擦除命令,命令字是0x20

使用特权

评论回复
16
dzxc_wh|  楼主 | 2021-7-28 08:16 | 只看该作者
我也是希望是我的软件出错了,但是就是没找出来哪里出错了

使用特权

评论回复
17
32021724| | 2021-7-28 08:27 | 只看该作者
应该是程序问题,逻辑分析仪看波形

使用特权

评论回复
18
dzxc_wh|  楼主 | 2021-7-28 08:41 | 只看该作者
没那么高级的东西,只用双通道示波器两两看过CS  SCK  SDI,和时序图也能对得上

使用特权

评论回复
19
dzxc_wh|  楼主 | 2021-7-28 08:43 | 只看该作者
哪位大哥有4K删除的源码的,可以贴出来,我看看跟我的有啥区别

使用特权

评论回复
20
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,肯定不会搞错,通过这个验证看看有什么规律没。
希望楼主能找到原因,找到后发表一下,让我们以后好避免。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

107

帖子

0

粉丝