stc12c5a60s2单片机EEPROM的问题

今天用这个单片机的EEPROM存储数据,经过测试发现,一次最多只能读写20个字节的数据,如果超过这个大小,就会导致数据丢失,不知道大家有木有遇到过这种情况。
我本来是往里面存了两个数组,分别是26个数据和25个数据,发现从第20位往后就出现异常,刚开始以为这两个数据的起始地址弄错了,导致数据覆盖,后来想了想,数据不可能覆盖的,因为没有执行擦除指令,而且即便是覆盖了,在读取的时候应该会读出后面那个数组的内容。我多次检查程序,确认没有程序错误。就开始怀疑单片机自身缺陷了,后来我把那两个数组分别拆开写,拆成了四个,每个十几个数据,之后就没再出现错误。由此确认该单片机确实存在缺陷,再测试几次后发现,每次最多就能读或写20个字节,多了就会丢失。这个问题纠结了我两个下午加一晚上的时间,快让我脑子炸掉了。
有木有遇到相似情况的兄弟,或者还发现有其他问题的,在这里 说一下,以防别人再因此陷入纠结。

我的eeprom是提供给用户的,允许用户通过串口连续写入16k字节的。
我有遇到写入出错的情况,但是增加延时就解决了。你试试增加几个延时指令,应该就解决了。追问

就是,我也纳闷儿,你说,我把一个25个数据的数组拆成两个,而且仍然是连续的两个for循环,写完前半部分接着写后半部分,中间没有延时,这两者有什么区别,但是一起读写不管用,分开了就管用,真是奇怪。

追答

uchar IapReadByte(uint addr)
{
uchar dat;
IAP_CONTR=ENABLE_IAP;
IAP_CMD=CMD_READ;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_TRIG=0x5a;
IAP_TRIG=0xa5;
_nop_(); //这儿加个延时吗?
dat=IAP_DATA;
IapIdle();
return dat;
}
void IapProg(uint addr,uchar dat)
{

IAP_CONTR=ENABLE_IAP;
IAP_CMD=CMD_PROG;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_DATA=dat;
IAP_TRIG=0x5a;
IAP_TRIG=0xa5;
_nop_();//这儿加个延时吗?
IapIdle();
}

追问

谢谢了,虽然我没有找到原因,但是你们几位大哥的回答都很耐心,也很热心,在此感谢各位,百度只允许采纳一个人的回答,我就只好采纳你的啦,因为你给了一段程序,并且标出了可能出现问题的地方,再次感谢了,希望后人能注意到这些问题吧!

温馨提示:内容为网友见解,仅供参考
第1个回答  2013-08-11
stc12c5a60s2单片机EEPROM 不存在问题,因为用汇编语言编程,可以连续读 或者 连续写
测试过 连续 写 0 ~ 255 循环写 所有存在的 全部扇区,再连续读取没有错误。
擦除是以扇区为单位 512 字节擦除的。
所谓缺陷应该说是 用 C 语言编程问题。没有按照STC单片机EEPROM的 读写要求。追问

难道是C语言有缺陷?我的程序是从技术手册里摘出来的,那个应该是按照要求写的啊。你说的擦除一个扇区我知道,我定义的那个数组就是把数据放在里面暂存的,读取完之后再擦除,然后和另外一个数组一起再写进去的

追答

C语言没有有缺陷,你可以直接用数据手册的程序试试,
数据手册 的例程 读写 一个扇区(512字节) 都没有问题,
应该你摘录有问题,或者你的 使用 区间有问题,
注意 擦除 是以扇区(512字节)为单位一次擦除的,
在同一区间 覆盖写入 数据是 会出错的,就是读出的数据 不等于 写入的数据。
要合理 使用 EEPROM 空间 需要有一些技巧。

追问

擦除的机制我懂得,程序没抄错,我看过好几次了,把那个长数组拆开管用,合在一起就不行,我也纳闷,数据没有覆盖,地址没有写错,也不可能覆盖,手册里说了,不是1就不能写入,也就是说必须擦除之后才能写入。估计是上面那哥们儿说的延时问题吧,一个数组拆开之后唯一的区别就是多执行了几条非读写的指令,可能这几个指令对eeprom来说相当于延时了。

追答

其实这个和延时没有什么关系,只要 IAP 等待时间设置正确 就没有问题。
还有一个 数据手册例程 没有用到 中断程序,所以在 IAP 读写时没有对中断方面的出来
就是 ISP/IAP 触发寄存器 写入两个字节 触发指令 中间不能 断开,否则触发会不成功。
如 写入 第一个 字节时 来一个中断触发程序 给打断,就会不成功。
一般处理就是 在 写入两个字节 触发指令 前 关闭总中断,
写入两个字节 触发指令 后 马上打开总中断。
如汇编是这样的
CLR EA ; 关总中断
MOV ISP_TRIG, #5AH ; 起动 ISP/IAP 触发寄存器
MOV ISP_TRIG, #0A5H
SETB EA ; 开总中断
C 语言如果用到中断也是一样需要这样处理一下的。

第2个回答  2013-08-11
应该没有问题,至少我是没有遇到过,你看看是不是程序有些问题。我用的是汇编,用数据手册中的例子改编的。追问

恩,我的也是从技术手册中摘出来的,只摘录了对eeprom操作的那部分并写成子函数,然后在别的函数中调用

相似回答