标题:
单片机W25X16读写程序
[打印本页]
作者:
wangruihua215
时间:
2016-11-17 14:00
标题:
单片机W25X16读写程序
51单片机读写25X16程序,简单昨懂
全部源码下载:
51读写W25X16程序.rar
(45.03 KB, 下载次数: 54)
2016-11-17 14:00 上传
点击文件名下载附件
下载积分: 黑币 -5
预览:
#include <intrins.h> //包含位移和_nop_();
#include "STC12C5A60S2.H"
//***************************************************************
void WriteDisable (void); //写禁止
void WriteEnable (void); //写允许
unsigned char W25X_BUSY_OrNot (void); //判忙碌
void W25X_ChipErase(void); //片擦除
void W25X_BlockErase(unsigned long Addre24);
void W25X_SectorErase(unsigned long Addre24); //擦除资料图示的4KB空间
//读数据可以无限次,这里是由缓冲决定的大小
void W25X_Flash_Byte_Read (unsigned long Addre24,unsigned char Quantity);//多字节读FLASH(1~256) -W25X32-000000-3FFF00(4M)-
void W25X_Flash_Byte_Write(unsigned long Addre24,unsigned char Quantity); //往FLASH里写一个或多个字节(小于256字节)
unsigned char Read_OneByte(void); //从SPI收8位数
void Send_OneByte(unsigned char DATA8);
void InitSerial(void); //串行口初始化.通信速率9600bps 在22.1184MHz晶振频率
void Delay100ms(unsigned int _100ms); //100ms级延时
//进度: 发一个指令OK 写允许OK 读状态OK 读写一个字节OK
unsigned char xdata Send_DATA[256]; //要发送的数据
unsigned char xdata Recv_DATA[256]; //已接收的数据, 如2个数,则为Recv_DATA[0] Recv_DATA[1]
unsigned char * Send_Pionter;
unsigned char * Recv_Pionter;
void main()
{
unsigned char BUSY; //判忙碌
unsigned long Addre24; //24位的Flash地址
unsigned char x=0;
unsigned char A;
unsigned char B;
unsigned char C;
unsigned long D;
//************************
A=0; B=0; C=0; D=0;
Delay100ms(2);
if(x)
{
WriteDisable (); //写禁止
W25X_ChipErase(); //片擦除
W25X_SectorErase(Addre24); //4K擦除
W25X_BlockErase (Addre24); //64K块擦除
BUSY=W25X_BUSY_OrNot(); //判忙碌
W25X_Flash_Byte_Read (Addre24,21); //读FLASH
W25X_Flash_Byte_Write(Addre24,21); //写入
}
//*************************
P1M0=0xB0;
InitSerial(); //串行口初始化.通信速率9600bps 在22.1184MHz晶振频率
Send_Pionter = &Send_DATA[0]; //发送指针取地址
Recv_Pionter = &Recv_DATA[0]; //接收指针取地址
for (D=0;D<256;D++)
{
Send_DATA[D]=D;
Recv_DATA[D]=0;
}
W25X_SectorErase(Addre24); Delay100ms (4); //4K擦除
//**************************
W25X_Flash_Byte_Write(0x000000,255); //写N个数
W25X_Flash_Byte_Read (0x000000,255); //读X个数
while(1)
{
SBUF =A;
while(TI==0);
TI=0;
SBUF =Recv_DATA[A] ;
while(TI==0);
TI=0;
Delay100ms(1);
A++;
}
} // End of Main
//*******************END of Main****************************
// ----W25X系统Flash读写---SUNYA注----
//sbit CS = P1^4; //选通
//sbit DIO = P1^5; //单片机输出
//sbit DO = P1^6; //FLASH输出
//sbit SCLK = P1^7; //时钟
//读写SPI口模拟模式3,时钟平时为高电平
//#define W25X_ReadStatus 0x05 //读状态寄存器
//#define W25X_WriteStatus 0x01 //写状态寄存器
//#define W25X_ReadDATA8 0x03 //普读_数据
//#define W25X_FastRead 0x0B //快读_数据
//#define W25X_DualOutput 0x3B //快读_双输出
//#define W25X_Write 0x02 //写_数据_0~255个字节
//#define W25X_S_Erase 0x20 //扇区擦除4KB
//#define W25X_B_Erase 0xD8 //块区擦除64KB
//#define W25X_C_Erase 0xC7 //整片格式化
//#define W25X_PowerDown 0xB9 //待机
//#define W25X_PowerON_ID 0xAB //开机或是读ID
//#define W25X_JEDEC_ID 0x9F //十六位的JEDEC_ID
//#define W25X_WriteEnable 0x06 //写充许
//#define W25X_WriteDisable 0x04 //写禁止
//#define W25X_BUSY 0x01 //FLASH忙
//#define W25X_NotBUSY 0x00 //FLASH闲 这是自定义的
//***************判BUSY********************************
unsigned char W25X_BUSY_OrNot (void) //在读和写之前得先判断FLASH是否BUSY
{ //BUSY的原因是擦除,或是连续读写
unsigned char k; //如果没有以上方式,不必判定可以写读
SCLK=1;
_nop_();
CS=0;
Send_OneByte(W25X_ReadStatus); //读状态寄存器
k=Read_OneByte(); //读一个字节
k=k&0x01;
CS=1;_nop_();
SCLK=1;
if(k)return (W25X_BUSY);
else return (W25X_NotBUSY);
} //end of check BUSY
//***********************************************
void W25X_Flash_Byte_Write(unsigned long Addre24,unsigned char Quantity) //往FLASH里写一个或多个字节(小于255)
{ //连续写的时候,地址最后八位必须从00开始写 *如果256个字节都读满或写满,三字节地址最后一个字节必须为0*
unsigned char Addre3; //否则当地址越过分面时,会从本页的00从新开始,造成错写
unsigned char Addre2; //^^现在本函数没启用连写连读
unsigned char Addre1;
unsigned char J; //计字节数
unsigned char x;
while(W25X_BUSY_OrNot ()); //判BUSY 等到Flash闲才能操作
WriteEnable(); //写允许
SCLK=1;
Addre1=Addre24;
Addre24=Addre24>>8;
Addre2=Addre24;
Addre24=Addre24>>8;
Addre3=Addre24; //把地址拆开来
CS=0;
Send_OneByte(W25X_Write); //命令
Send_OneByte(Addre3);
Send_OneByte(Addre2);
Send_OneByte(Addre1);
for (J=0;J<Quantity;J++)
{
Send_OneByte(Send_DATA[J]); //写字节
}
CS=1;
_nop_();_nop_();
SCLK=1;
for(x=0;x<200;x++) //延时一点点
{
_nop_();_nop_();
}
Addre24=0; //地址清0
} //写FLASH结束
//***********************************************
void W25X_Flash_Byte_Read (unsigned long Addre24,unsigned char Quantity) //从Flash里读出小于256字节数
{
unsigned char xdata DATA8[256]; //要返回的字节
unsigned char * DATA; //定义一个指针
unsigned char J; //计字节数
unsigned char Addre3;
unsigned char Addre2;
unsigned char Addre1;
while(W25X_BUSY_OrNot ()); //判BUSY
DATA=&DATA8[0]; //指针指向DATA8[256]
Addre1=Addre24;
Addre24=Addre24>>8;
Addre2=Addre24;
Addre24=Addre24>>8;
Addre3=Addre24; //把地址拆开来
CS=0;
Send_OneByte(W25X_ReadDATA8);//命令读
Send_OneByte(Addre3);
Send_OneByte(Addre2);
Send_OneByte(Addre1);
for (J=0;J<Quantity;J++)
{
Recv_DATA[J]=Read_OneByte(); //读一个字节
}
CS=1;
_nop_();_nop_();
SCLK=1;
_nop_();_nop_();
Addre24=0; //地址清0
} //读FLASH结束
//*********************************************** OK
void Send_OneByte(unsigned char DATA8) //从SPI发8位数
{ //上升沿写入
unsigned char x;
for (x=0;x<8;x++)
{
SCLK=0;
if(DATA8&0x80)DIO=1;
else DIO=0;
SCLK=1;
DATA8=DATA8<<1;
}
//发完后SCLK为1
} //end of Send_OneByte
//*********************************************** OK
unsigned char Read_OneByte(void) //从SPI收8位数
{ //下降沿输出
unsigned char DATA8;
unsigned char x;
SCLK=1;
DATA8=0x00;
for (x=0;x<8;x++)
{
_nop_();
SCLK=0;
DATA8=DATA8<<1;
if(DO)DATA8=DATA8|0x01;
SCLK=1;
}
return (DATA8);
//完成后SCLK=1
}//end of Read_OneByte
//**************片擦除 (MAX_80S)****************** OK
void W25X_ChipErase(void)
{
//BUSY ?
WriteEnable(); //写允许
SCLK=1;
CS=0;
Send_OneByte(W25X_C_Erase);//整片擦除命令
CS=1; //从CS=1时开始执行擦除
SCLK=1;
}
//*************** 4K扇擦除************************ OK
void W25X_SectorErase(unsigned long Addre24) //擦除资料图示的4KB空间
{
//判BUSY或许放这里
unsigned char Addre3;
unsigned char Addre2;
unsigned char Addre1;
WriteEnable(); //写允许
Addre1=Addre24;
Addre24=Addre24>>8;
Addre2=Addre24;
Addre24=Addre24>>8;
Addre3=Addre24; //把地址拆开来
SCLK=1;
CS=0;
Send_OneByte(W25X_S_Erase);//整扇擦除命令
Send_OneByte(Addre3);
Send_OneByte(Addre2);
Send_OneByte(Addre1);
CS=1;
_nop_();
SCLK=1;
_nop_();_nop_();
Addre24=0; //地址清0
}
//*************** 64K页/块擦除************************* OK
void W25X_BlockErase(unsigned long Addre24) //擦除资料图示的64KB空间
{
//判BUSY或许放这里
unsigned char Addre3;
unsigned char Addre2;
unsigned char Addre1;
WriteEnable(); //写允许
Addre1=Addre24;
Addre24=Addre24>>8;
Addre2=Addre24;
Addre24=Addre24>>8;
Addre3=Addre24; //把地址拆开来
SCLK=1;
CS=0;
Send_OneByte(W25X_B_Erase);//整扇擦除命令
Send_OneByte(Addre3);
Send_OneByte(Addre2);
Send_OneByte(Addre1);
CS=1;
_nop_();_nop_();
SCLK=1;
_nop_();_nop_();
Addre24=0; //地址清0
}
//*************** 写允许 **************************** OK
void WriteEnable (void)
{
SCLK=1;
CS=0;
Send_OneByte(W25X_WriteEnable);
CS=1;
SCLK=1;
}
//*************** 写禁止 **************************** OK
void WriteDisable (void)
{
SCLK=1;
CS=0;
Send_OneByte(W25X_WriteDisable);
CS=1;
SCLK=1;
}
//******************************************************** OK
void Delay100ms(unsigned int _100ms) //100ms级延时
{
unsigned char n,i,ms,loop;
for(loop=12;loop>0;loop--) //STC12C5412AD为快速单片机,此100ms延时要快6倍
{ ms=_100ms; //晶体为11.0592MHz
for(;ms>0;ms--)
for(n=145;n>0;n--)
for(i=251;i>0;i--)_nop_();
}
}
//***************************************//串行口初始化 OK
void InitSerial(void) //串行口初始化.通信速率9600bps 在22.1184MHz晶振频率
{
SCON = 0x50;
BRT = 250;
AUXR = 0x11; //使用独立波特率发生器
AUXR1= 0x80;
ES=1;
EA=1;
/*
TR1=0;
ET1=0; //定时器1禁止中断
TMOD=TMOD&0xCF;
TMOD=TMOD|0x20; //通信方式2
TH1=0xFF; //波特率:bps
TL1=0xFF; //1位起始位,8位数据位,2位停止位,无校验
SCON=0xD8;
PCON=0x80;
TR1=1; //开启定时
ES=1;
*/
//IE=IE|0x90; //开中断,允许串口中断
}
//***************************************************************
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1