找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1701|回复: 29
收起左侧

STC15F2K60S2单片机内部EEPROM保存数据成功率低

  [复制链接]
ID:965189 发表于 2023-1-27 17:31 | 显示全部楼层 |阅读模式
STC15F2K60S2内部EEPROM保存数据成功率低。我只保存2个16位的数据。有时能保,有时不保。
回复

使用道具 举报

ID:213173 发表于 2023-1-27 20:59 | 显示全部楼层
不知道你的应用场景,无法做出判断。如果是用于掉电保存,是需要有一定的编程技巧和硬件支持。
回复

使用道具 举报

ID:57657 发表于 2023-1-27 21:49 | 显示全部楼层
保存有问题可能是供电不足、晶振频率、寄存器配置有问题,具体提供程序源码。
回复

使用道具 举报

ID:965189 发表于 2023-1-27 22:39 | 显示全部楼层
成功率最低的部分
         case 3:disp_cn_1_16x16(piad[11],4,48);            //
                   if(num==12)                                                        //确认键
                        {
                          if((shui_h!=shu)&&(shu!=0))
                          {
                               shui_h=shu;
                               delay_ms(2);
                                IapErase(0x0200);                         //扇区擦除
                                IapProgram(0x0200,shui_h>>8);  //保存高水位数据高8位
                                IapProgram(0x0200+1,shui_h);    //保存高水位数据低8位
                          }
                          flas++;
                          shu=0;                                 //输入板清0
                        }
                        if(shui_h>99)
                        {
                          disp_cn_2_8x16(pia1[h1],4,40); //h百位
                        }
                        else
                        {
                          disp_cn_2_8x16(pi0[0],4,40); //
                        }
                        if(shui_h>9)
                        {
                          disp_cn_2_8x16(pia1[h2],4,48); //h十位
                        }
                        else
                        {
                          disp_cn_2_8x16(pi0[0],4,48); //
                        }
                          disp_cn_2_8x16(pia1[h3],4,56);
                        if(num==15)flas--;
                        break;
回复

使用道具 举报

ID:965189 发表于 2023-1-27 22:41 | 显示全部楼层
按确认键(num==12),把设定的数据保存。
回复

使用道具 举报

ID:965189 发表于 2023-1-27 22:48 | 显示全部楼层
这些都是STC的例程提供的
/*----------------------------
    关闭IAP
----------------------------*/
void IapIdle()
{
    IAP_CONTR = 0;                  //关闭IAP功能
    IAP_CMD = 0;                    //清除命令寄存器
    IAP_TRIG = 0;                   //清除触发寄存器
    IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
    IAP_ADDRL = 0;
        EA=1;
}

/*----------------------------
从ISP/IAP/EEPROM区域读取一字节
----------------------------*/
char IapRead(int addr)          //读数据
{
    BYTE dat;                       //数据缓冲区

    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_READ;             //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr >> 8;          //设置IAP高地址
    EA=0;
        IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
   
        _nop_();                        //等待ISP/IAP/EEPROM操作完成
    dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
    IapIdle();                      //关闭IAP功能

    return dat;                     //返回
}

/*----------------------------
写一字节数据到ISP/IAP/EEPROM区域
----------------------------*/
void IapProgram(int addr, char dat)        //写数据
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_PROGRAM;          //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr >> 8;          //设置IAP高地址
    EA=0;
        IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
    IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}

/*----------------------------
扇区擦除
----------------------------*/
void IapErase(int addr)                //扇区擦除
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_ERASE;            //设置IAP命令
    IAP_ADDRL = addr;               //设置IAP低地址
    IAP_ADDRH = addr >> 8;          //设置IAP高地址
    EA=0;
        IAP_TRIG = 0x5a;                //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                //写触发命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}
回复

使用道具 举报

ID:965189 发表于 2023-1-27 22:55 | 显示全部楼层
wulin 发表于 2023-1-27 20:59
不知道你的应用场景,无法做出判断。如果是用于掉电保存,是需要有一定的编程技巧和硬件支持。

不是掉电,按确认键保存的。之前用过8G的,掉电保存都正常成功。
回复

使用道具 举报

ID:624769 发表于 2023-1-28 00:00 来自手机 | 显示全部楼层
检查 iap_contr 的设置,是否和你晶振一致,
回复

使用道具 举报

ID:213173 发表于 2023-1-28 07:21 | 显示全部楼层
君工创 发表于 2023-1-27 22:55
不是掉电,按确认键保存的。之前用过8G的,掉电保存都正常成功。

CPU的等待时间ENABLE_IAP设置是否得当?芯片型号确认是STC15xxxx,不是IAP15xxxx?后者要另行指定保存地址。
回复

使用道具 举报

ID:491577 发表于 2023-1-28 14:34 | 显示全部楼层
最可能是扇区擦除时间没有设置正确,造成擦除不完全。要根据单片机使用频率选择。STC例程工作频率为11.0592MHz,选择#define ENABLE_IAP  0x82是有问题的,应该选0x83更好。
//#define ENABLE_IAP 0x80           //if SYSCLK<30MHz
//#define ENABLE_IAP 0x81           //if SYSCLK<24MHz
#define ENABLE_IAP  0x82            //if SYSCLK<20MHz
//#define ENABLE_IAP 0x83           //if SYSCLK<12MHz
//#define ENABLE_IAP 0x84           //if SYSCLK<6MHz
//#define ENABLE_IAP 0x85           //if SYSCLK<3MHz
//#define ENABLE_IAP 0x86           //if SYSCLK<2MHz
//#define ENABLE_IAP 0x87           //if SYSCLK<1MHz
回复

