关于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:06 编辑
目前做的,就是只使用全片擦除指令,然后一页一页的写,说白了就是避开也扇区擦除,但是总是想着把这个原因找出来 //读取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(); //等待写入结束
}
页的读写指令正常 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();
}
这两个也是正常的 这明显命令转换出错了,对照手册看下数据包正常不 看过数据包,24位地址是对的 你这是片外flash吧,应该去flash厂商那里问, 除非你是SPI有问题, 但是看描述,SPI通讯是没问题的。 对头的,片外FLASH,SPI总线,128M-bit,华邦原厂 我给华邦官网给技术支持发了个电子邮件,不知道会不会有人理我 一看就是程序问题,
48 页 0X3000
304 0x13000
就算是软件问题,地址发出的不对,这里也应该是只擦除一个4K的空间,我的意思是擦除了不止一个4K的空间,问题是在这里 特意仿真看了,当
SPI_FLASH_SECTOR_ERASE(3);
的时候,24位地址是0x003000,要发送的第一个字节是0x00,第2个字节是0x30,第3个字节是0x00
按数据手册的,高地址在前,低地址在后,应该是没问题 0x00 00 30,0x00 01 30,0x00 02 30,0x00 03 30,0x00 04 30,0x00 05 30,0x00 06 30,这些页,以及后面跟着的15页,也都是被删除了,后面的地址应该还有 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擦除,你想想你的命令哪不对 我用的是4K的擦除命令,命令字是0x20 我也是希望是我的软件出错了,但是就是没找出来哪里出错了 应该是程序问题,逻辑分析仪看波形 没那么高级的东西,只用双通道示波器两两看过CSSCKSDI,和时序图也能对得上 哪位大哥有4K删除的源码的,可以贴出来,我看看跟我的有啥区别 最近刚好写过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