本帖最后由 lvben5d 于 2019-4-28 19:45 编辑
用的不多 但没遇到过这个情况, 你看下,会不会是自己代码软件问题。 比如你串口接收的处理 是否来得及 收1个 擦1个。。应用没讲清,下面是我调试过OK的 w25 FLASH 你可以参考。
/*返回 1 表示超时 学习Linux的返回值方式 0表示成功*/
unsigned char w25qxx_wait_idle(void)
{
unsigned char w25q_state=0x0F;
unsigned short int timeout=0;
W25QXX_CS_L;
SEND_BYTE(W25Q_ReadStatusReg);
while((w25q_state&0x01) && (++timeout<60000))
{
w25q_state = RECV_BYTE(W25Q_ReadStatusReg);
delay_us(20);
}
W25QXX_CS_H;
if(timeout==60000) return 1;
else return 0;
}
/*当用户的MCU主频过快的时候,片选时间需要注意*/
void w25qxx_write_enable(void)
{
W25QXX_CS_L;
SEND_BYTE(W25Q_WriteEnable); //使能写寄存器
W25QXX_CS_H;
}
void w25qxx_write_disable(void)
{
W25QXX_CS_L;
SEND_BYTE(W25Q_WriteDisable); //禁能写寄存器
W25QXX_CS_H;
}
/*芯片一次擦除的是4KB 所以我们应用需要安排好*/
void w25qxx_sector4KB_erase(unsigned long sector_addr)
{
//u8 state ;
//state = w25qxx_wait_idle();
//if(state!=0) return 1; //这段代码加这里 模块就不能正常擦除。见鬼
w25qxx_write_enable();
W25QXX_CS_L;
SEND_BYTE(W25Q_SectorErase);
SEND_BYTE(sector_addr >> 16);
SEND_BYTE(sector_addr >> 8);
SEND_BYTE(sector_addr);
W25QXX_CS_H;
//state = w25qxx_wait_idle();
/*
if(state!=0) return 1; //超时 加这里就没事。 奇怪
*/
}
/*芯片块擦除分32KB和64KB */
void w25qxx_block32KB_erase(unsigned long block_addr)
{
w25qxx_write_enable();
W25QXX_CS_L;
SEND_BYTE(W25Q_BlockErase_32KB);
SEND_BYTE(block_addr >> 16);
SEND_BYTE(block_addr >> 8);
SEND_BYTE(block_addr);
W25QXX_CS_H;
}
/*
一般擦除一个扇区,然后从页的首地址写入信息,因为FLASH的特性决定这样应用合适!
需要先读出这页的数据到RAM,
编译器会自动取0x12345678 低字节0x78 如果大小端方式不同,则需要注意修改。
注意: 用户需注意自己传递的指针p的范围,避免越界!!1~256个字节
*/
unsigned char w25qxx_write_Nbytes(unsigned long page_addr, unsigned char *p, unsigned short int m)
{
unsigned short int cnt;
cnt = w25qxx_wait_idle(); //确保上一次擦或写的操作已经完成。
if(cnt!=0) return 1; //超时
w25qxx_write_enable();
if(m==0) { m=1; return 2; }; //不能传递0个数据写入SPI FLASH
W25QXX_CS_L;
SEND_BYTE(W25Q_PageProgram);
SEND_BYTE(page_addr >> 16);
SEND_BYTE(page_addr >> 8);
SEND_BYTE(page_addr);
for(cnt=0; cnt<m; cnt++) //1~256个字节
{
SEND_BYTE(*p++);
}
W25QXX_CS_H;
return 0; //成功
}
/*只要CS步拉高,就可以一直读下去*/
unsigned char w25qxx_read_Nbytes(unsigned long page_addr, unsigned char *prcv_buf, unsigned short int m)
{
unsigned short int cnt;
cnt = w25qxx_wait_idle();
if(cnt!=0) return 1; //超时
W25QXX_CS_L;
SEND_BYTE(W25Q_ReadData);//W25Q_ReadData);
SEND_BYTE(page_addr >> 16);
SEND_BYTE(page_addr >> 8);
RECV_BYTE(page_addr);
for(cnt=0; cnt<m; cnt++) //1~256个字节
{
*prcv_buf = RECV_BYTE(0x00);
prcv_buf++;
}
W25QXX_CS_H;
return 0;
}
|