stronghold 发表于 2005-6-29 14:29:53

究竟该怎样正确读写EEPROM?

./emotion/em078.gif

大家好!

   小弟在使用mega128时需要将一些程序运行中需要的一些初始设置值存放到EEPROM中,但是在调试中遇到如下问题:

调试环境:ICC6.31A+AVRstudio4.11

1)在AVRstudio下仿真,在程序里先把数据写入EEPROM,此时在仿真环境下EEPROM中观察到的数据变化是正确的;

2)然后把 程序里的数据写入EEPROM语句屏蔽,再用ICC编译后再用AVRstudio仿真,程序运行后,读出的EEPROM对应的数据全变为为0xFF。



为什么重新下载程序后,会读EEPROM内容不对??

我使用的是mega128手册中的EEPROM_write(x,x)和EEPROM_read(xx)程序。小弟在论坛里看了相关的一些帖子,还是有些地方弄得不太懂,.

1.ICCAVR编译后的.eep文件( INTEL HEX 格式文件包含了EEPROM 的初始化数据),这个文件到底该怎么用,能否详细的说明一下。

2.在AVRstudio中该如何设置图中画框的选项。

3.UP/DownloadDebugPlatformMemory这个选项应该在什么情况下使用?

请了解的朋友指教指教,不胜感谢!!!!!!!

http://cache.amobbs.com/bbs_upload782111/files_2/armok0154688.jpg

wxjia2004 发表于 2005-6-29 15:13:01

.eep文件直接在上面的窗口中写入eeprom即可。

好象程序要和EEPROM一起写入才行,如果只写一个另外的那个好像也被檫除了,变成了FF

biansf2001 发表于 2005-6-29 15:42:36

榕寺位eesave选了没?没选就嚓掉了

ilan2003 发表于 2005-6-29 16:52:17

每次仿真的时候会把eeprom檫掉的

stronghold 发表于 2005-6-29 18:02:49

还是不行呐,我现在都有点糊涂了,哪位朋友能不能肯定的给个操作流程,尽量详细点,谢谢了!

我现在的操作流程是:1.在程序里先把数据写入EEPROM,在AVRstudio中编译,然后选择UP/DownloadDebugPlatformMemory这个选项将写好数据后的.eep文件保存;2.然后把 程序里的数据写入EEPROM语句屏蔽,改为读EEPROM中的指定位,用ICC编译将生成的.eep文件换为前次保存的.eep文件;3.在到AVRstudio中同时将程序文件和.eep文件写入芯片,但是运行仿真查看时还都是0xFF,这是怎么回事,是我的操作有问题吗?请指教
-----此内容被stronghold于2005-06-29,20:47:42编辑过

dawei 发表于 2005-11-22 19:28:14

我也想知道如何操作,并请教.eep文件如何生存?请高手指点.

LOVEMCU 发表于 2005-11-23 09:02:19

LZ的问题偶也不知道怎么解决,在这里提供一个对EEPROM进行读、写操作的思路,仅供参考。如果EEPROM中需要存储的有用的数据不多的时候,可以采用如下的方法对EEPROM进行读、写,基本上可以避免出错。

向EEPROM中写数据时,每个数据都写在EEPROM的连续3个单元中,写完后再将刚才写入的内容读出,与之前写的数据进行比较,不一致则重写。

/*****************************************

         向EEPROM中写数据子程序

*****************************************/

void write_eeprom(void)       

