打印

EEPROM的问题无法理解

[复制链接]
3867|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
playpic|  楼主 | 2010-10-21 22:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请教一下各位老手,我这个是什么原因啊?百思不得其解。代码如下:
//程序目的:1)按下KEY,单片机采集AN2的电压,存在0X10(HIGHT),0X11   (LOW),同时把0X10和0X11的内容复制一份到0X20,0X21   
// 2)LED起指示作用
#include <pic.h>
__CONFIG(0X0384);//4MHZ FOSC
#define UCHAR  unsigned char
#define UINT   unsigned int
#define LED  GPIO1
#define KEY  GPIO5
#define POWER GPIO4
UCHAR ADRESULT_H,ADRESULT_L;
void Delay_ms(UCHAR x)
{
UCHAR y,z;
for(y=x;y>0;y--)
for(z=200;z>0;z--);
}
void Sys_Init()
{
CMCON0=0X07;       //关闭比较器
ANSEL=0X54;        //FOSC/16  0100
TRISIO=0XED;       //1110 1101
OSCTUNE=0X00;
OSCCON=0X61;       //4MHZ INTRCOSC
OPTION=0X00;      
WPU=0X20;          //0010 0000 GP5 PULL UP
IOC=0X00;          //0000 0000 DISABLE ALL LEVEL INTERRUPT
INTCON=0X00;       //0000 0000 DISABLE ALL INTERRUPT
CCP1CON=0X00;
POWER=1;
GIE=0;
PIE1=0;
ADRESL=0;
ADRESH=0;

}
void main()
{
  UCHAR temp,count;
  Sys_Init();
  Delay_ms(220);
  if(KEY==0)
  {
   GPIO=0X3D;
   while(KEY==0);
   GPIO=0X3F;
  ADCON0=0X89;        //CH2 RIGHT ON
  Delay_ms(1);
  GODONE=1;
  while(GODONE==1);
  ADRESULT_L=ADRESL;
  ADRESULT_H=ADRESH;
  EEPROM_WRITE(0X10,ADRESULT_H);
  Delay_ms(0x02);
  temp=EEPROM_READ(0X10);
  EEPROM_WRITE(0X20,temp);  //奇怪的问题就在这里,当把读0X10和0X11的语句去掉,工作是正常的
                                   //当加上读0X10和0X11再写入到0X20和0X21的时候,4个单元的值都是0X00
                                   //很奇怪!
  EEPROM_WRITE(0X11,ADRESULT_L);
  temp=EEPROM_READ(0X11);
  EEPROM_WRITE(0X21,temp);
  GPIO=0X3D;
  Delay_ms(220);
  Delay_ms(220);
  GPIO=0X3F;
  while(1);
}
}
沙发
playpic|  楼主 | 2010-10-22 07:53 | 只看该作者
奇怪的问题就在这里,当把读0X10和0X11的语句去掉,工作是正常的
                                   当加上读0X10和0X11再写入到0X20和0X21的时候,4个单元的值都是0X00
                                   很奇怪!

使用特权

评论回复
板凳
谈的元| | 2010-10-22 07:55 | 只看该作者
会不会读写没有完成?

之间插延时

使用特权

评论回复
地板
playpic|  楼主 | 2010-10-22 09:30 | 只看该作者
这是标准的库函数,按道理的话函数里面应该是等待写完成以后才退出EEPROM_WRITE函数的

使用特权

评论回复
5
playpic|  楼主 | 2010-10-22 12:05 | 只看该作者
斑竹能不能帮我看一下,谢谢了。这个问题理论上应该是不存在的,但是还是出现了。想了好久想不明白,在EE—WRITE之间加200MS的延时也没有用

使用特权

评论回复
6
dodome521| | 2010-10-22 16:38 | 只看该作者
应该是时间的问题,写周期没有完成,又启动了读操作。不知你说的200MS是否正确,写周期应该5MS左右就完成了。

使用特权

评论回复
7
zdhlixiang2006| | 2010-10-24 10:02 | 只看该作者
我碰到过更**的事情,就是首地址00和01一直读不对,找不到原因,后来换了读写位置就好了,我换位fe和ff,一些就正常了哦,解释不了

使用特权

评论回复
8
yewuyi| | 2010-10-25 11:50 | 只看该作者
库函数的使用不是没有任何条件的,对库函数的使用应该弄明白库函数占用什么资源,需要什么资源。
EEPROM_WRITE()这个函数的具体实现不知道是什么,但写EEPROM是需要时间,一般5~10MS,这个时间如果没有在EEPROM_WRITE()库函数中保证,那则需要你代码的其它部分实现,如果这个时间已经在库函数中完成,那你则必须确定在这个写时间内没有发生中断,但显然在库函数中实现这个时间等待是不合理的,这样独霸CPU的行为时可耻的,连一个合格电子民工都不应该这么做。

我个人给出的建议:可以直接引用读函数,写函数还是根据自己的程序结构自己写的好,我以前在本版块发过自己写的读写EEPROM函数的示例,你可以翻翻老帖子。

使用特权

评论回复
9
yewuyi| | 2010-10-25 11:56 | 只看该作者
我碰到过更**的事情,就是首地址00和01一直读不对,找不到原因,后来换了读写位置就好了,我换位fe和ff,一些就正常了哦,解释不了
zdhlixiang2006 发表于 2010-10-24 10:02



你估计是用AVR出现的问题吧?在PIC上面从来没有出现过这个问题,除非是你自己的代码有问题,但这个问题倒是在AVR芯片上面曾经长期存在,主要是它上电复位有问题造成的误擦除动作,但即使在AVR上面也只是偶尔丢数,并不是100%出现。

使用特权

评论回复
10
andy2003hu| | 2010-10-25 12:27 | 只看该作者
库函数的使用不是没有任何条件的,对库函数的使用应该弄明白库函数占用什么资源,需要什么资源。
EEPROM_WRITE()这个函数的具体实现不知道是什么,但写EEPROM是需要时间,一般5~10MS,这个时间如果没有在EEPROM_WRIT ...
yewuyi 发表于 2010-10-25 11:50


请问能不能在MPLAB环境把EEPROM_WRITE跟EEPROM_READ的函数原型找出来?

使用特权

评论回复
11
andy2003hu| | 2010-10-25 12:28 | 只看该作者
9# yewuyi

使用特权

评论回复
12
yewuyi| | 2010-10-25 13:12 | 只看该作者
请问能不能在MPLAB环境把EEPROM_WRITE跟EEPROM_READ的函数原型找出来?
andy2003hu 发表于 2010-10-25 12:27


在C编译器提供的文件中查找。

使用特权

评论回复
13
XIEYUANBIN| | 2010-10-25 15:34 | 只看该作者
请问能不能在MPLAB环境把EEPROM_WRITE跟EEPROM_READ的函数原型找出来?
andy2003hu 发表于 2010-10-25 12:27

可以的,只需要编译以后看汇编即可。我看到的读写EEPROM函数都是死等的,而且在等待之前是关闭中断的。

使用特权

评论回复
14
skygrow| | 2010-10-25 15:39 | 只看该作者
本帖最后由 skygrow 于 2010-10-25 16:09 编辑

函数原形, 目录C:\Program Files\HI-TECH Software\PICC\9.80\include\eeprom_routin.h
"
#define        EEPROM_WRITE(addr, value) \
do{ \
        while(WR)continue;EEADRL=(addr);EEDATA=(value); \
        CARRY=0;if(GIE)CARRY=1;GIE=0; \
        WREN=1;EECON2=0x55;EECON2=0xAA;WR=1;WREN=0; \
        if(CARRY)GIE=1; \
}while(0)"

最后一个有没有写完需自己判断

使用特权

评论回复
15
zdhlixiang2006| | 2010-11-7 13:40 | 只看该作者
PIC18F442,不是AVR的机子

使用特权

评论回复
16
ji_dan| | 2010-11-9 16:24 | 只看该作者
路过~

使用特权

评论回复
17
Light_David| | 2010-11-13 02:26 | 只看该作者
14楼的正确,我是看过编译后的汇编的,

写EPROM是这样的,如果开了中断,它会在EECON2写时序前先关掉GIE,然后打开,(关断时执行EECON2写时序避免中断被破坏,共计是8条指令)。
然后就退出函数,如果此时立即再次调用EEPROM_WRITE,你会看到这句while(WR)continue;它会一直等待上次写完以后再进入。而此时并不会影响中断。
感觉这个原型写法基本和汇编写法一致了,没必要去自己写这个。
EEPROM_READ()就更简单了,根本没有等待的概念,一个机器周期完成的事。进去就出来了,也没有延迟。
总的来说这两个函数已经很完美了,随时调用。都应该没问题,而且已经最优化。

使用特权

评论回复
18
Light_David| | 2010-11-13 02:27 | 只看该作者
,(关断时执行EECON2写时序避免被中断破坏,共计是8条指令)。
:L

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

21

帖子

1

粉丝