wqsjob 发表于 2020-9-4 21:25:13

STC的EEPROM掉电会丢数据,一部分芯片

如题,我去年用stc做了个小东西,用到了EEPROM,后来我选了个STC8G2K64S4打算替代,结果问题来了,设置完参数掉电就没了?命名设置完参数我还读出校验的,没设置进去,那是要返回设置失败的,但是设置的时候返回都成功。
我觉得是不是这个地方的EEPROM坏了,然后换了几个位置都一样。
换了个没上过电的样品测试,一样保存不下来。
后来单独写了个小程序,如果能保存,第二次以后上电,都会闪几下灯,测试了两个样品,无论多少次,灯都不闪,然后把第二个样品换了个芯片,居然,灯闪了,真是郁闷。

#include "stc8g.h"
#include "intrins.h"
//#include <eepromx.h>
//#include "task_mange.h"
sbit                run_led        =   P3^6;
        unsigned char code test1[]={0x11,0x22,0x33,0x44};
        unsigned char test2;       
#define WT_30M          0x80
//#define WT_24M          0x81
//#define WT_20M          0x82
//#define WT_12M          0x83
//#define WT_6M         0x84
//#define WT_3M         0x85
//#define WT_2M         0x86
//#define WT_1M         0x87
#define IAP_OFFSET           0X8000
#define test_addr           0X800

#define   RUN_LED_ON()            run_led=0
#define   RUN_LED_OFF()            run_led=1

void Delay100ms()                //@33.1776MHz
{
        unsigned char i, j, k;

        _nop_();
        i = 17;
        j = 213;
        k = 185;
        do
        {
                do
                {
                        while (--k);
                } while (--j);
        } while (--i);
}



void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                              //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