{         

    uint i;

    uchar CheckCount=0;

    uchar CheckStatus1=0;

    uchar CheckStatus2=1;

    for(i=0;i<3;i++)       //将新的设置写入到EEPROM 的3个连续单元中

    EEPROM_WRITE(i,WrEeprom);

    while(CheckStatus1 == 0)

   {

       for(i=0;i<3;i++)        //将刚才写入的数据读出               

       EEPROM_READ(i,EepromData);

       for(i=0;i<3;i++)       

       {

          if(EepromData != WrEeprom)       

         //比较刚才写入的数据与设置值WrEeprom是否一致

          {

              CheckStatus2=0; //如果不一致,则改变标志位,并重新写入数据

              EEPROM_WRITE(i,WrEeprom);

          }

       }

       if(CheckStatus2 == 0)//如果检测到有数据不一致的情况,则要重新进行比较

       {

          CheckStatus1 = 0;

          CheckStatus2 = 1;

          CheckCount++;

       }

      else                //否则将标志位置1,跳出循环                       

      {

         CheckStatus1 = 1;

          CheckCount=0;

      }

      if(CheckCount == 100)                               

//如果连续写EEPROM 100次都有数据不一致的情况,则发消息给上位机,并跳出循环

   {

          CheckCount=0;

          CheckStatus1 = 1;

   }

}



读EEPROM的数据时,读EEPROM的连续3个单元,读完后将这3个单元的内容进行比较,有两个一致的数据则认为是正确的数据。

/*****************************************

         读EEPROM中数据子程序

*****************************************/

void read_eeprom(void)                                                                  

{

   uint i;

   for(i=0;i<3;i++)

   EEPROM_READ(i,EepromData);        //读EEPROM中的数据

   if(EepromData == EepromData)//如果第0个与第1个数据一致

    {

      if(EepromData == EepromData)//再比较第0个与第2个数据是否一致

      EepromStatus=1;                //如果3个数据完全一致,则置标志位为1        

      else if(EepromData != EepromData)//如果第2个数据与第0个不一致

      {                                            

           EepromData= EepromData;

            //则认为第2个数据有误,用第0个数据覆盖掉第2个数据

           EEPROM_WRITE(2,EepromData);   //将数据重新写入EEPROM                   EepromStatus=2;                        //并将标志位置为2

      }

   }

   else if(EepromData != EepromData)        //如果第0个与第1个数据不一致

    {

      if(EepromData == EepromData)//再判断第0个数据与第2个数据是否一致

       {

           EepromData= EepromData;               

            //如果一致,则认为第1个数据有误,用第0个数据覆盖掉第1个数据

           EEPROM_WRITE(1,EepromData);   //将数据重新写入EEPROM       

           EepromStatus=2;                        //同时将标志位置为2

       }

       else if(EepromData != EepromData)//如果第0个数据与第2个数据也不一致

      {

           if(EepromData == EepromData)       

            //再判断第1个数据与第2个数据是否一致

          {

             EepromData= EepromData;       

                //如果一致,则认为第0个数据有误,用第1个数据覆盖掉第0个数据

             EEPROM_WRITE(0,EepromData);   //将数据重新写入EEPROM       

             EepromStatus=2;                   //同时将标志位置为2

          }

          else if(EepromData != EepromData)

      //如果第1个数据与第2个数据也不一致,说明3个数据都不一致,则EEPROM数据出错

          EepromStatus=0;                              //将标志位置为0

      }

   }

   switch(EepromStatus)

{       

      case 0x00:                //3个数据都不一致

      ******;                 

      break;

      case 0x01:                //3个数据完全一致

      ******;                 

      break;

      case 0x02:                //有一个数据出错

      ******;                 

      break;

   }       

}
-----此内容被LOVEMCU于2005-11-23,09:03:23编辑过

igoal 发表于 2005-11-23 09:07:23

进入仿真模式后就自动把EEPROM给清除了啊!当然没有了。用JTAG坊真其实就是把程序烧到单片机了运行的,不信你把仿真器拔下来,程序肯定就运行了,所以进仿真模式和烧程序到单片机了效果是一样的,EEPROM已经被清除了。

biansf2001 发表于 2005-11-23 11:17:46

jtag会擦出eeprom,isp不会

while 发表于 2005-11-24 14:27:55

在防真的时候,JTAG ICE Options中Debug下Preserve EEPROM contenes when reprograming device 选项,有没有选呀,如果没选,那就会丢失的.

tearsnow 发表于 2006-4-4 18:21:15

向6楼问下?

如果有大量数据要在EEPROM里进行读写该怎么办啊?

xrb3115 发表于 2006-4-4 23:01:31

我觉得对于3中取2的问题,分成3个区域进行操作比“连续3个单元”更合理,例如以下的程序片段:



//定义内部 EEPROM 的地址分配

//MEGA16内部有512字节EEP,地址范围 0x0000 - 0x01FF

//                      输出映像为 0x0011 - 0x0080   (112BYTE)

//                      备份1      0x0081 - 0x00F0      

//                      备份2      0x00F1 - 0x0160

//3个区域互为备份



#defineEEpModuleId       0x0011             //modbus模块地址编号

#defineEEpWdtComp      0x0012             //看门狗门值

#defineEEpWdtAct         0x0013             //看门狗动作类型

#defineEEpIAPAct         0x0014             //升级标志 55H有效   

#defineEEpOffLineStat    0x0015             //离线标志

……



这样在定义EEP地址时,可以连续排列,而不需要注意以3为模的问题,以下是读写函数:



/* ***************************************************************

**函数名称:ApEepRead()

**函数功能:读出数据 字节方式

**入口参数:wAddr操作地址

**出口参数:经过3中取2的数据

**备    注: 若有需要,自动更新备份文件

*************************************************************** */

uint8 ApEepRead(uint16 wAddr)

{

    uint8 temp1,temp2,temp3;

       

    temp1 = eeprom_read_byte(wAddr);

    temp2 = eeprom_read_byte(wAddr + 0x70);

    temp3 = eeprom_read_byte(wAddr + 0xF0);

       

    if ((temp1 == temp2) && (temp2 == temp3))

    {

      return temp1;

    }

    else if ((temp1 == temp2) || (temp1 == temp3))

    {

      ApEepWrite(wAddr, temp1);

      return temp1;

    }

    else if (temp2 == temp3)

    {

      ApEepWrite(wAddr, temp2);

      return temp2;

    }

    else

    {

      ApEepWrite(wAddr, 0);      //如果3个都不同的处理

      return 0;       

    }

}



/* ***************************************************************

**函数名称:ApEepWrite()

**函数功能:写入数据 字节方式

**入口参数:wAddr待写入的地址wDate待写入的数据   

**出口参数:

**备    注: 自动写备份文件

*************************************************************** */

void ApEepWrite(uint16 wAddr, uint8 wDate)

{

    /* 先读出数据,如果一致就不需要再次写入 */

    ……



    /* 写3次数据 */

    eeprom_write_byte (wAddr, wDate);DelayNMs(10);

    eeprom_write_byte (wAddr + 0x70, wDate);DelayNMs(10);

    eeprom_write_byte (wAddr + 0xF0, wDate);DelayNMs(10);

}





以前在使用24Cxx时,总觉得3个数据连续挨着受破坏的概率要大于分散在3个不同的区域,测试的结果好象也映证了这一点。AVR的内部EEP没有经过这方面的测试



-----此内容被xrb3115于2006-04-04,23:08:17编辑过


-----此内容被xrb3115于2006-04-04,23:21:43编辑过

lovenashte 发表于 2006-11-10 13:45:27

在JTAG ICE Options中Debug下Preserve EEPROM contenes when reprograming device 选项,选上那么就不会丢失了.



我之前也试过.

3jamesbond 发表于 2007-7-21 11:31:58

容丝位要设定为烧写时不擦除 一般就没有问题了

ba_wang_mao 发表于 2007-7-21 13:32:39

你尝试过在接收到串行中断请求“写全部EEPROM”指令后,先给上位机发送应答帧后,立即

写380字节,写EEPROM不出错吗?注:定时中断每隔20ms触发。

liyaofeng2000 发表于 2007-7-21 14:40:07

/********************************************************************

;*子程序名称:        uint08 ReadEepromByte(uint16 addr)

;*程序功能:         读一字节数据从 EEPROM

;*输入参数:       

;*输出参数:       

;*调用函数:       

;*******************************************************************/

    uData08 ReadEepromByte_CLI(uData08 addr)

    {

      uData08 result;

      uData08 temp=SREG;



      while(EECR & (1<<1) );

      __disable_interrupt();

      result=ReadEepromByte(addr);



      SREG=temp;

      return result;

    }

piratest 发表于 2007-7-23 00:54:51

http://cache.amobbs.com/bbs_upload782111/files_7/armok01163038.JPG

我用的下载软件和你使用的不一样.这里一定要注意熔丝位EESAVE要进行编程,也就是EESAVE=0,另外不要在烧写时对EEPROM擦除,我的软件设置就是不要在program option里的EEPROM打勾

piratest 发表于 2007-7-23 02:31:56

新下载的MuCodeISP有些默认的熔丝位的设置要修改,记住修改后要点旁边的write键才能生效.

PS:MuCodeISP是并口下载软件

luojiyin 发表于 2010-6-19 21:56:28

mark

cqsgcqsg 发表于 2014-9-26 10:32:23

{:loveliness:}{:loveliness:}{:loveliness:}

zhans 发表于 2014-9-26 21:47:43

{:handshake:}。好学问~

codeman 发表于 2014-9-26 22:10:47

用ISP下载并设置好不会擦除EEPROM

一夕nandy 发表于 2014-9-26 22:53:27

不错 学习下
页: [1]
查看完整版本: 究竟该怎样正确读写EEPROM?