📄 w29c040读写程序.txt
字号:
W29C040(512K FLASH)读写程序2007-09-10 11:16很是激动,去年用AT89S52捣弄了半年也没搞定,这次换成C8051f040,也不知道是天见我可怜还是狗运,终于把数据写进去了。想当时到处找的程序都没用,郁闷非常,这次走运成功,拿出来晒晒太阳(虽然也是该的别人的程序,但是好歹能用)。
/*W29C040(512K FLASH)读写程序*/
#include <c8051f040.h>
#include <INTRINS.h>
#include <absacc.h>
sbit E=P1^0;
sbit RW=P1^1;
sbit RS=P1^2;
sbit A16=P4^0;//高地址16读写,推拉式
sbit A17=P4^1;//高地址17读写,推拉式
sbit A18=P4^2;//高地址18读写,推拉式
sbit CS=P4^4;//片选,低电平有效,推拉式
//C8051F040有两套外部存储器接口,为了方便,这里用第二套,且不用分时复用
sbit WR=P4^7
sbit RD=P4^6;
sbit Button=P3^7;
//P7 数据写推拉式,数据读漏极开路
//P6 低地址读写,推拉式
//P5 高地址读写,推拉式
//256B数组
unsigned int xdata Data[256]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255};
void Delay(unsigned int l_time);
void protect();
void erase();
void read();
void select_segment(unsigned char seg);
/***********************************************************************************/
void Reset_Sources_Init()//禁止看门狗
{
WDTCN = 0xDE;
WDTCN = 0xAD;
}
void EMI_Init()//设置EMI,WR=P4^7,RD=P4^6;P7 数据读写,P6 低地址读写,P5 高地址读写
{
SFRPAGE = EMI0_PAGE;
EMI0CF = 0x37;
}
void Port_IO_Init()//端口状态设置,推拉——漏极
{
SFRPAGE = CONFIG_PAGE;
P4MDOUT = 0xD0;
P5MDOUT = 0xFF;
P6MDOUT = 0xFF;
P7MDOUT = 0xFF;
XBR2 = 0x40;
}
void Init_Device(void)//初始化
{
Reset_Sources_Init();
EMI_Init();
Port_IO_Init();
}
/***********************************************************************************/
void SendCommandByte(unsigned char ch)//液晶1602写控制命令
{
RS=0;
RW=0;
P2=ch;
E=1;
Delay(10);
E=0;
Delay(100);
}
void SendDataByte(unsigned char ch)//液晶1602写数据
{ RS=1;
RW=0;
P2=ch;
E=1;
Delay(10);
E=0;
Delay(100);
}
void InitLcd()//液晶1602初始化
{
SendCommandByte(0x30);
SendCommandByte(0x30);
SendCommandByte(0x30);
SendCommandByte(0x38); //设置工作方式
SendCommandByte(0x0c); //显示状态设置
SendCommandByte(0x01); //清屏
SendCommandByte(0x06); //输入方式设置
}
void DisplayMsg1(unsigned char *p)//显示第一行
{
unsigned char count;
SendCommandByte(0x80); //设置DDRAM地址
Delay(2000);//根据单片机频率设置延时,以免液晶未准备好导致字符显示不完全
for(count=0;count<16;count++)
{
SendDataByte(*p++);
}
}
void DisplayMsg2(unsigned char *p)//显示第二行
{
unsigned char count;
SendCommandByte(0xc0); //设置DDRAM地址
Delay(2000);
for(count=0;count<16;count++)
{
SendDataByte(*p++);
}
}
/***********************************************************************************/
void write_data(unsigned int m_addr,unsigned int s_sector,unsigned int acount) //写数据
{
unsigned int data addraa; /* addraa 为内存地址,addrbb 为29C040地址 */
unsigned int data i,j;
bit flag;
addraa=m_addr;
for(j=acount;j>0;j--)
{
protect(); //接触保护 ?
CS=0;
select_segment(s_sector/256); /*s_sector 是256的整数倍*/
for(i=0;i<256;i++,addraa++)
{
XBYTE[addraa]=Data[i]; //高位
}
/*翻转位判断写入完成
--addraa;
ACC=Data[addraa];
flag=ACC^7;
while(1)
{
ACC=XBYTE[addraa];
if(ACC^7==flag) break;
flag=ACC^7;
}
*/
//延时等待写入完成
for(i=0;i<2;i++)
{
Delay(65535);
}
CS=1;
s_sector++;
}
}
/* 选择 29C040 段地址(高位地址),seg 为段地址*/
void select_segment(unsigned char seg)
{
P4&=0xf8;
switch(seg)
{
case 0: P4|=0x00; break; // 29c040 a18a17a16= 000 00000-0ffff
case 1: P4|=0x01; break; // 29c040 a18a17a16= 001 10000-1ffff
case 2: P4|=0x02; break; // 29c040 a18a17a16= 010 20000-2ffff
case 3: P4|=0x03; break; // 29c040 a18a17a16= 011 30000-3ffff
case 4: P4|=0x04; break; // 29c040 a18a17a16= 100 40000-4ffff
case 5: P4|=0x05; break; // 29c040 a18a17a16= 101 50000-5ffff
case 6: P4|=0x06; break; // 29c040 a18a17a16= 110 60000-6ffff
case 7: P4|=0x07; break; // 29c040 a18a17a16= 111 70000-7ffff
}
}
void protect() //解除保护?
{
select_segment(0);/*必须写到第0段*/
XBYTE[0x5555]=0xaa;
XBYTE[0x2aaa]=0x55;
XBYTE[0x5555]=0xa0;
}
void erase()//整片擦除
{
unsigned char i;
select_segment(0);/*必须写到第0段*/
CS=0;
XBYTE[0x5555]=0xaa;
XBYTE[0x2aaa]=0x55;
XBYTE[0x5555]=0x80;
XBYTE[0x5555]=0xAA;
XBYTE[0x2AAA]=0x55;
XBYTE[0x5555]=0x10;
CS=1;
for(i=0;i<6;i++)
{
Delay(65535);
}
_nop_();
}
void Read(unsigned int r_addr)//读数据
{
unsigned char ch1[16]="addr 0x ";
unsigned char ch2[16]="data 0x ";
unsigned char i;
unsigned int Data;
//读数据,P7为漏极开路
SFRPAGE = CONFIG_PAGE;
P4MDOUT = 0xD0;
P5MDOUT = 0xFF;
P6MDOUT = 0xFF;
XBR2 = 0x40;
CS=0;
_nop_();_nop_();_nop_();_nop_();_nop_();
Data=XBYTE[r_addr];
CS=1;
/***********************************************/
//转化为可显示ASCII字符
ch2[8]=Data%0x10+0x30;
ch2[7]=Data/0x10%0x10+0x30;
for(i=7;i<9;i++)
{
if(ch2[i]>0x39) ch2[i]+=0x7;
}
ch1[10]=r_addr%0x10+0x30;
ch1[9]=r_addr/0x10%0x10+0x30;
ch1[8]=r_addr/0x100%0x10+0x30;
ch1[7]=r_addr/0x1000%0x10+0x30;
for(i=7;i<11;i++)
{
if(ch1[i]>0x39) ch1[i]+=0x7;
}
/**********************************************/
SendCommandByte(0x01); //清屏
DisplayMsg1(ch1);
DisplayMsg2(ch2);
}
void Delay(unsigned int l_time)/*写完一个扇区后延时*/
{
unsigned int data lp;
for(lp=0;lp<l_time;lp++)
{;}
}
main()
{
unsigned char xdata msg1[16]="0123456789ABCDEF";
unsigned char xdata msg2[16]="....READY,GO!...";
unsigned int i;
Init_Device();
InitLcd();
DisplayMsg1(msg1);
DisplayMsg2(msg2);
erase();
write_data(0x2000,0,1);
for(i=0x2000;i<0x2100;i++)
{
Read(i);
while(1)//添加一个按钮,按一下地址自加一,并显示地址和读出的数据
{
if(Button==0)
{
while(Button==0){;}
break;
}
}
}
while(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -