EEPROM的程序错在哪里?

shenwen11 2008-10-04 02:50:56
#include <AT89X51.H>
#include <intrins.h>

//***********************<define.h>****************************************
#define uchar unsigned char
#define uint unsigned int
#define EEPROMSTARTADDR 0x2000 //STC89C52RD+为0x2000

//STC单片机特殊功能寄存器
sfr ISP_DATA = 0xE2;
sfr ISP_ADDRH = 0xE3;
sfr ISP_ADDRL = 0xE4;
sfr ISP_CMD = 0xE5;
sfr ISP_TRIG = 0xE6;
sfr ISP_CONTR = 0xE7;

#define ISP_IAP_BYTE_READ 1 //读字节
#define ISP_IAP_BYTE_PROGRAM 2 //写字节编程
#define ISP_IAP_SECTOR_ERASE 3 //扇区擦去
#define WAIT_TIME 1 //设置等待时间40M以下 0 ,20M以下1,10M以下2,5M以下3
#define _nop() _nop_() /*定义空指令*/


void delay1S(void) //延时1 秒
{
uchar h,i,j,k;
for(h=5;h>0;h--)
for(i=4;i>0;i--)
for(j=116;j>0;j--)
for(k=214;k>0;k--);
}

//******************************************************************************
//函数名称:FlashEraseSingleSector
//函数的功能:擦除一个扇区
//输入变量:addr 扇区开始地址
//输出变量:没有返回变量
void FlashEraseSingleSector(uint addr)
{
uint tempaddr=addr;
ISP_ADDRL=0;
ISP_ADDRH=(unsigned char)(tempaddr>>8);
ISP_CONTR=WAIT_TIME;
ISP_CONTR=0x80; //允许编程改变FLASH 区
ISP_CMD=ISP_IAP_SECTOR_ERASE; //擦除
ISP_TRIG=0x46; //触发
ISP_TRIG=0xb9; //触发启动
_nop_();
ISP_CONTR &= 0x7f;
// 高位为0,禁止ISP/IAP编程改变FLash区,同时保持WAIT_TIME不变
}

//******************************************************************************
//函数名称:ReadOneDataFromFlash
//函数的功能: 读取一个扇区数据
//输入变量:rdaddr 扇区开始地址
//输出变量:没有返回变量
uchar ReadOneDataFromFlash(uint rdaddr)
{
uchar readda;
uint temlongaddr=rdaddr;
ISP_ADDRL=(uchar) temlongaddr;
temlongaddr=rdaddr;
ISP_ADDRH=(uchar) (temlongaddr>>0);

ISP_CONTR=WAIT_TIME;
ISP_CONTR=0x80;
ISP_CMD=ISP_IAP_BYTE_READ; //读取数据
ISP_TRIG=0x46;
ISP_TRIG=0xb9;
_nop();
ISP_CONTR &= 0x7f;
readda=ISP_DATA;

return readda;
}

//******************************************************************************
//函数名称:WriteOneDataToFlash
//函数的功能:写入 一个数据
//输入变量:wdaddr 写入数据开始地址;wrdata写入的数据
//输出变量:没有返回变量
void WriteOneDataToFlash(uint wdaddr, uchar wrdata)
{

uint tempaddr,tempdata;
tempaddr=wdaddr;

ISP_DATA=wrdata;
ISP_ADDRL=(uchar) tempaddr;
tempaddr=wdaddr;
ISP_ADDRH=(uchar) (tempaddr>>8);
ISP_CONTR=WAIT_TIME;
ISP_CONTR=0x80;
ISP_CMD=ISP_IAP_BYTE_PROGRAM;
ISP_TRIG=0x46;
ISP_TRIG=0xb9;
_nop();
ISP_CONTR&=0x7f;
}

//*******************************************************************************
void main()
{

uchar flag;

flag=ReadOneDataFromFlash(0x2000);
while(1)
{
if(P3==0xf7) //独立键盘按下
flag=0xf0;
WriteOneDataToFlash(0X2000,flag);//写EEPROM
P0=ReadOneDataFromFlash(0x2000);
delay1S();
}
}
__________________________________________________
P0接的是8个发光二极管,上电flag=ReadOneDataFromFlash(0x2050)=0xff;没按下按键,P0显示0XFF;
按下按键后,flag=0xf0;2000中的数值保存为0XF0;P0=0XF0;(上面都可以实现,问题在下面)
断电复位后,经flag=ReadOneDataFromFlash(0x2000)后,flag=@2000=0xf0;P0=0XF0才对,但是为什么我断电复位后,P0还是等于0XFF??肯请高人帮回答一下。谢谢
...全文
307 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
丰满 2011-07-19
  • 打赏
  • 举报
回复
首先是eeprom是不需要擦处得,地址的读写也是自动加1的,只要保证是读写的地址正确和时钟时序对就可以了,我有dsp2812模拟读写eeprom的256芯片的程序
maoy001 2011-07-19
  • 打赏
  • 举报
