#define SF_WREN 0x06 //Flash命令
#define SF_WRDI 0x04
#define SF_RDSR 0x05
#define SF_WRSR 0x01
#define SF_READ 0x03
#define SF_FASTREAD 0x0B
#define SF_RDID 0x90
#define SF_PAGEPROG 0x02
//#define SF_RDCR 0xA1
//#define SF_WRCR 0xF1
#define SF_SECTORER 0x20
#define SF_BLOCKER1 0x52 //32KB
#define SF_BLOCKER2 0xD8 //64KB
#define SF_CHIPER 0xC7
//#define NULL 0
//#define FALSE 0
//#define TRUE 1
#define BUFFER_SIZE 256 //缓冲区大小
#define TEST_ADDR 512 //Flash测试地址
uchar idflag;
//uchar m=256;
uchar g_Buffer[BUFFER_SIZE];
/*
void waitsend();
void UART_Initial();
void send_char( uchar ch);
void spi_write(unsigned char spi_dat);
unsigned char spi_read();
//BYTE SpiShift(BYTE dat);
FlashCheckID();
void FlashBusy();
void FlashWriteEnable();
void FlashErase();
void FlashChipErase();
void FlashSectorErase();
void FlashBlockErase();
void FlashRead( addr, size,unsigned char *buffer);
void FlashWrite( addr, size,unsigned char *buffer);
*/
void waitsend()
{
TI = 0;
ES = 0;
while(!TI)
{
};
TI = 0;
ES = 1;
}
void delay(long i)
{
long j;
for(j=0;j
{
SomeNOP();
SomeNOP();
}
}
void delay1ms(long i)
{
long j;
for(j=0;j
{
delay(70);
}
}
// UART
void UART_Initial()
{
SCON = 0x50; //串口方式1,允许接收
TMOD = 0x20; //定时计数器1方式2
TH1 = 0xFD; //9600 波特率 FD
TL1 = 0xFD;
EA=1;
ES=1;
TR1 = 1;
}
//向串口发送一个字符
void send_char( uchar ch)
{
SBUF=ch;
//delay1ms(1);
//while (TI==0);
//TI=0;
}
/************************************************
使用SPI方式与Flash进行数据交换
入口参数:
dat : 准备写入的数据
出口参数:
从Flash中读出的数据
************************************************
BYTE SpiShift(BYTE dat)
{
SPDAT = dat; //触发SPI发送
while (!(SPSTAT & SPIF)); //等待SPI数据传输完成
SPSTAT = SPIF | WCOL; //清除SPI状态
return SPDAT;
}
*/
/************************************************
检测FlashID
W25Q16:0XEF14
************************************************/
unsigned char FlashCheckID()
{
uchar dat1,dat2;
uchar flag=0;
spi_cs = 0;
spi_write(SF_RDID); //发送读取ID命令
spi_write(0x00); //空读3个字节
spi_write(0x00);
spi_write(0x00);
dat1 = spi_read(); //读取制造商ID1
dat2 = spi_read(); //读取制造商ID2
spi_cs = 1;
flag = ((dat1==0xef)&&(dat2==0x14));
return flag;
}
/************************************************
检测Flash的忙状态读状态寄存器1
入口参数: 无
出口参数:
0 : Flash处于空闲状态
1 : Flash处于忙状态
************************************************/
FlashBusy(void)
{
uchar dat;
spi_cs = 0;
spi_write(SF_RDSR); //发送读取状态命令
dat = spi_read(); //读取状态
spi_cs = 1;
//if(dat&0x03)
//dat = 0x01;
//else
//dat = 0x00;
//return (dat);
return (dat & 0x01); //状态值的Bit0即为忙标志
}
/************************************************
使能Flash写命令
入口参数: 无
出口参数: 无
************************************************/
void FlashWriteEnable()
{
// while (FlashBusy()); //Flash忙检测
spi_cs = 0;
spi_write(0x06); //发送写使能命令
spi_cs = 1;
//delay1ms(10);
}
/************************************************
擦除整片Flash
入口参数: addr
出口参数: 无
************************************************/
void FlashChipErase(unsigned long addr)
{
FlashWriteEnable(); //使能Flash写命令
spi_cs = 0;
spi_write(SF_CHIPER); //发送擦除命令
spi_write(addr>>16 & 0xff); //设置起始地址
spi_write(addr>>8 & 0xff);
spi_write(addr & 0xff);
spi_cs = 1;
}
/************************************************
擦除扇区Flash
入口参数: addr
出口参数: 无
************************************************/
void FlashSectorErase(unsigned long addr)
{
FlashWriteEnable(); //使能Flash写命令
spi_cs = 0;
spi_write(SF_SECTORER); //发送擦除命令
spi_write(addr>>16 & 0xff); //设置起始地址
spi_write(addr>>8 & 0xff);
spi_write(addr & 0xff);
spi_cs = 1;
while (FlashBusy());
}
/************************************************
擦除BlockFlash(64KB)
入口参数: addr
出口参数: 无
************************************************/
void FlashBlockErase(unsigned long addr)
{
FlashWriteEnable(); //使能Flash写命令
spi_cs = 0;
spi_write(SF_BLOCKER2); //发送擦除命令
spi_write(addr>>16 & 0xff); //设置起始地址
spi_write(addr>>8 & 0xff);
spi_write(addr & 0xff);
spi_cs = 1;
}
/************************************************
从Flash中读取数据fastread
入口参数:
addr : 地址参数
size : 数据块大小
buffer : 缓冲从Flash中读取的数据
出口参数:
无
************************************************/
void FlashRead(unsigned long addr,unsigned long size, unsigned char *buffer)
{
while (FlashBusy()); //Flash忙检测
spi_cs = 0;
spi_write(SF_FASTREAD); //使用快速读取命令
spi_write(addr>>16); //设置起始地址
spi_write(addr>>8 );
spi_write(addr );
spi_write(0x00); //需要空读一个字节
while (size)
{
*buffer = spi_read(); //自动连续读取并保存
addr++;
buffer++;
size--;
}
spi_cs = 1;
}
/************************************************
写数据到Flash中
入口参数:
addr : 地址参数
size : 数据块大小
buffer : 缓冲需要写入Flash的数据
出口参数: 无
************************************************/
void FlashWrite( unsigned long addr,unsigned long size, unsigned char *buffer)
{
//while (FlashBusy());
//while (size)
//{
//uchar i;
FlashWriteEnable(); //使能Flash写命令
spi_cs = 0;
spi_write(SF_PAGEPROG); //发送页编程命令
spi_write(addr>>16 ); //设置起始地址
spi_write(addr>>8 );
spi_write(addr );
//for (i=0; i<0x100; i++)
//{
//spi_write(*buffer);
//size--;
//buffer++;
//}
while (size)
{
spi_write(*buffer); //连续页内写
buffer++;
addr++;
//buffer++;
size--;
//if ((addr & 0xff) == 0) break;
}
spi_cs = 1;
//while (FlashBusy());
// }
}
void main()
{
int i;
for (i=0; i
{
g_Buffer[i]=i;
}
//初始化Flash状态
//g_fFlashOK = FALSE;
//初始化串口
UART_Initial();
delay1ms(2);
FlashSectorErase(TEST_ADDR);
delay1ms(200);
while(1)
{
//for (i=0; i
//{
//send_char(g_Buffer[i]),waitsend();
//delay1ms(100);
//}
//i=0;
//检测Flash状态
idflag = FlashCheckID();
send_char(idflag),waitsend();
delay1ms(1000);
//send_char(0x01), waitsend();
//将缓冲区的数据写到Flash中
FlashWrite(TEST_ADDR, BUFFER_SIZE, g_Buffer);
//send_char(addr);
delay1ms(100);
//读取测试地址的数据
FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
delay1ms(100);
//发送到串口
for (i=0; i
{
send_char(g_Buffer[i]),waitsend();
delay1ms(100);
}
/*
//擦除Flash
FlashErase();
//读取测试地址的数据
FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
//发送到串口
for (i=0; i
//修改置缓冲区
for (i=0; i>2;
//将缓冲区的数据写到Flash中
FlashWrite(TEST_ADDR, BUFFER_SIZE, g_Buffer);
//读取测试地址的数据
FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
//发送到串口
for (i=0; i
FlashErase();
//读取测试地址的数据
FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
//发送到串口
for (i=0; i
//修改置缓冲区
for (i=0; i>2);
//将缓冲区的数据写到Flash中
FlashWrite(TEST_ADDR, BUFFER_SIZE, g_Buffer);
//读取测试地址的数据
FlashRead(TEST_ADDR, BUFFER_SIZE, g_Buffer);
//发送到串口
for (i=0; i
*/
}
}
程序如上
|