| |
sst29sf040当作数据存储器,数据会丢失吗? |
|
|
| 出处:21ic 时间: 2007-09-30 |
|
ccjchen 发布于 2007-9-26 21:13:00 请问各位大虾我把时为什么在单片机掉电或复位后数据又恢复原来初始化的值啊?sst29sf040是flash阿,数据怎么会丢失呢?
aibxyz 发布于 2007-9-27 9:34:00 这个我用过,还不错的
ccjchen 发布于 2007-9-27 14:20:00 那我读了以后怎么能把读到的数据显示出来呢?
john_light 发布于 2007-9-27 14:57:00 比如要写入的数据保存在数组DataToWrite[]中,写入后将数据读回数组DataReadBack[]中,然后比较这两个数组。相同的话就点灯或什么……
ccjchen 发布于 2007-9-28 13:43:00 我声明了两个数组,要写入的数据保存在数组DataToWrite[]中,写入后将数据读回数组DataReadBack[]中,在软件中发现XDATA数据一样,但是我用示波器却在sst29sf040的RD端一直看到高电平,而没有波形,而在WR端却能看到波形,这是为什么?难道硬件根本没通,上面那些只是软件仿真吗?
john_light 发布于 2007-9-28 14:25:00 你最好先实现Product Identification过程,看能否读回正确的芯片ID:0xBF13。
具体实现仔细阅读datasheet。
ccjchen 发布于 2007-9-29 14:11:00 这说明编址应该正确吧,读写也应该正确吧,但是为什么断电后数据恢复为初始化时的数值呢?我是将uchar idata syn[8]={"24.5 6 0"}调在LCD中显示出来,然后通过增减按键改变syn[8]={"24.5 6 0"}的数值,保存在sst29sf040中,但是为什么一断电后从新接好电源或单片机复位后,在LCD中显示的值又恢复为syn[8]={"24.5 6 0"},这是怎么回事呢?
john_light 发布于 2007-9-29 14:46:00 能正确读回ID表示硬件连接大概没问题了(至少低十二条地址线,八条数据线还有读、写、片选等正常)。
The first step is the three-byte load sequence for Software Data Protection. The second step is to load byte address and byte data.
你在进行字节写的时候先按顺序写那三个字节了吗? 写后进行Data# Polling了吗?
ccjchen 发布于 2007-9-29 21:22:00 能否把你的程序发上来我看一下阿?唉,搞了好长时间了,都没进展!
john_light 发布于 2007-9-30 8:17:00 2004年写的,针对AT29C040A,简直惨不忍睹,不敢拿出来丢丑。
把你的贴上来吧,我看看。
john_light 发布于 2007-9-30 8:56:00 如U-boot就有一些flash.c可供参考。
ccjchen 发布于 2007-9-30 9:31:00 #define _SST_C_ #include "reg51.h" #include "sst.h" #include <intrins.h> #include <absacc.h>
#define SECTOR_SIZE 128 /*Must be 128 bytes for 29EE020*/
#define SST_ID 0xBF #define SST_29SF040 0X13 #define uchar unsigned char #define uint unsigned int uchar idata syn[8]={"24.5 6 0"};
void wait(uchar p,uchar q); int Check_SST_29SF040(); void Check_Toggle_Ready(uint Dst); void ByteProgram(uchar SrcByte,uint Dst); int Erase_One_Sector(uint Dst); uchar ByteRead(uint addr);
void main(void) { initlcm();//初始化lcd initmcu();//初始化89C52 for(;;) { if(ByteRead(0x0080+7)==3)///这里用来证明数据是否写进 //检查最后一个数据是否是3,如果是从Flash中读取数据更新syn
{ sst_read(); } else { sst_write(); } } syn_add();//syn增 syn_dec();//syn减这两个 sst_write();//改变syn后写进sst29sf040内 }
void ByteProgram(uchar data SrcByte,uint Dst) { XBYTE[0x0555] = 0xAA; XBYTE[0x02AA] = 0x55; XBYTE[0x0555] = 0xA0; XBYTE[Dst] = SrcByte; //Check_Toggle_Ready(Dst); wait(1,9);//等待25us }
int Check_SST_29SF040() { uchar SST_id1; uchar SST_id2; int ReturnStatus; /* Issue the Software ID code to 29sf040*/ XBYTE[0x0555]= 0xAA;/* set up address to be 555h */ /* write data 0xAA to the address */ XBYTE[0x02AA]= 0x55;/* set up address to be 2AAh */ /* write data 0x55 to the address */ XBYTE[0x0555]= 0x90; wait(61,74); /*delay 10ms*/ /*read the product ID from29sf040*/ /* set up address to be 0000h */ SST_id1 = XBYTE[0x0000] ; /* get first ID byte???????????????*/ SST_id2 = XBYTE[0x0001];/* set up address to be 0001h */ if ((SST_id1 ==SST_ID)&&(SST_id2 == SST_29SF040)) { ReturnStatus = 1; } else ReturnStatus = 0; /* Issue the Soffware Product ID Exit code thus returning the 29EE020 */ /* to the read operating mode */ /* set up address to be 555h */ XBYTE[0x0555] = 0xAA; /* write data 0xAA to the address */ /* set up address to be 2AAh */ XBYTE[0x02AA] = 0x55; /* write data 0x55 to the address */ /* set up address to be 555h */ XBYTE[0x0555] =0xF0; /* write data 0xF0 to the address */ wait(61,74); /*delay 10ms*/ return(ReturnStatus);
}
int Erase_One_Sector(uint Dst) {
/* Issue the Sector Erase command to 39SF040 */
XBYTE[0x0555] = 0xAA; /* set up address to be 555h */ /* write data 0xAA to the address */ XBYTE[0x02AA] = 0x55; /* set up address to be 2AAh */ /* write data 0x55 to the address */ XBYTE[0x0555] = 0x80; /* set up address to be 555h */ /* write data 0x80 to the address */ XBYTE[0x0555] = 0xAA; /* set up address to be 555h */ /* write data 0xAA to the address */ XBYTE[0x02AA] = 0x55; /* set up address to be 2AAh */ /* write data 0x55 to the address */ XBYTE[Dst] = 0x20; /* set up starting address to be erased */ /* write data 0x30 to the address */ wait(85,134); /* check DATABOOK for the most */ /* accurate value -- Tse */ }
uchar ByteRead(uint addr) { uchar GetData; GetData = XBYTE[addr]; return(GetData); } void wait(uchar p,uchar q) { uchar i,j; //(2*j+3)*i+4 for (i=p;i>0;i--)
for (j=q;j>0;j--); }
void sst_read() { uchar i; for(i=0;i<4;i++) { syn[2*i+1]=ByteRead(0x0080+i); } for(i=4;i<8;i++) { ByteRead(0x0080+i); } } void sst_write()//用于保存易丢失数据 { uchar i; Erase_One_Sector(128); for(i=0;i<4;i++) { ByteProgram(syn[2*i+1],0x0080+i); } for(i=4;i<8;i++) { ByteProgram(3,0x0080+i); } } void syn_add(void) { SendCMD(0x06);SendCMD(0x0f); SendCMD(0|0x90); put_str(0x80,synth,11); put_str(0x90,syn,8);//lcd上显示syn if(ff==1) { switch(fan) { case 0:fan=0; if(flag5==1) { flag5=0; syn[1]++; } if(syn[1]>=0x3a) { syn[1]='9'; } SendCMD(0|0x90); break; case 1:fan=1; if(flag5==1) { flag5=0; syn[3]++; } if(syn[3]>=0x3a) { syn[3]='9'; } SendCMD(1|0x90); break; case 2:fan=2; if(flag5==1) { flag5=0; syn[5]++; } if(syn[5]>=0x3a) { syn[5]='9'; } SendCMD(2|0x90); break; case 3:fan=3; if(flag5==1) { flag5=0; syn[7]++; } if(syn[7]>=0x3a) { syn[7]='9'; } SendCMD(3|0x90); break; default: break; } } } void syn_dec(void) { SendCMD(0x06);SendCMD(0x0f); SendCMD(0|0x90); put_str(0x80,synth,11); put_str(0x90,syn,8); if(ff==1)//ff用来防止其它按键后再按此键,键值发生变化 {//ff用来保证只有8键按下后再按下16键syn值才会变化 switch(fan) { case 0:fan=0; if(flag5==1) { flag5=0; syn[1]--; } if(syn[1]<=0x2f) { syn[1]='0'; } SendCMD(0|0x90); break; case 1:fan=1; if(flag5==1) { flag5=0; syn[3]--; } if(syn[3]<=0x2f) { syn[3]='0'; } SendCMD(1|0x90); break; case 2:fan=2; if(flag5==1) { flag5=0; syn[5]--; } if(syn[5]<=0x2f) { syn[5]='0'; } SendCMD(2|0x90); break; case 3:fan=3; if(flag5==1) { flag5=0; syn[7]--; } if(syn[7]<=0x2f) { syn[7]='0'; } SendCMD(3|0x90); break; default: break; } }
}
john_light 发布于 2007-9-30 9:52:00 你的CPU是89C52? A16~A18你怎么连接的?
john_light 发布于 2007-9-30 10:13:00 #define _SST_C_ #include "reg51.h" #include "sst.h" #include <intrins.h> #include <absacc.h>
#define SECTOR_SIZE 128 /*Must be 128 bytes for 29EE020*/
#define SST_ID 0xBF #define SST_29SF040 0X13 #define uchar unsigned char #define uint unsigned int uchar idata syn[8]={"24.5 6 0"}; //这个字符串8个字节装不完
void wait(uchar p,uchar q); int Check_SST_29SF040(); void Check_Toggle_Ready(uint Dst); void ByteProgram(uchar SrcByte,uint Dst); int Erase_One_Sector(uint Dst); uchar ByteRead(uint addr);
void main(void){ initlcm();//初始化lcd initmcu();//初始化89C52 for(;;) { if(ByteRead(0x0080+7)==3)//这里用来证明数据是否写进 //检查最后一个数据是否是3,如果是从Flash中读取数据更新syn { sst_read(); }else{ sst_write(); } }
//死循环后面还有东西? syn_add();//syn增 syn_dec();//syn减这两个 sst_write();//改变syn后写进sst29sf040内 }
void ByteProgram(uchar data SrcByte,uint Dst){ XBYTE[0x0555] = 0xAA; XBYTE[0x02AA] = 0x55; XBYTE[0x0555] = 0xA0; XBYTE[Dst] = SrcByte; //Check_Toggle_Ready(Dst); //wait(1,9);//等待25us while(XBYTE[Dst] != SrcByte){//Data# Polling的变通实现/不建议采用固定的延时(不同的芯片不同的速度可能会有不同结果) ;//考虑超时处理 } }
int Check_SST_29SF040(){ uchar SST_id1; uchar SST_id2; int ReturnStatus; /* Issue the Software ID code to 29sf040*/ XBYTE[0x0555]= 0xAA;/* set up address to be 555h */ /* write data 0xAA to the address */ XBYTE[0x02AA]= 0x55;/* set up address to be 2AAh */ /* write data 0x55 to the address */ XBYTE[0x0555]= 0x90; wait(61,74); /*delay 10ms*/ /*read the product ID from29sf040*/ /* set up address to be 0000h */ SST_id1 = XBYTE[0x0000] ; /* get first ID byte???????????????*/ SST_id2 = XBYTE[0x0001];/* set up address to be 0001h */ if ((SST_id1 ==SST_ID)&&(SST_id2 == SST_29SF040)){ ReturnStatus = 1; }else{ ReturnStatus = 0; }
/* Issue the Soffware Product ID Exit code thus returning the 29EE020 */ /* to the read operating mode */ /* set up address to be 555h */ XBYTE[0x0555] = 0xAA; /* write data 0xAA to the address */ /* set up address to be 2AAh */ XBYTE[0x02AA] = 0x55; /* write data 0x55 to the address */ /* set up address to be 555h */ XBYTE[0x0555] =0xF0; /* write data 0xF0 to the address */ wait(61,74); /*delay 10ms*/ return(ReturnStatus);
}
int Erase_One_Sector(uint Dst){
/* Issue the Sector Erase command to 39SF040 */
XBYTE[0x0555] = 0xAA; /* set up address to be 555h */ /* write data 0xAA to the address */ XBYTE[0x02AA] = 0x55; /* set up address to be 2AAh */ /* write data 0x55 to the address */ XBYTE[0x0555] = 0x80; /* set up address to be 555h */ /* write data 0x80 to the address */ XBYTE[0x0555] = 0xAA; /* set up address to be 555h */ /* write data 0xAA to the address */ XBYTE[0x02AA] = 0x55; /* set up address to be 2AAh */ /* write data 0x55 to the address */ XBYTE[Dst] = 0x20; /* set up starting address to be erased */ /* write data 0x30 to the address */ wait(85,134); /* check DATABOOK for the most */ /* accurate value -- Tse */ //不建议采用固定的延时(参考字节编程部分) }
uchar ByteRead(uint addr){ uchar GetData; GetData = XBYTE[addr]; return(GetData); }
void wait(uchar p,uchar q){ uchar i,j; //(2*j+3)*i+4 for (i=p;i>0;i--){ for (j=q;j>0;j--){ ; } } }
void sst_read(){ uchar i; for(i=0;i<4;i++) { syn[2*i+1]=ByteRead(0x0080+i);
} for(i=4;i<8;i++) { ByteRead(0x0080+i); } }
void sst_write()//用于保存易丢失数据 { uchar i; Erase_One_Sector(128); for(i=0;i<4;i++) {
ByteProgram(syn[2*i+1],0x0080+i);
} for(i=4;i<8;i++) { ByteProgram(3,0x0080+i); } }
john_light 发布于 2007-9-30 10:28:00 我觉得你的问题不是数据丢失,而是数据根本没存进去。
2004年,我初次使用ATMEL的AT29C040A,由于是DIP封装,非常方便调试。
我先确定硬件的正确连接: 1、读FlashID; 2、用通用编程器往芯片不同特定地址写入特定数据,然后在程序中读回验证。
然后尝试片擦除: 用通用编程器读回验证。
再然后字节编程: (AT29C040A要求一次要写入256字节的一个扇区)。 用通用编程器读回验证。
得益于DIP封装和通用编程器,我很快就掌握了这种Flash的编程方法。
|
| 【关闭】 【打印】 |
|
|
|
|