使用道具 举报

ID:434018 发表于 2023-1-28 17:50 | 显示全部楼层
增加 _nop_(); 数量试试
Example
for (int i=0;i<50;i++)  _nop_();
回复

使用道具 举报

ID:1034262 发表于 2023-1-28 17:58 | 显示全部楼层
楼主很可能是你设置的读写速度和MCU的频率对不上导致的。
回复

使用道具 举报

ID:965189 发表于 2023-1-28 22:10 | 显示全部楼层
多谢上面几位的建议,我的CPU主频是24MHz.
回复

使用道具 举报

ID:41656 发表于 2023-1-29 10:39 | 显示全部楼层
你程序问题  STC用了很多了没有发现这个问题注意设置的时间控制寄存器设置是否正确
回复

使用道具 举报

ID:491577 发表于 2023-1-29 21:45 | 显示全部楼层
CPU主频是24MHz,比例程快了1倍,引用例程时有些地方需要多加一个_nop_(); 比如:
_nop_();                        //等待ISP/IAP/EEPROM操作完成
要多加一个_nop_();
另外:
#define ENABLE_IAP 0x81           //if SYSCLK<24MHz

回复

使用道具 举报

ID:965189 发表于 2023-1-29 22:14 | 显示全部楼层
之前用0x80;对应30MHz,现在用#define ENABLE_IAP  0x81,对应24MHz,两个都用过,没有改变。
回复

使用道具 举报

ID:965189 发表于 2023-1-29 22:17 | 显示全部楼层
唯有这个增加_nop_();未试过。
回复

使用道具 举报

ID:401564 发表于 2023-1-30 09:20 | 显示全部楼层
不存在成功率这一说的
代码正确了就一定行
代码正确了,保存不了,单片机本身的问题概率小到几乎为0
检查一下代码
回复

使用道具 举报

ID:213173 发表于 2023-1-30 09:56 | 显示全部楼层
君工创 发表于 2023-1-28 22:10
多谢上面几位的建议,我的CPU主频是24MHz.

有可能是楼主开了中断,在读写EEPROM时发生中断,破坏了正常读写EEPROM。从你提供的代码看并不是STC的原例程,被你插入了EA=1;/EA=0;。正常处理中断的写法是:
        case 3:disp_cn_1_16x16(piad[11],4,48);//
                if(num==12)//确认键
                {
                        if((shui_h!=shu)&&(shu!=0))
                        {
                                shui_h=shu;
                                delay_ms(2);
                                EA=0;
                                IapErase(0x0200);                         //扇区擦除
                                IapProgram(0x0200,shui_h>>8);  //保存高水位数据高8位
                                IapProgram(0x0200+1,shui_h);    //保存高水位数据低8位
                                EA=1;
                        }
                }
回复

使用道具 举报

ID:491577 发表于 2023-1-30 12:46 | 显示全部楼层
还有可能是电源滤波问题,24M需要103电容,12M需要104电容,楼主可以试试12M或6M主频时是否正常。如果降低主频正常,电源加一个103电容和1个22uf电容。
回复

使用道具 举报

ID:965189 发表于 2023-1-30 13:17 | 显示全部楼层

我试过这个方法不行才改现在这的。
回复

使用道具 举报

ID:965189 发表于 2023-1-30 13:19 | 显示全部楼层

CPU傍边有并104电容。
回复

使用道具 举报

ID:491577 发表于 2023-1-30 15:09 | 显示全部楼层
24M主频需要103电容,104不行。STC手册有要求好好看一下。12M主频以下要104电容。
回复

使用道具 举报

ID:1044091 发表于 2023-1-30 15:22 来自手机 | 显示全部楼层
还有一个方法,问下STC的技术支持,就是产品手册上那个电话。我还是单片机初哥的时候就问过一次,技术小妹很专业,几句话就把问题解决了。
回复

使用道具 举报

ID:382454 发表于 2023-1-30 15:29 | 显示全部楼层
不可能的,要这样说的话,芯片司也要倒闭了。
回复

使用道具 举报

ID:491577 发表于 2023-1-30 16:06 | 显示全部楼层
STC手册的建议,24M主频需要103电容,12M主频以下要104电容。大部分情况下用104都没事,但是有部分会出问题。最好按手册来做,要是经常改变频率,最好103,104电容都加上,安全一些。
无标题.jpg
回复

使用道具 举报

ID:213173 发表于 2023-1-30 17:34 | 显示全部楼层
君工创 发表于 2023-1-30 13:17
我试过这个方法不行才改现在这的。

STC的例程没有问题,做各种应用测试也没有出现过你上述现象。上万件的产品出去没有发生过EEPROM出这种问题。多数是你软件或硬件有问题。
回复

使用道具 举报

ID:965189 发表于 2023-1-30 21:33 | 显示全部楼层
hhh402 发表于 2023-1-30 16:06
STC手册的建议,24M主频需要103电容,12M主频以下要104电容。大部分情况下用104都没事,但是有部分会出问题 ...

谢谢你的提醒,一直没有留意这个问题,而且我习惯用104,看来这个问题也要重视。回到广州再试下。
回复

使用道具 举报

ID:965189 发表于 2023-1-31 09:25 | 显示全部楼层
wulin 发表于 2023-1-30 17:34
STC的例程没有问题,做各种应用测试也没有出现过你上述现象。上万件的产品出去没有发生过EEPROM出这种问 ...

我也认为是我的问题,只是暂时没找到原因。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表