电路:
C51读写W25Q测试通过
C51读写W25Q测试通过
最简单粗暴的:
//管脚定义
sbit fwcs =P1^7;
sbit fwsck =P5^4;
sbit fwsi =P5^5;
sbit fwso =P1^6;

//spi模拟写
void w25wspi(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
if(dat & 0x80)
{
fwso=1;
}
else
{
fwso=0;
}
fwsck=1;
dat=dat<<1;
fwsck=0;
}
fwso=1;
fwsck=0;
}
//spi模拟读
uchar w25rspi()
{
uchar i;
uchar rs;

for(i=0;i<8;i++)
{
	fwsck=0;
	rs=rs<<1;
	if(fwsi)
		rs=rs | 1;
	fwsck=1;
}
fwsck=0;
return rs;

}
//双倍速读
uchar w25frspi()
{
uchar i;
uchar rs;
for(i=0;i<4;i++)
{
rs=rs<<2;
fwsck=0;
if(fwsi)
rs=rs | 0x02;
if(fwso)
rs=rs | 0x01;
fwsck=1;
}
fwso=1;
fwsck=0;
return rs;
}

//读取状态寄存器1
uchar readrs1()
{
uchar rs;
fwcs=0;
w25wspi(ReadStatusRegister1);
rs=w25rspi();
fwcs=1;
return rs;
}

//读取状态寄存器2
uchar readrs2()
{
uchar rs;
fwcs=0;
w25wspi(ReadStatusRegister2);
rs=w25rspi();
fwcs=1;
return rs;
}

//读取状态寄存器3
uchar readrs3()
{
uchar rs;
fwcs=0;
w25wspi(ReadStatusRegister3);
rs=w25rspi();
fwcs=1;
return rs;
}
//初始化
void init_w25q128()
{
int i,j;
P1M1 = 0xC0; //开漏 1.6 、1.7
P1M0 = 0xC0; //开漏
P5M1 = 0x30; //开漏 5.4 、5.5
P5M0 = 0x30; //开漏
fwcs=1;
fwso=1;
fwsck=0;
//fwrst=1;
for(j=0;j<200;j++)
{
for(i=0;i<200;i++);
}
reset_w25q128();
}

//复位w25q128
void reset_w25q128()
{
uchar i;
fwcs=0;
w25wspi(EnableReset);
fwcs=1;
for(i=0;i<100;i++);
fwcs=0;
w25wspi(ResetDevice);
fwcs=1;
for(i=0;i<240;i++);
}

//读取数据
//buf:读出数据缓冲区f
//black_numb:块号
//page_numb:页号
//len:读取长度为 len+1,最多读256个字节
//成功返回 1,失败返回 0
uchar readdata(uchar * buf,uchar block_numb,uchar page_numb,uchar len)
{
uchar i,j;
uchar rs[4];

i=BUSY;
j=0;
//是否忙
while(i==BUSY)
{
	fwcs=0;
	w25wspi(ReadStatusRegister1);
	i=w25rspi();
	fwcs=1;
	i=i & BUSY;
	ms1(1);
	j++;
	if(j==128)
		return 0;
}

rs[0]=ReadData;
rs[1]=block_numb;
rs[2]=page_numb;
rs[3]=0;

fwcs=0;
for(i=0;i<4;i++)
{
	w25wspi(rs[i]);
}
for(i=0;i<len;i++)
{
	buf[i]=w25rspi();
}
buf[len]=w25rspi();
fwcs=1;
return 1;

}

//双倍速读,
uchar fastreaddata(uchar * buf,uchar block_numb,uchar page_numb,uchar len)
{
uchar i,j;
uchar rs[4];

i=BUSY;
j=0;
//是否忙
while(i==BUSY)
{
	fwcs=0;
	w25wspi(ReadStatusRegister1);
	i=w25rspi();
	fwcs=1;
	i=i & BUSY;
	ms1(1);
	j++;
	if(j==128)
		return 0;
}

rs[0]=FastReadData;
rs[1]=block_numb;
rs[2]=page_numb;
rs[3]=0;

fwcs=0;
for(i=0;i<4;i++)
{
	w25wspi(rs[i]);
}
P1M1 = 0xC0;
P1M0 = 0x80;
w25wspi(0x00);
for(i=0;i<len;i++)
{
	buf[i]=w25frspi();
}
buf[len]=w25frspi();
P1M1 = 0xC0;
P1M0 = 0xC0;
fwcs=1;
return 1;

}

