標題: STC15F2K60S2單片機內(nèi)部EEPROM保存數(shù)據(jù)成功率低 [打印本頁]

作者: 君工創(chuàng)    時間: 2023-1-27 17:31
標題: STC15F2K60S2單片機內(nèi)部EEPROM保存數(shù)據(jù)成功率低
STC15F2K60S2內(nèi)部EEPROM保存數(shù)據(jù)成功率低。我只保存2個16位的數(shù)據(jù)。有時能保,有時不保。

作者: wulin    時間: 2023-1-27 20:59
不知道你的應用場景,無法做出判斷。如果是用于掉電保存,是需要有一定的編程技巧和硬件支持。
作者: npn    時間: 2023-1-27 21:49
保存有問題可能是供電不足、晶振頻率、寄存器配置有問題,具體提供程序源碼。
作者: 君工創(chuàng)    時間: 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);                         //扇區(qū)擦除
                                IapProgram(0x0200,shui_h>>8);  //保存高水位數(shù)據(jù)高8位
                                IapProgram(0x0200+1,shui_h);    //保存高水位數(shù)據(jù)低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;
作者: 君工創(chuàng)    時間: 2023-1-27 22:41
按確認鍵(num==12),把設定的數(shù)據(jù)保存。
作者: 君工創(chuàng)    時間: 2023-1-27 22:48
這些都是STC的例程提供的
/*----------------------------
    關閉IAP
----------------------------*/
void IapIdle()
{
    IAP_CONTR = 0;                  //關閉IAP功能
    IAP_CMD = 0;                    //清除命令寄存器
    IAP_TRIG = 0;                   //清除觸發(fā)寄存器
    IAP_ADDRH = 0x80;               //將地址設置到非IAP區(qū)域
    IAP_ADDRL = 0;
        EA=1;
}

/*----------------------------
從ISP/IAP/EEPROM區(qū)域讀取一字節(jié)
----------------------------*/
char IapRead(int addr)          //讀數(shù)據(jù)
{
    BYTE dat;                       //數(shù)據(jù)緩沖區(qū)

    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_READ;             //設置IAP命令
    IAP_ADDRL = addr;               //設置IAP低地址
    IAP_ADDRH = addr >> 8;          //設置IAP高地址
    EA=0;
        IAP_TRIG = 0x5a;                //寫觸發(fā)命令(0x5a)
    IAP_TRIG = 0xa5;                //寫觸發(fā)命令(0xa5)
   
        _nop_();                        //等待ISP/IAP/EEPROM操作完成
    dat = IAP_DATA;                 //讀ISP/IAP/EEPROM數(shù)據(jù)
    IapIdle();                      //關閉IAP功能

    return dat;                     //返回
}

/*----------------------------
寫一字節(jié)數(shù)據(jù)到ISP/IAP/EEPROM區(qū)域
----------------------------*/
void IapProgram(int addr, char dat)        //寫數(shù)據(jù)
{
    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數(shù)據(jù)
    IAP_TRIG = 0x5a;                //寫觸發(fā)命令(0x5a)
    IAP_TRIG = 0xa5;                //寫觸發(fā)命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}

/*----------------------------
扇區(qū)擦除
----------------------------*/
void IapErase(int addr)                //扇區(qū)擦除
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_ERASE;            //設置IAP命令
    IAP_ADDRL = addr;               //設置IAP低地址
    IAP_ADDRH = addr >> 8;          //設置IAP高地址
    EA=0;
        IAP_TRIG = 0x5a;                //寫觸發(fā)命令(0x5a)
    IAP_TRIG = 0xa5;                //寫觸發(fā)命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}

作者: 君工創(chuàng)    時間: 2023-1-27 22:55
wulin 發(fā)表于 2023-1-27 20:59
不知道你的應用場景,無法做出判斷。如果是用于掉電保存,是需要有一定的編程技巧和硬件支持。

不是掉電,按確認鍵保存的。之前用過8G的,掉電保存都正常成功。
作者: 188610329    時間: 2023-1-28 00:00
檢查 iap_contr 的設置,是否和你晶振一致,
作者: wulin    時間: 2023-1-28 07:21
君工創(chuàng) 發(fā)表于 2023-1-27 22:55
不是掉電,按確認鍵保存的。之前用過8G的,掉電保存都正常成功。

CPU的等待時間ENABLE_IAP設置是否得當?芯片型號確認是STC15xxxx,不是IAP15xxxx?后者要另行指定保存地址。
作者: hhh402    時間: 2023-1-28 14:34
最可能是扇區(qū)擦除時間沒有設置正確,造成擦除不完全。要根據(jù)單片機使用頻率選擇。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
作者: frank_tw    時間: 2023-1-28 17:50
增加 _nop_(); 數(shù)量試試
Example
for (int i=0;i<50;i++)  _nop_();
作者: coody_sz    時間: 2023-1-28 17:58
樓主很可能是你設置的讀寫速度和MCU的頻率對不上導致的。
作者: 君工創(chuàng)    時間: 2023-1-28 22:10
多謝上面幾位的建議,我的CPU主頻是24MHz.
作者: aidianzi    時間: 2023-1-29 10:39
你程序問題  STC用了很多了沒有發(fā)現(xiàn)這個問題注意設置的時間控制寄存器設置是否正確
作者: hhh402    時間: 2023-1-29 21:45
CPU主頻是24MHz,比例程快了1倍,引用例程時有些地方需要多加一個_nop_(); 比如:
_nop_();                        //等待ISP/IAP/EEPROM操作完成
要多加一個_nop_();
另外:
#define ENABLE_IAP 0x81           //if SYSCLK<24MHz


作者: 君工創(chuàng)    時間: 2023-1-29 22:14
之前用0x80;對應30MHz,現(xiàn)在用#define ENABLE_IAP  0x81,對應24MHz,兩個都用過,沒有改變。
作者: 君工創(chuàng)    時間: 2023-1-29 22:17
唯有這個增加_nop_();未試過。
作者: Y_G_G    時間: 2023-1-30 09:20
不存在成功率這一說的
代碼正確了就一定行
代碼正確了,保存不了,單片機本身的問題概率小到幾乎為0
檢查一下代碼
作者: wulin    時間: 2023-1-30 09:56
君工創(chuàng) 發(fā)表于 2023-1-28 22:10
多謝上面幾位的建議,我的CPU主頻是24MHz.

有可能是樓主開了中斷,在讀寫EEPROM時發(fā)生中斷,破壞了正常讀寫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);                         //扇區(qū)擦除
                                IapProgram(0x0200,shui_h>>8);  //保存高水位數(shù)據(jù)高8位
                                IapProgram(0x0200+1,shui_h);    //保存高水位數(shù)據(jù)低8位
                                EA=1;
                        }
                }