回复
学习了
qinshop 2008-12-05
  • 打赏
  • 举报
回复
wo ye yu dao zhe ge wen ti!
shenwen11 2008-10-10
  • 打赏
  • 举报
回复
5555555555555555..
1程序断电不能保存。。。
2,不管地址是多少(在2000-2FFF内),都能显示出来,比如我写一句write(2001,0xf0);//在2001中写入0Xf0
read(2003);显示出的也是0xf0;
肯定还有地方不对,,有高手发现了吗?
shenwen11 2008-10-09
  • 打赏
  • 举报
回复
哈 哈,已经可以了。原因在ISP_CONTR=0X18;

这里的一些参数不能直接赋值,应该改成ISP_CONTR&=0X18;
同理后面的ISP_CONTR=0X01; 应该改成ISP_CONTR|=0X01;




shenwen11 2008-10-09
  • 打赏
  • 举报
回复
STC上面的代码是江汇编的,我只能看得懂C的。
下了几个程序,好像都不行。
上面的程序是我仿着写的,但是连写都写不进去,郁闷了啊。
zyzhang365 2008-10-08
  • 打赏
  • 举报
回复
先保证地址合法、擦写时边界对齐。

没有用过这个芯片,自己看看datasheet,application notes. 也可以到芯片厂家网站上下载示例代码参考一下。
shenwen11 2008-10-08
  • 打赏
  • 举报
回复
#include"reg52.h"
#define uchar unsigned char
#define uint unsigned int
sfr ISP_DATE=0xe2;
sfr ISP_ADDRH =0xe3;
sfr ISP_ADDRL =0xe4;
sfr ISP_CMD =0xe5;
sfr ISP_TRIG=0xe6;
sfr ISP_CONTR=0xe7;
//延时
void delay()
{
uchar i;
for(i=0;i<100;i++)
{;}
}
//开启
void start()
{
EA=0;
ISP_CONTR=0X18;
ISP_CONTR=0X01;
ISP_CONTR=0x80;
ISP_TRIG=0x46;
ISP_TRIG=0xb9;
delay();
}
//停止
void stop()
{
ISP_CONTR=0x7f;
ISP_TRIG=0x00;
EA=1;
}
//擦除
void er(uint m)
{
ISP_CMD&=0X98;
ISP_ADDRH=(uchar)((m&0xfe00)>>8);
ISP_ADDRL=0x00;
start();
ISP_CMD|=0x03;//擦除
stop();
}
//写
void write(uint add,uchar d)
{
ISP_CMD&=0X98;
ISP_CMD|=0x02;//编程
ISP_ADDRH=(uchar)(add>>8);
ISP_ADDRL=(uchar)add;
ISP_DATE=d;
start();
stop();
}
//读
uchar read(uint add)
{
uchar temp;

ISP_CMD&=0X98;
ISP_CMD|=0x01;//读
ISP_ADDRH=(uchar)(add>>8);
ISP_ADDRL=(uchar)(add);
temp=ISP_DATE;
start();
stop();
return(temp);
}
//检查
uchar cheak(uint add,uchar temp)
{
ISP_ADDRH=(uchar)(add>>8);
ISP_ADDRL=(uchar)(add);
ISP_CMD&=0X98;
ISP_CMD=0x02;//写
start();
stop();
start();
ISP_DATE=0x00;/* 清数据传递寄存器*/
ISP_CMD&=0x98;/* 清低3 位*/
ISP_CMD|=0X01;/* 读命令1*/
stop();
if(temp==ISP_DATE)
return 0;
else
return 1;
}
//主函数
main()
{
uchar flag;
er(2000);
delay();
write(2001,0xf0);//在2001中写入0Xf0
delay();
flag=read(2001);//读出2001中的数

delay();
P0=flag;//通过P0口显示出来P0=0XF0;
while(1);
}
_____________________________
上面的程序,程序都写不进EEPROM,我用的是STC89C52的芯片。
麻烦楼上的再帮我看看。谢谢先了。。。
学单片机没多久,
zyzhang365 2008-10-05
  • 打赏
  • 举报
回复
1没有加扇区擦除,
2应该怎么改?----- 写之前回读, 如果待写的内容与原来的内容不一致时再擦写; 否则直接返回. 思路是这样的,具体看实现了.
shenwen11 2008-10-05
  • 打赏
  • 举报
回复
1. 在写之前有扇区擦除操作吗?
2. while(1)里面每次写同一个地方,很快就写坏了.
_______________________________________________

1没有加扇区擦除,
2应该怎么改?
zyzhang365 2008-10-04
  • 打赏
  • 举报
回复
另外, 写后需要回读验证操作是否成功.
zyzhang365 2008-10-04
  • 打赏
  • 举报
回复
1. 在写之前有扇区擦除操作吗?
2. while(1)里面每次写同一个地方,很快就写坏了.

27,372

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