//块擦除命令
//block_numb:块号
//成功返回 1,失败返回 0
uchar eraseblock(uchar block_numb)
{
uchar i,j;

//是否忙
i=BUSY;
j=0;
while(i==BUSY)
{
	ms1(1);
	fwcs=0;
	w25wspi(ReadStatusRegister1);
	i=w25rspi();
	fwcs=1;
	i=i & BUSY;
	j++;
	if(j==128)
		return 0;
}

//写使能
fwcs=0;
w25wspi(WriteEnable);
fwcs=1;

//写使能执行是否完成
i=0;
j=0;
while(i!=WEL)
{
	ms1(1);
	fwcs=0;
	w25wspi(ReadStatusRegister1);
	i=w25rspi();
	fwcs=1;
	i=i & WEL;
	j++;
	if(j==254)
		return 0;
}

//执行擦除命令
fwcs=0;
w25wspi(SectorErase64k);
w25wspi(block_numb);
w25wspi(0);
w25wspi(0);
fwcs=1;

//是否完成擦除
i=BUSY;
j=0;
while(i==BUSY)
{
	ms1(1);
	fwcs=0;
	w25wspi(ReadStatusRegister1);
	i=w25rspi();
	fwcs=1;
	i=i & BUSY;
	j++;
	if(j==254)
		return 0;
}
i=WEL;
j=0;
while(i==WEL)
{
	ms1(1);
	fwcs=0;
	w25wspi(ReadStatusRegister1);
	i=w25rspi();
	fwcs=1;
	i=i & WEL;
	j++;
	if(j==254)
		return 0;
}
return 1;

}
//页编程
//buf:要写入数据
//black_numb:块号
//page_numb:页号
//len:编程长度为 len+1,最写入256个字节
//成功返回 1,失败返回 0
uchar pageprogramblock(uchar * buf,uchar block_numb,uchar page_numb,uchar len)
{
uchar i,j;
i=BUSY;
j=0;
//是否忙
while(iBUSY)
{
ms1(1);
fwcs=0;
w25wspi(ReadStatusRegister1);
i=w25rspi();
fwcs=1;
i=i & BUSY;
j++;
if(j
128)
return 0;
}

//写使能
fwcs=0;
w25wspi(WriteEnable);
fwcs=1;

i=0;
j=0;
//写使能执行完成
while(i!=WEL)
{
	ms1(1);
	fwcs=0;
	w25wspi(ReadStatusRegister1);
	i=w25rspi();
	fwcs=1;
	i=i & WEL;
	j++;
	if(j==254)
		return 0;
}

//执行页编程
fwcs=0;
w25wspi(PageProgram);
w25wspi(block_numb);
w25wspi(page_numb);
w25wspi(0);
for(i=0;i<len;i++)
{
	w25wspi(buf[i]);
}
w25wspi(buf[len]);
fwcs=1;

//是否完成页编程
i=BUSY;
j=0;
while(i==BUSY)
{
	ms1(1);
	fwcs=0;
	w25wspi(ReadStatusRegister1);
	i=w25rspi();
	fwcs=1;
	i=i & BUSY;
	j++;
	if(j==254)
		return 0;
}
i=WEL;
j=0;
while(i==WEL)
{
	ms1(1);
	fwcs=0;
	w25wspi(ReadStatusRegister1);
	i=w25rspi();
	fwcs=1;
	i=i & WEL;
	j++;
	if(j==254)
		return 0;
}
return 1;

}

void ms1(uchar time) //@22.1184MHz
{
uchar i, j, m;
for(m=0;m<time;m++)
{
i = 29;
j = 183;
do
{
while (–j);
} while (–i);
}
}

/头文件*******
#ifndef W25Q128_H
#define W25Q128_H

#include “STC8.H”

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

//------------------------命令段----------------------------
#define WriteEnable 0x06 //写使能
#define WriteEnableVolatile 0x50 //易失性寄存器写使能
#define WriteDisable 0x04 //写禁止
#define ReadStatusRegister1 0x05 //读状态寄存器1
#define ReadStatusRegister2 0x35 //读状态寄存器2
#define ReadStatusRegister3 0x15 //读状态寄存器3
#define WriteStatusRegister1 0x01 //写状态寄存器1
#define WriteStatusRegister2 0x31 //写状态寄存器2
#define WriteStatusRegister3 0x11 //写状态寄存器3
#define ReadData 0x03 //读数据
#define PageProgram 0x02 //页编程
#define SectorErase64k 0xd8 //扇区擦除
#define ChipErase 0xc7 //芯片擦除
#define ReadUniqueIDNumber 0x4b //读取唯一设备号
#define ReadSFDPRegister 0x5a //读sfpd寄存器
#define EraseSecurityRegisters 0x44 //擦除安全寄存器
#define ProgramSecurityRegisters 0x42 //安全寄存器编程
#define ReadSecurityRegisters 0x48 //读取安全寄存器
#define IndividualBlockSectorLock 0x36 //单个块/扇区锁定
#define IndividualBlockSectorUnlock 0x39 //单个块/扇区解锁
#define ReadBlockSectorLock 0x3d //读取单个块/扇区锁
#define GlobalBlockSectorLock 0x7e //全局加锁
#define GlobalBlockSectorUnlock 0x98 //全局解锁
#define EnableReset 0x66 //复位使能
#define ResetDevice 0x99 //系统复位
#define FastReadData 0x3b //快速读取

//-----------------------------状态----------------------------------
#define BUSY 0x01 //W25Q128工作状态
#define WEL 0X02 //W25Q128写使能位

void ms1(uchar time);

void init_w25q128(); //加载W25Q128
void reset_w25q128(); //复位W25q128

uchar readrs1();
uchar readrs2();
uchar readrs3();

//读取数据
//buf:读出数据缓冲区f
//black_numb:块号
//page_numb:页号
//len:读取长度为 len+1,最多读256个字节
//成功返回 1,失败返回 0
uchar readdata(uchar * buf,uchar block_numb,uchar page_numb,uchar len);
uchar fastreaddata(uchar * buf,uchar block_numb,uchar page_numb,uchar len);

//块擦除命令
//block_numb:块号
//成功返回 1,失败返回 0
uchar eraseblock(uchar block_numb);

//页编程
//buf:要写入数据
//black_numb:块号
//page_numb:页号
//len:编程长度为 len+1,最写入256个字节
//成功返回 1,失败返回 0
uchar pageprogramblock(uchar * buf,uchar block_numb,uchar page_numb,uchar len);

void sendchr(uchar a1);

#endif

相关文章:

  • 2021-07-08
  • 2021-08-08
  • 2021-06-18
  • 2021-11-20
  • 2021-08-08
  • 2021-09-18
  • 2022-12-23
猜你喜欢
  • 2021-05-04
  • 2021-04-30
  • 2022-02-10
  • 2021-05-16
  • 2022-12-23
  • 2022-12-23
  • 2022-01-03
相关资源
相似解决方案