char IapRead(int addr)
{
    char dat;

    IAP_CONTR = WT_30M;                         //使能IAP
        IAP_TPS = 33;
    IAP_CMD = 1;                              //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                           //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

void IapProgram(int addr, char dat)
{
    IAP_CONTR = WT_30M;                         //使能IAP
        IAP_TPS = 33;
    IAP_CMD = 2;                              //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                           //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

void IapErase(int addr)
{
    IAP_CONTR = WT_30M;                         //使能IAP
        IAP_TPS = 33;
    IAP_CMD = 3;                              //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}
//char eeprom_read(unsigned int addr)
//{
//        addr+=IAP_OFFSET;
//        return *(char code *)(addr);
//}


//读取多个EEPROM地址 ,返回值为CRC 校验码
void eeprom_read_buf(int addr,char *buf,char bflong)
{
//        char xj;
//        int crc=0;
//        int crc2=0;
        char i=0;
        for(i=0;i<bflong;i++)
        {
                //IapProgram(addr+i, buf);
                buf=IapRead(addr+i);   //eeprom_read(addr+i);       
        }
//        crc=eeprom_read(addr+i);       
//        //crc=xj;
//        crc=crc<<8;
//        i++       ;
       
//        crc2=eeprom_read(addr+i);               //注意
//        crc=crc+(crc2&0x00ff);
//        return (crc);
}

//写多个EEPROM地址
void IapProgram_buf(int addr,char *buf,char bflong)
{
        char i=0;
//        int crcx;
        char mid;
//        crc
        IapErase(addr);               //        先擦除EEPROM对应的块
//        crcx = crc16_modbus(buf, bflong) ;
        for(i=0;i<bflong;i++)
        {
                mid=buf;
                IapProgram(addr+i, buf);       
        }
//        IapProgram(addr+i,         (crcx>>8));                        //写入CRC
//       
//        i++;
//        IapProgram(addr+i,         crcx);
}
//--------------------------------------------

void test_eeprom()
{

        IapErase(test_addr);
        IapProgram_buf(test_addr,test1,4);       
        //IapProgram_buf(test_addr,test1,4);
        eeprom_read_buf(test_addr,test2,4);       
        _nop_();

}
void testread()
{
        eeprom_read_buf(test_addr,test2,4);       
        _nop_();
}


void main(void)
{
       unsigned char xi1;
               P3M0|=0X60;       
        P3M1&=0X9F;
       testread();
       for(xi1=0;xi1<20;xi1++)
       {

               
               if(test2==0x11)
               {
                   _nop_();
                   RUN_LED_ON() ;
                  Delay100ms();
                       Delay100ms();
                          Delay100ms();
                           Delay100ms();
                           RUN_LED_OFF() ;
                          Delay100ms();
                       Delay100ms();
                          Delay100ms();
                           Delay100ms();
               }
               
          }
       
       test_eeprom();
        while(1)
        {
          _nop_();
        }
}


wqsjob 发表于 2020-9-4 21:27:38

这个是程序存储器里分出来的。我只是担心,是否程序存储器会丢失?

huangyiting1990 发表于 2020-9-4 21:44:49

wqsjob 发表于 2020-9-4 21:27
这个是程序存储器里分出来的。我只是担心,是否程序存储器会丢失?

   程序也会丢的,亲身经历 {:lol:}
   不过当时是我逻辑没写好 , 在掉电后去操作了 EEPROM , 导致有概率丢程序。后来改掉那个BUG后就好了

wye11083 发表于 2020-9-4 22:53:59

huangyiting1990 发表于 2020-9-4 21:44
程序也会丢的,亲身经历
   不过当时是我逻辑没写好 , 在掉电后去操作了 EEPROM , 导致有概 ...

所以还是要开低电压复位啊。不过stc待机功耗还是要大不少,没有stm32l0省电。

hefq 发表于 2020-9-4 23:54:25

wye11083 发表于 2020-9-4 22:53
所以还是要开低电压复位啊。不过stc待机功耗还是要大不少,没有stm32l0省电。 ...

低电压复位解决不了问题吧,要做掉电检测+大电容才能解决问题

我是一个大白菜 发表于 2020-9-4 23:57:48

操作flash之前,我都是先判断有没有低压标志,电压正常再操作,基本就没有出问题了

hefq 发表于 2020-9-4 23:57:50

要不就写两份,每份都加校验码一起写进去
两份不要同时写,隔个几秒,
这样能保证掉电时只会写坏一份,因为有校验码,所以肯定知道哪一份是好的

lb0857 发表于 2020-9-5 07:57:49

重要场合关键参数还是外置eep芯片安全 可靠内部flash从当年的PIC到现在的MCU标配   都一样性格异变不可捉摸{:lol:}

wqsjob 发表于 2020-9-5 09:05:28

hefq 发表于 2020-9-4 23:57
要不就写两份,每份都加校验码一起写进去
两份不要同时写,隔个几秒,
这样能保证掉电时只会写坏一份,因为 ...

我怀疑你只看了标题,但是我没证据{:lol:}
是整个都坏了。
只是存储配置数据,也许一辈子就写那么一次.原来我程序里读用的并不是IAP读,而是MOVC读,上边贴出来的有这段子程序,只是我现在测试的时候用了IAP的读.
还有,不牵涉到掉电的时候保存数据,不存在掉电的时候破坏EEPROM数据.


我思考了一夜,大概理出来一个思路,坏的原因应该如下:
以下子程序里,IAP_TPS = 33;这一行是后来加的,在老的芯片里根本没有这个配置,也就是在去年的芯片里,这个是在IAP_CONTR 里配置的.
void IapProgram(int addr, char dat)
{
    IAP_CONTR = WT_30M;                         //使能IAP
      IAP_TPS = 33;
    IAP_CMD = 2;                              //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                           //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

1.开始两个样片都是上电,烧老程序.然后测试发现没法设置,返回设置不成功.
2.然后我将其中一个配置成仿真模式,看看什么问题,结果发现写的时候死在那里了,然后我就纳闷,去年好好的程序,写EEPROM死了?
3. 查数据手册,发现新版的多了个以上这么个东西,然后把这句话加进去.果然解决了问题.设置也成功了.
4.忙其他事情几天,才回来弄这件小事,不过说实话,研发无小事啊.结果头大了,每次上电,都恢复到默认的参数了,配置的都保存不下来.
5. 我当时想,是不是老程序把eeprom的这个部分写坏了,我换个地址.然后换了地址也是一样现象,设置成功,但是停电了,数据就没了.这是最坑的地方,写进去,读出来比较,和写进去的一样.但是一停电就没了,这是把EEPROM直接升级成SRAM了啊?RAM不是比EEPROM贵吗?
6.开始我是想换个芯片,但想想两块都是这样,可能性太小了.并且老电工了,也懒的动手,把去年写的程序扒出来一点点查,查了一天,总算把程序又看懂了,我写这部分程序的时候可是才用了半天时间,检查都用了一天。可是程序没发现什么问题.
7.其中一块换了芯片,上测试程序,OK.上正常程序,OK.


也就是,老程序就写了EEPROM其中的某一个地方,我一次配置数据有4个区域,相当于测试那么长时间,写了几百次,把整块EEPROM都干死了?

还有就是,出了这个问题,老板看我的眼神都不对,和我说,这么低级的问题,你竟然搞了两次,前后弄了两三天?




hefq 发表于 2020-9-5 09:46:18

wqsjob 发表于 2020-9-5 09:05
我怀疑你只看了标题,但是我没证据
是整个都坏了。
只是存储配置数据,也许一辈子就写那么一次. ...

我是回的另一个人的贴子,你的这种情况就是坏了,没救了{:lol:}

gylg3344love 发表于 2020-9-27 11:07:16

这种问题碰到多了,特别是外部强干扰的时候更容易出问题。就是Flash的EEprom数据丢失,再不敢用STC内部的EEprom了,正常使用压根用不到写,甚至把写功能屏蔽掉了,使用过程中还是一样丢过一部分数据。今后不敢再用了,外部EEprom走起。。。

wqsjob 发表于 2020-9-27 13:02:47

gylg3344love 发表于 2020-9-27 11:07
这种问题碰到多了,特别是外部强干扰的时候更容易出问题。就是Flash的EEprom数据丢失,再不敢用STC内部的EE ...

是的,我这个产品就是安装的时候,设置一下服务器的IP地址之类的参数,之后就不会再写了。

小李非刀 发表于 2020-9-27 16:19:19

wye11083 发表于 2020-9-4 22:53
所以还是要开低电压复位啊。不过stc待机功耗还是要大不少,没有stm32l0省电。 ...

STC8G系列的,Power Down模式0.4uA。

小李非刀 发表于 2020-9-27 16:28:38

擦除、写入EEPROM时,多设置一些条件吧,比如我常用一个4字节的PASSWORD。STC的EEPROM是从FLASH中分出来的,按理不应该容易掉的,反正从2003年用STC到现在,我基本没碰到掉EEPROM数据的。如果EEPROM容易掉,同理程序也应该容易掉,但是实际上程序却又很少会掉,所以基本跟操作有关的,或者电源或IO有高压尖峰(超过6V就算)冲击IC。我一般开发产品时,都会做几十上百个样机做220V上电、断电实现,开4秒关4秒,24小时超过1万次的开关电,看是否有任何异样。

ltby00 发表于 2020-9-27 16:40:09

我有个小产品正在上,看来的得注意下这问题了! 但还是有点堵的赶脚

wye11083 发表于 2020-9-27 22:00:53

小李非刀 发表于 2020-9-27 16:19
STC8G系列的,Power Down模式0.4uA。

stm32l0是4ua。。

电子喵星人 发表于 2020-9-27 22:03:50

碰到过 eeprom读出来变成255了。

ax6808 发表于 2022-7-3 15:36:28

EEPROM 操作所需时间是硬件自动控制的,用户只需要正确设置 IAP_TPS 寄存器即可。
IAP_TPS=系统工作频率/1000000(小数部分四舍五入进行取整)
例如: 系统工作频率为 12MHz,则 IAP_TPS 设置为 12;
你的系统工作频率为30MHz???则 IAP_TPS 设置为30,而你套用了33 ??? 导致操作时间不能保证哦

akey3000 发表于 2022-7-3 15:49:48

gylg3344love 发表于 2020-9-27 11:07
这种问题碰到多了,特别是外部强干扰的时候更容易出问题。就是Flash的EEprom数据丢失,再不敢用STC内部的EE ...
(引用自11楼)

为何外部就一定稳定

akey3000 发表于 2022-7-3 15:51:01

lb0857 发表于 2020-9-5 07:57
重要场合关键参数还是外置eep芯片安全 可靠内部flash从当年的PIC到现在的MCU标配   都一样性格异变 ...
(引用自8楼)

为何外部的稳定

51单片机爱好者 发表于 2022-7-8 08:46:52

akey3000 发表于 2022-7-3 15:51
为何外部的稳定
(引用自21楼)

内部时钟一般是RC振荡电路,会收到温漂的影响,不过在他们的销售强推下,实测STC15系列的比早期的老型号确实是好了很多。要求高的话可以外部时钟,时钟精准
页: [1]
查看完整版本: STC的EEPROM掉电会丢数据,一部分芯片