作者: hhh402    時間: 2023-1-30 12:46
還有可能是電源濾波問題,24M需要103電容,12M需要104電容,樓主可以試試12M或6M主頻時是否正常。如果降低主頻正常,電源加一個103電容和1個22uf電容。
作者: 君工創(chuàng)    時間: 2023-1-30 13:17
wulin 發(fā)表于 2023-1-30 09:56
有可能是

我試過這個方法不行才改現(xiàn)在這的。
作者: 君工創(chuàng)    時間: 2023-1-30 13:19
hhh402 發(fā)表于 2023-1-30 12:46
還有可能是電

CPU傍邊有并104電容。
作者: hhh402    時間: 2023-1-30 15:09
24M主頻需要103電容,104不行。STC手冊有要求好好看一下。12M主頻以下要104電容。
作者: ningsy    時間: 2023-1-30 15:22
還有一個方法,問下STC的技術支持,就是產(chǎn)品手冊上那個電話。我還是單片機初哥的時候就問過一次,技術小妹很專業(yè),幾句話就把問題解決了。
作者: univers    時間: 2023-1-30 15:29
不可能的,要這樣說的話,芯片司也要倒閉了。
作者: hhh402    時間: 2023-1-30 16:06
STC手冊的建議,24M主頻需要103電容,12M主頻以下要104電容。大部分情況下用104都沒事,但是有部分會出問題。最好按手冊來做,要是經(jīng)常改變頻率,最好103,104電容都加上,安全一些。

無標題.jpg (250.64 KB, 下載次數(shù): 61)

無標題.jpg

作者: wulin    時間: 2023-1-30 17:34
君工創(chuàng) 發(fā)表于 2023-1-30 13:17
我試過這個方法不行才改現(xiàn)在這的。

STC的例程沒有問題,做各種應用測試也沒有出現(xiàn)過你上述現(xiàn)象。上萬件的產(chǎn)品出去沒有發(fā)生過EEPROM出這種問題。多數(shù)是你軟件或硬件有問題。
作者: 君工創(chuàng)    時間: 2023-1-30 21:33
hhh402 發(fā)表于 2023-1-30 16:06
STC手冊的建議,24M主頻需要103電容,12M主頻以下要104電容。大部分情況下用104都沒事,但是有部分會出問題 ...

謝謝你的提醒,一直沒有留意這個問題,而且我習慣用104,看來這個問題也要重視;氐綇V州再試下。
作者: 君工創(chuàng)    時間: 2023-1-31 09:25
wulin 發(fā)表于 2023-1-30 17:34
STC的例程沒有問題,做各種應用測試也沒有出現(xiàn)過你上述現(xiàn)象。上萬件的產(chǎn)品出去沒有發(fā)生過EEPROM出這種問 ...

我也認為是我的問題,只是暫時沒找到原因。




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1