久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 805|回復: 37
打印 上一主題 下一主題
收起左側

一個STC單片機EEPROM讀寫奇怪的問題

[復制鏈接]
跳轉到指定樓層
樓主
ID:232366 發表于 2025-4-5 22:33 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
遇到個奇怪的問題!!!!!單片機STC15F2K60S2  EEPROM兩個扇區,
讀寫程序用的是官方代碼,今天寫著寫著突然扇區2不能正常讀寫了,扇區1又可以一點問題都沒有!!!
然后又單獨對扇區2進行讀寫測試依然不行,同樣的程序換一塊一樣的單片機又可以正常讀寫了!!!

哪位老師可以給解答一下???


EEPROM扇區什么情況下會單獨壞一個扇區另外一個扇區又正常????
EEPROM什么情況下會損壞,操作EEPROM時需要注意的???



下載時已經勾選將EEPRO恢復到FF


這是串口讀出的數據:
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
                    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00






//本示例在Keil開發環境下請選擇Intel的8058芯片型號進行編譯
//若無特別說明,工作頻率一般為11.0592MHz


#define     FOSC    11059200UL
#define     BAUD    115200

typedef bit BOOL;
typedef unsigned char BYTE;
typedef unsigned int WORD;

#define CMD_IDLE    0               //空閑模式
#define CMD_READ    1               //IAP字節讀命令
#define CMD_PROGRAM 2               //IAP字節編程命令
#define CMD_ERASE   3               //IAP扇區擦除命令

#define     URMD    0               //0:使用定時器2作為波特率發生器
                                    //1:使用定時器1的模式0(16位自動重載模式)作為波特率發生器
                                    //2:使用定時器1的模式2(8位自動重載模式)作為波特率發生器
                                                                        
//#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

//測試地址
#define IAP_ADDRESS 0x0200

void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);
BYTE sequential_write_flash_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
BYTE write_flash_with_protect_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
void InitUart();
BYTE SendData(BYTE dat);


int i;

void main()
{
    P1M0 = 0x00;P1M1 = 0x00;
    P2M0 = 0x00;P2M1 = 0x00;
    P3M0 = 0x00;P3M1 = 0x00;
    P5M0 = 0x00;P5M1 = 0x00;

    InitUart();
        
    for (i=0; i<512; i++)           //校驗512字節
    {
        SendData(IapReadByte(IAP_ADDRESS+i));
    }
    while (1);
}

/*----------------------------
關閉IAP
----------------------------*/
void IapIdle()
{
    IAP_CONTR = 0;                  //關閉IAP功能
    IAP_CMD = 0;                    //清除命令寄存器
    IAP_TRIG = 0;                   //清除觸發寄存器
    IAP_ADDRH = 0x80;               //將地址設置到非IAP區域
    IAP_ADDRL = 0;
}

/*----------------------------
從ISP/IAP/EEPROM區域讀取一字節
----------------------------*/
BYTE IapReadByte(WORD addr)
{
    BYTE dat;                       //數據緩沖區

    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_READ;             //設置IAP命令
    IAP_ADDRL = addr;               //設置IAP低地址
    IAP_ADDRH = addr >> 8;          //設置IAP高地址
    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 IapProgramByte(WORD addr, BYTE dat)
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_PROGRAM;          //設置IAP命令
    IAP_ADDRL = addr;               //設置IAP低地址
    IAP_ADDRH = addr >> 8;          //設置IAP高地址
    IAP_DATA = dat;                 //寫ISP/IAP/EEPROM數據
    IAP_TRIG = 0x5a;                //寫觸發命令(0x5a)
    IAP_TRIG = 0xa5;                //寫觸發命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}

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

/*----------------------------
初始化串口
----------------------------*/
void InitUart()
{
    SCON = 0x5a;                //設置串口為8位可變波特率
#if URMD == 0
    T2L = (65536 - (FOSC/4/BAUD));
    T2H = (65536 - (FOSC/4/BAUD)) >> 8;
    AUXR = 0x14;                //T2為1T模式, 并啟動定時器2
    AUXR |= 0x01;               //選擇定時器2為串口1的波特率發生器
#elif URMD == 1
    AUXR = 0x40;                //定時器1為1T模式
    TMOD = 0x00;                //定時器1為模式0(16位自動重載)
    TL1 = (65536 - (FOSC/4/BAUD));
    TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
    TR1 = 1;                    //定時器1開始啟動
#else
    TMOD = 0x20;                //設置定時器1為8位自動重裝載模式
    AUXR = 0x40;                //定時器1為1T模式
    TH1 = TL1 = (256 - (FOSC/32/BAUD));
    TR1 = 1;
#endif
}

/*----------------------------
發送串口數據
----------------------------*/
BYTE SendData(BYTE dat)
{
    while (!TI);                 //等待前一個數據發送完成
    TI = 0;                      //清除發送標志
    SBUF = dat;                  //發送當前數據

    return dat;
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:1109793 發表于 2025-4-6 07:06 | 只看該作者
次數太多了?
回復

使用道具 舉報

板凳
ID:74687 發表于 2025-4-6 07:39 | 只看該作者
你問這個問題,代碼都不放一個,讓別人怎么回答你?
回復

使用道具 舉報

地板
ID:57657 發表于 2025-4-6 08:04 | 只看該作者
樓主的程序可能有問題:STC的EEPROM分為字節讀、字節寫(二進制1可寫為0不可逆)。
扇區擦除(沒有字節擦除),一次擦1扇區(512字節) 后恢復為0xFF(二進制全部的1)。
扇區2有問題可能是里面有數據且程序有問題,下載時將EEPROM全部填滿為0xFF。
回復

使用道具 舉報

5#
ID:341045 發表于 2025-4-6 09:22 | 只看該作者
新片子無問題就是壽命到了。EEROM以扇區為單位,只要數據非空,要修改只能扇區擦除,每扇區可靠擦寫也就10萬次,全力干1秒可干幾百次,幾分鐘就干廢了。查下程序是不是把EEROM當內存用了。
回復

使用道具 舉報

6#
ID:232366 發表于 2025-4-6 09:42 來自手機 | 只看該作者
zyftank 發表于 2025-4-6 07:39
你問這個問題,代碼都不放一個,讓別人怎么回答你?

您好、感謝您的回答、程序的問題已經可以排除。
回復

使用道具 舉報

7#
ID:232366 發表于 2025-4-6 09:45 來自手機 | 只看該作者
npn 發表于 2025-4-6 08:04
樓主的程序可能有問題:STC的EEPROM分為字節讀、字節寫(二進制1可寫為0不可逆)。
扇區擦除(沒有字節擦除), ...

試過了STCISP軟件下載時勾選了將EEPROM清除為FF
回復

使用道具 舉報

8#
ID:830831 發表于 2025-4-6 10:38 | 只看該作者
換一片
回復

使用道具 舉報

9#
ID:232366 發表于 2025-4-6 11:55 | 只看該作者
zyftank 發表于 2025-4-6 07:39
你問這個問題,代碼都不放一個,讓別人怎么回答你?

#include "main.h"


//本示例在Keil開發環境下請選擇Intel的8058芯片型號進行編譯
//若無特別說明,工作頻率一般為11.0592MHz


#define     FOSC    11059200UL
#define     BAUD    115200

typedef bit BOOL;
typedef unsigned char BYTE;
typedef unsigned int WORD;

#define CMD_IDLE    0               //空閑模式
#define CMD_READ    1               //IAP字節讀命令
#define CMD_PROGRAM 2               //IAP字節編程命令
#define CMD_ERASE   3               //IAP扇區擦除命令

#define     URMD    0               //0:使用定時器2作為波特率發生器
                                    //1:使用定時器1的模式0(16位自動重載模式)作為波特率發生器
                                    //2:使用定時器1的模式2(8位自動重載模式)作為波特率發生器
                                                                       
//#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

//測試地址
#define IAP_ADDRESS 0x0400

void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);
BYTE sequential_write_flash_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
BYTE write_flash_with_protect_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
void InitUart();
BYTE SendData(BYTE dat);


int i;

void main()
{
    P1M0 = 0x00;P1M1 = 0x00;
    P2M0 = 0x00;P2M1 = 0x00;
    P3M0 = 0x00;P3M1 = 0x00;
    P5M0 = 0x00;P5M1 = 0x00;

    InitUart();
       
    for (i=0; i<512; i++)           //校驗512字節
    {
        SendData(IapReadByte(IAP_ADDRESS+i));
    }
    while (1);
}

/*----------------------------
關閉IAP
----------------------------*/
void IapIdle()
{
    IAP_CONTR = 0;                  //關閉IAP功能
    IAP_CMD = 0;                    //清除命令寄存器
    IAP_TRIG = 0;                   //清除觸發寄存器
    IAP_ADDRH = 0x80;               //將地址設置到非IAP區域
    IAP_ADDRL = 0;
}

/*----------------------------
從ISP/IAP/EEPROM區域讀取一字節
----------------------------*/
BYTE IapReadByte(WORD addr)
{
    BYTE dat;                       //數據緩沖區

    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_READ;             //設置IAP命令
    IAP_ADDRL = addr;               //設置IAP低地址
    IAP_ADDRH = addr >> 8;          //設置IAP高地址
    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 IapProgramByte(WORD addr, BYTE dat)
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_PROGRAM;          //設置IAP命令
    IAP_ADDRL = addr;               //設置IAP低地址
    IAP_ADDRH = addr >> 8;          //設置IAP高地址
    IAP_DATA = dat;                 //寫ISP/IAP/EEPROM數據
    IAP_TRIG = 0x5a;                //寫觸發命令(0x5a)
    IAP_TRIG = 0xa5;                //寫觸發命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}

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

/*----------------------------
初始化串口
----------------------------*/
void InitUart()
{
    SCON = 0x5a;                //設置串口為8位可變波特率
#if URMD == 0
    T2L = (65536 - (FOSC/4/BAUD));
    T2H = (65536 - (FOSC/4/BAUD)) >> 8;
    AUXR = 0x14;                //T2為1T模式, 并啟動定時器2
    AUXR |= 0x01;               //選擇定時器2為串口1的波特率發生器
#elif URMD == 1
    AUXR = 0x40;                //定時器1為1T模式
    TMOD = 0x00;                //定時器1為模式0(16位自動重載)
    TL1 = (65536 - (FOSC/4/BAUD));
    TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
    TR1 = 1;                    //定時器1開始啟動
#else
    TMOD = 0x20;                //設置定時器1為8位自動重裝載模式
    AUXR = 0x40;                //定時器1為1T模式
    TH1 = TL1 = (256 - (FOSC/32/BAUD));
    TR1 = 1;
#endif
}

/*----------------------------
發送串口數據
----------------------------*/
BYTE SendData(BYTE dat)
{
    while (!TI);                 //等待前一個數據發送完成
    TI = 0;                      //清除發送標志
    SBUF = dat;                  //發送當前數據
   
    return dat;
}
回復

使用道具 舉報

10#
ID:232366 發表于 2025-4-6 11:55 | 只看該作者
npn 發表于 2025-4-6 08:04
樓主的程序可能有問題:STC的EEPROM分為字節讀、字節寫(二進制1可寫為0不可逆)。
扇區擦除(沒有字節擦除), ...

#include "main.h"


//本示例在Keil開發環境下請選擇Intel的8058芯片型號進行編譯
//若無特別說明,工作頻率一般為11.0592MHz


#define     FOSC    11059200UL
#define     BAUD    115200

typedef bit BOOL;
typedef unsigned char BYTE;
typedef unsigned int WORD;

#define CMD_IDLE    0               //空閑模式
#define CMD_READ    1               //IAP字節讀命令
#define CMD_PROGRAM 2               //IAP字節編程命令
#define CMD_ERASE   3               //IAP扇區擦除命令

#define     URMD    0               //0:使用定時器2作為波特率發生器
                                    //1:使用定時器1的模式0(16位自動重載模式)作為波特率發生器
                                    //2:使用定時器1的模式2(8位自動重載模式)作為波特率發生器
                                                                       
//#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

//測試地址
#define IAP_ADDRESS 0x0400

void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);
BYTE sequential_write_flash_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
BYTE write_flash_with_protect_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
void InitUart();
BYTE SendData(BYTE dat);


int i;

void main()
{
    P1M0 = 0x00;P1M1 = 0x00;
    P2M0 = 0x00;P2M1 = 0x00;
    P3M0 = 0x00;P3M1 = 0x00;
    P5M0 = 0x00;P5M1 = 0x00;

    InitUart();
       
    for (i=0; i<512; i++)           //校驗512字節
    {
        SendData(IapReadByte(IAP_ADDRESS+i));
    }
    while (1);
}

/*----------------------------
關閉IAP
----------------------------*/
void IapIdle()
{
    IAP_CONTR = 0;                  //關閉IAP功能
    IAP_CMD = 0;                    //清除命令寄存器
    IAP_TRIG = 0;                   //清除觸發寄存器
    IAP_ADDRH = 0x80;               //將地址設置到非IAP區域
    IAP_ADDRL = 0;
}

/*----------------------------
從ISP/IAP/EEPROM區域讀取一字節
----------------------------*/
BYTE IapReadByte(WORD addr)
{
    BYTE dat;                       //數據緩沖區

    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_READ;             //設置IAP命令
    IAP_ADDRL = addr;               //設置IAP低地址
    IAP_ADDRH = addr >> 8;          //設置IAP高地址
    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 IapProgramByte(WORD addr, BYTE dat)
{
    IAP_CONTR = ENABLE_IAP;         //使能IAP
    IAP_CMD = CMD_PROGRAM;          //設置IAP命令
    IAP_ADDRL = addr;               //設置IAP低地址
    IAP_ADDRH = addr >> 8;          //設置IAP高地址
    IAP_DATA = dat;                 //寫ISP/IAP/EEPROM數據
    IAP_TRIG = 0x5a;                //寫觸發命令(0x5a)
    IAP_TRIG = 0xa5;                //寫觸發命令(0xa5)
    _nop_();                        //等待ISP/IAP/EEPROM操作完成
    IapIdle();
}

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

/*----------------------------
初始化串口
----------------------------*/
void InitUart()
{
    SCON = 0x5a;                //設置串口為8位可變波特率
#if URMD == 0
    T2L = (65536 - (FOSC/4/BAUD));
    T2H = (65536 - (FOSC/4/BAUD)) >> 8;
    AUXR = 0x14;                //T2為1T模式, 并啟動定時器2
    AUXR |= 0x01;               //選擇定時器2為串口1的波特率發生器
#elif URMD == 1
    AUXR = 0x40;                //定時器1為1T模式
    TMOD = 0x00;                //定時器1為模式0(16位自動重載)
    TL1 = (65536 - (FOSC/4/BAUD));
    TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
    TR1 = 1;                    //定時器1開始啟動
#else
    TMOD = 0x20;                //設置定時器1為8位自動重裝載模式
    AUXR = 0x40;                //定時器1為1T模式
    TH1 = TL1 = (256 - (FOSC/32/BAUD));
    TR1 = 1;
#endif
}

/*----------------------------
發送串口數據
----------------------------*/
BYTE SendData(BYTE dat)
{
    while (!TI);                 //等待前一個數據發送完成
    TI = 0;                      //清除發送標志
    SBUF = dat;                  //發送當前數據
   
    return dat;
}
回復

使用道具 舉報

11#
ID:232366 發表于 2025-4-6 21:09 | 只看該作者

不知道目前問題還未找出來
回復

使用道具 舉報

12#
ID:232366 發表于 2025-4-6 21:09 | 只看該作者

如您所說   換一片就好了
回復

使用道具 舉報

13#
ID:879348 發表于 2025-4-7 09:01 | 只看該作者
這個東西的壽命次數是有限的,擦除一次就是一次壽命,所以千萬不要用EEPROM的思維操作它,雖然它有10萬次,但是如果你放在主循環不停擦除也堅持不了多久
回復

使用道具 舉報

14#
ID:74687 發表于 2025-4-7 09:12 | 只看該作者
看你也不是外接的EEPROM,如果外掛的EEPROM,出現這種情況,有可能是數據線沒有上拉電阻。
回復

使用道具 舉報

15#
ID:341045 發表于 2025-4-7 10:15 | 只看該作者
都是在打啞迷,你放這程序是什么鬼,只是讀,怎么變的寫著寫著的。而且這程序感覺有問題,會是官方的。因為i感覺要定義一下,至少8位和16位是不同的
回復

使用道具 舉報

16#
ID:1109793 發表于 2025-4-7 10:57 | 只看該作者
lzts88 發表于 2025-4-7 10:15
都是在打啞迷,你放這程序是什么鬼,只是讀,怎么變的寫著寫著的。而且這程序感覺有問題,會是官方的。因為 ...

人家不是有個int i;嗎?
樓主的意思大概是下載時,選了清除為0XFF。但是上電后讀出來通過串口發送出去的是0x00,難道不應該是0XFF嗎?
回復

使用道具 舉報

17#
ID:232366 發表于 2025-4-7 11:12 | 只看該作者
xiaobendan001 發表于 2025-4-7 10:57
人家不是有個int i;嗎?
樓主的意思大概是下載時,選了清除為0XFF。但是上電后讀出來通過串口發送出去的 ...

是的  非常正確✅    實際全部都是0  扇區0就不會
回復

使用道具 舉報

18#
ID:232366 發表于 2025-4-7 11:14 | 只看該作者
wufa1986 發表于 2025-4-7 09:01
這個東西的壽命次數是有限的,擦除一次就是一次壽命,所以千萬不要用EEPROM的思維操作它,雖然它有10萬次, ...

你肯定沒有認真看我的問題呢!
回復

使用道具 舉報

19#
ID:232366 發表于 2025-4-7 12:18 | 只看該作者
lzts88 發表于 2025-4-6 09:22
新片子無問題就是壽命到了。EEROM以扇區為單位,只要數據非空,要修改只能扇區擦除,每扇區可靠擦寫也就10 ...

比如需要注意些啥方面
回復

使用道具 舉報

20#
ID:232366 發表于 2025-4-7 12:20 | 只看該作者
wufa1986 發表于 2025-4-7 09:01
這個東西的壽命次數是有限的,擦除一次就是一次壽命,所以千萬不要用EEPROM的思維操作它,雖然它有10萬次, ...

沒有放在大循環里
回復

使用道具 舉報

21#
ID:57657 發表于 2025-4-8 07:27 | 只看該作者
下載時EEPROM文件全部填充0xAA,然后用unsigned char code指針讀取,具體地址見數據手冊,讀不出來表示可能有損壞。
回復

使用道具 舉報

22#
ID:232366 發表于 2025-4-8 14:51 | 只看該作者
zyftank 發表于 2025-4-7 09:12
看你也不是外接的EEPROM,如果外掛的EEPROM,出現這種情況,有可能是數據線沒有上拉電阻。

是內部的EEPROM
回復

使用道具 舉報

23#
ID:232366 發表于 2025-4-8 14:52 | 只看該作者
lzts88 發表于 2025-4-6 09:22
新片子無問題就是壽命到了。EEROM以扇區為單位,只要數據非空,要修改只能扇區擦除,每扇區可靠擦寫也就10 ...

現在單獨測試扇區2都不行了
回復

使用道具 舉報

24#
ID:232366 發表于 2025-4-8 14:55 | 只看該作者
npn 發表于 2025-4-8 07:27
下載時EEPROM文件全部填充0xAA,然后用unsigned char code指針讀取,具體地址見數據手冊,讀不出來表示可能 ...

下載時不是只能復位到FF嗎?    使用指針讀取?是_at _嗎?   有點沒看懂
回復

使用道具 舉報

25#
ID:1109793 發表于 2025-4-8 16:30 | 只看該作者
SHANWAZI 發表于 2025-4-8 14:55
下載時不是只能復位到FF嗎?    使用指針讀取?是_at _嗎?   有點沒看懂

我的STC軟件里面只顯示清除,并沒顯示是00還是FF啊。
回復

使用道具 舉報

26#
ID:232366 發表于 2025-4-8 18:39 | 只看該作者
xiaobendan001 發表于 2025-4-8 16:30
我的STC軟件里面只顯示清除,并沒顯示是00還是FF啊。

V6.95K版本
回復

使用道具 舉報

27#
ID:1109793 發表于 2025-4-9 09:41 | 只看該作者

可以單獨做個文件用來在下載時給EEPROM填充一些初始數據。這樣測試產品時就方便許多
回復

使用道具 舉報

28#
ID:57657 發表于 2025-4-9 15:39 | 只看該作者
SHANWAZI 發表于 2025-4-8 14:55
下載時不是只能復位到FF嗎?    使用指針讀取?是_at _嗎?   有點沒看懂

下載時EEPROM可以寫數據的,有不懂的地方可以咨詢STC總部。
回復

使用道具 舉報

29#
ID:232366 發表于 2025-4-9 17:43 | 只看該作者
npn 發表于 2025-4-9 15:39
下載時EEPROM可以寫數據的,有不懂的地方可以咨詢STC總部。

現在的問題是寫進去的是FF讀出來是00
回復

使用道具 舉報

30#
ID:1109793 發表于 2025-4-10 07:52 | 只看該作者
換個新的就好了,一段時間又不行了,大概是代碼有問題,寫的太頻繁
回復

使用道具 舉報

31#
ID:232366 發表于 2025-4-11 02:32 | 只看該作者
xiaobendan001 發表于 2025-4-10 07:52
換個新的就好了,一段時間又不行了,大概是代碼有問題,寫的太頻繁

不是一段時間不行
回復

使用道具 舉報

32#
ID:1109793 發表于 2025-4-11 13:05 | 只看該作者
SHANWAZI 發表于 2025-4-11 02:32
不是一段時間不行

不是說兩片都不行嗎啊?
回復

使用道具 舉報

33#
ID:232366 發表于 2025-4-11 21:12 | 只看該作者
xiaobendan001 發表于 2025-4-11 13:05
不是說兩片都不行嗎啊?

您認真看一下我的問題!!!!
回復

使用道具 舉報

34#
ID:1133081 發表于 2025-4-12 07:29 | 只看該作者
SHANWAZI 發表于 2025-4-6 09:42
您好、感謝您的回答、程序的問題已經可以排除。

樓主聲稱“程序的問題已經可以排除”,其實問題就在樓主程序本身。硬件MCU 99.99%沒有問題。樓主并沒有完全按照官方測試程序運行,只是把官方測試程序想當然的修改后用來測試,當然得不到預想結果。首先要確定被測MCU型號系列,STC不同型號MCU的EEPROM扇區地址范圍有可能不同。測試步驟通常是先擦除扇區,然后寫數據,再讀取數據校驗。STC15F2K60S2官方測試程序如下:
  1. //本示例在Keil開發環境下請選擇Intel的8058芯片型號進行編譯
  2. //若無特別說明,工作頻率一般為11.0592MHz


  3. #include "reg51.h"
  4. #include "intrins.h"

  5. #define     FOSC    11059200UL
  6. #define     BAUD    115200

  7. typedef bit BOOL;
  8. typedef unsigned char BYTE;
  9. typedef unsigned int WORD;

  10. #define ERROR   0
  11. #define OK      1

  12. //-----------------------------------------------

  13. sfr IAP_DATA    =   0xC2;           //IAP數據寄存器
  14. sfr IAP_ADDRH   =   0xC3;           //IAP地址寄存器高字節
  15. sfr IAP_ADDRL   =   0xC4;           //IAP地址寄存器低字節
  16. sfr IAP_CMD     =   0xC5;           //IAP命令寄存器
  17. sfr IAP_TRIG    =   0xC6;           //IAP命令觸發寄存器
  18. sfr IAP_CONTR   =   0xC7;           //IAP控制寄存器

  19. sbit Begin_LED  =   P1^0;
  20. sbit ERROR_LED  =   P1^3;
  21. sbit OK_LED     =   P1^7;

  22. #define CMD_IDLE    0               //空閑模式
  23. #define CMD_READ    1               //IAP字節讀命令
  24. #define CMD_PROGRAM 2               //IAP字節編程命令
  25. #define CMD_ERASE   3               //IAP扇區擦除命令

  26. #define     URMD    0               //0:使用定時器2作為波特率發生器
  27.                                     //1:使用定時器1的模式0(16位自動重載模式)作為波特率發生器
  28.                                     //2:使用定時器1的模式2(8位自動重載模式)作為波特率發生器

  29. sfr P0M1 = 0x93;
  30. sfr P0M0 = 0x94;
  31. sfr P1M1 = 0x91;
  32. sfr P1M0 = 0x92;
  33. sfr P2M1 = 0x95;
  34. sfr P2M0 = 0x96;
  35. sfr P3M1 = 0xb1;
  36. sfr P3M0 = 0xb2;
  37. sfr P4M1 = 0xb3;
  38. sfr P4M0 = 0xb4;
  39. sfr P5M1 = 0xC9;
  40. sfr P5M0 = 0xCA;
  41. sfr P6M1 = 0xCB;
  42. sfr P6M0 = 0xCC;
  43. sfr P7M1 = 0xE1;
  44. sfr P7M0 = 0xE2;

  45. sfr T2H   = 0xd6;                   //定時器2高8位
  46. sfr T2L   = 0xd7;                   //定時器2低8位

  47. sfr  AUXR       =   0x8e;           //輔助寄存器                              

  48. //#define ENABLE_IAP 0x80           //if SYSCLK<30MHz
  49. //#define ENABLE_IAP 0x81           //if SYSCLK<24MHz
  50. #define ENABLE_IAP  0x82            //if SYSCLK<20MHz
  51. //#define ENABLE_IAP 0x83           //if SYSCLK<12MHz
  52. //#define ENABLE_IAP 0x84           //if SYSCLK<6MHz
  53. //#define ENABLE_IAP 0x85           //if SYSCLK<3MHz
  54. //#define ENABLE_IAP 0x86           //if SYSCLK<2MHz
  55. //#define ENABLE_IAP 0x87           //if SYSCLK<1MHz

  56. //測試地址
  57. #define IAP_ADDRESS 0x0400

  58. void IapIdle();
  59. BYTE IapReadByte(WORD addr);
  60. void IapProgramByte(WORD addr, BYTE dat);
  61. void IapEraseSector(WORD addr);
  62. BYTE sequential_write_flash_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
  63. BYTE write_flash_with_protect_in_one_sector(WORD begin_addr, WORD counter, BYTE array[]);
  64. void InitUart();
  65. BYTE SendData(BYTE dat);

  66. #define display_Begin_LED() Begin_LED = 0
  67. #define off_Begin_LED()     Begin_LED = 1
  68. #define display_OK_LED()    OK_LED = 0
  69. #define off_OK_LED()        OK_LED = 1
  70. #define display_ERROR_LED() ERROR_LED = 0
  71. #define off_ERROR_LED()     ERROR_LED = 1

  72. //#define USED_BYTE_QTY_IN_ONE_SECTOR   1
  73. //#define USED_BYTE_QTY_IN_ONE_SECTOR   2
  74. //#define USED_BYTE_QTY_IN_ONE_SECTOR   4
  75. //#define USED_BYTE_QTY_IN_ONE_SECTOR   8
  76. //#define USED_BYTE_QTY_IN_ONE_SECTOR   16
  77. //#define USED_BYTE_QTY_IN_ONE_SECTOR   32
  78. //#define USED_BYTE_QTY_IN_ONE_SECTOR   64
  79. #define USED_BYTE_QTY_IN_ONE_SECTOR     128
  80. //#define USED_BYTE_QTY_IN_ONE_SECTOR   256
  81. //#define USED_BYTE_QTY_IN_ONE_SECTOR   512

  82. #define DEBUG_Data_Memory_Begin_Sector_addr     0x0400

  83. BYTE xdata protect_buffer[USED_BYTE_QTY_IN_ONE_SECTOR];

  84. /* 測試常量數組 */
  85. BYTE code Test_array_total[512] =
  86. {
  87.     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
  88.     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
  89.     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
  90.     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
  91.     0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
  92.     0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
  93.     0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
  94.     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
  95.     0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
  96.     0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
  97.     0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
  98.     0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
  99.     0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
  100.     0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
  101.     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
  102.     0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
  103.     0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0,
  104.     0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe5,0xe4,0xe3,0xe2,0xe1,0xe0,
  105.     0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd0,
  106.     0xcf,0xce,0xcd,0xcc,0xcb,0xca,0xc9,0xc8,0xc7,0xc6,0xc5,0xc4,0xc3,0xc2,0xc1,0xc0,
  107.     0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0,
  108.     0xaf,0xae,0xad,0xac,0xab,0xaa,0xa9,0xa8,0xa7,0xa6,0xa5,0xa4,0xa3,0xa2,0xa1,0xa0,
  109.     0x9f,0x9e,0x9d,0x9c,0x9b,0x9a,0x99,0x98,0x97,0x96,0x95,0x94,0x93,0x92,0x91,0x90,
  110.     0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x84,0x83,0x82,0x81,0x80,
  111.     0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x71,0x70,
  112.     0x6f,0x6e,0x6d,0x6c,0x6b,0x6a,0x69,0x68,0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x60,
  113.     0x5f,0x5e,0x5d,0x5c,0x5b,0x5a,0x59,0x58,0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50,
  114.     0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40,
  115.     0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x33,0x36,0x35,0x34,0x33,0x32,0x31,0x30,
  116.     0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,
  117.     0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,
  118.     0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00
  119. };

  120. void main()
  121. {
  122.     P0M0 = 0x00;
  123.     P0M1 = 0x00;
  124.     P1M0 = 0x00;
  125.     P1M1 = 0x00;
  126.     P2M0 = 0x00;
  127.     P2M1 = 0x00;
  128.     P3M0 = 0x00;
  129.     P3M1 = 0x00;
  130.     P4M0 = 0x00;
  131.     P4M1 = 0x00;
  132.     P5M0 = 0x00;
  133.     P5M1 = 0x00;
  134.     P6M0 = 0x00;
  135.     P6M1 = 0x00;
  136.     P7M0 = 0x00;
  137.     P7M1 = 0x00;

  138.     InitUart();
  139.   
  140. //  if(sequential_write_flash_in_one_sector(DEBUG_Data_Memory_Begin_Sector_addr, USED_BYTE_QTY_IN_ONE_SECTOR, Test_array_total))
  141. //      display_OK_LED();
  142. //  else
  143. //      display_ERROR_LED();

  144.     if(write_flash_with_protect_in_one_sector(DEBUG_Data_Memory_Begin_Sector_addr+0x3, USED_BYTE_QTY_IN_ONE_SECTOR-0x30, Test_array_total))
  145.         display_OK_LED();
  146.     else
  147.         display_ERROR_LED();

  148.     while(1);
  149. }

  150. /*----------------------------
  151. 關閉IAP
  152. ----------------------------*/
  153. void IapIdle()
  154. {
  155.     IAP_CONTR = 0;                  //關閉IAP功能
  156.     IAP_CMD = 0;                    //清除命令寄存器
  157.     IAP_TRIG = 0;                   //清除觸發寄存器
  158.     IAP_ADDRH = 0x80;               //將地址設置到非IAP區域
  159.     IAP_ADDRL = 0;
  160. }

  161. /*----------------------------
  162. 從ISP/IAP/EEPROM區域讀取一字節
  163. ----------------------------*/
  164. BYTE IapReadByte(WORD addr)
  165. {
  166.     BYTE dat;                       //數據緩沖區

  167.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  168.     IAP_CMD = CMD_READ;             //設置IAP命令
  169.     IAP_ADDRL = addr;               //設置IAP低地址
  170.     IAP_ADDRH = addr >> 8;          //設置IAP高地址
  171.     IAP_TRIG = 0x5a;                //寫觸發命令(0x5a)
  172.     IAP_TRIG = 0xa5;                //寫觸發命令(0xa5)
  173.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  174.     dat = IAP_DATA;                 //讀ISP/IAP/EEPROM數據
  175.     IapIdle();                      //關閉IAP功能

  176.     return dat;                     //返回
  177. }

  178. /*----------------------------
  179. 寫一字節數據到ISP/IAP/EEPROM區域
  180. ----------------------------*/
  181. void IapProgramByte(WORD addr, BYTE dat)
  182. {
  183.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  184.     IAP_CMD = CMD_PROGRAM;          //設置IAP命令
  185.     IAP_ADDRL = addr;               //設置IAP低地址
  186.     IAP_ADDRH = addr >> 8;          //設置IAP高地址
  187.     IAP_DATA = dat;                 //寫ISP/IAP/EEPROM數據
  188.     IAP_TRIG = 0x5a;                //寫觸發命令(0x5a)
  189.     IAP_TRIG = 0xa5;                //寫觸發命令(0xa5)
  190.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  191.     IapIdle();
  192. }

  193. /*----------------------------
  194. 扇區擦除
  195. ----------------------------*/
  196. void IapEraseSector(WORD addr)
  197. {
  198.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  199.     IAP_CMD = CMD_ERASE;            //設置IAP命令
  200.     IAP_ADDRL = addr;               //設置IAP低地址
  201.     IAP_ADDRH = addr >> 8;          //設置IAP高地址
  202.     IAP_TRIG = 0x5a;                //寫觸發命令(0x5a)
  203.     IAP_TRIG = 0xa5;                //寫觸發命令(0xa5)
  204.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  205.     IapIdle();
  206. }

  207. /* 寫數據進 數據Flash存儲器, 只在同一個扇區內寫,不保留原有數據 */
  208. /* begin_addr,被寫數據Flash開始地址;counter,連續寫多少個字節; array[],數據來源   */
  209. BYTE sequential_write_flash_in_one_sector(WORD begin_addr, WORD counter, BYTE array[])
  210. {
  211.     WORD i = 0;
  212.     WORD in_sector_begin_addr = 0;
  213.     WORD sector_addr = 0;

  214.     /* 判是否是有效范圍,此函數不允許跨扇區操作 */
  215.     if(counter > USED_BYTE_QTY_IN_ONE_SECTOR)
  216.         return  ERROR;
  217.     in_sector_begin_addr = begin_addr & 0x01ff;
  218.     if((in_sector_begin_addr + counter) > USED_BYTE_QTY_IN_ONE_SECTOR)
  219.         return ERROR;

  220.     /* 擦除 要修改/寫入 的扇區 */
  221.     IapEraseSector(begin_addr);

  222.     for(i=0; i<counter; i++)
  223.     {
  224.         /* 寫一個字節 */
  225.         IapProgramByte(begin_addr, array[i]);
  226.         /*  比較對錯 */
  227.         if (SendData(IapReadByte(begin_addr)) != array[i])
  228.         {
  229.             IapIdle();
  230.             return ERROR;
  231.         }
  232.         begin_addr++;
  233.     }
  234.     IapIdle();
  235.     return  OK;
  236. }

  237. /* 寫數據進數據Flash存儲器(EEPROM), 只在同一個扇區內寫,保留同一扇區中不需修改的數據    */
  238. /* begin_addr,被寫數據Flash開始地址;counter,連續寫多少個字節; array[],數據來源       */
  239. BYTE write_flash_with_protect_in_one_sector(WORD begin_addr, WORD counter, BYTE array[])
  240. {
  241.     WORD i = 0;
  242.     WORD in_sector_begin_addr = 0;
  243.     WORD sector_addr = 0;
  244.     WORD byte_addr = 0;

  245.     /* 判是否是有效范圍,此函數不允許跨扇區操作 */
  246.     if(counter > USED_BYTE_QTY_IN_ONE_SECTOR)
  247.         return ERROR;
  248.     in_sector_begin_addr = begin_addr & 0x01ff;
  249.     /* 假定從扇區的第0個字節開始,到USED_BYTE_QTY_IN_ONE_SECTOR-1個字節結束,后面部分不用,程序易編寫 */
  250.     if((in_sector_begin_addr + counter) > USED_BYTE_QTY_IN_ONE_SECTOR)
  251.         return ERROR;

  252.     /* 將該扇區數據 0 - (USED_BYTE_QTY_IN_ONE_SECTOR-1) 字節數據讀入緩沖區保護 */
  253.     sector_addr = (begin_addr & 0xfe00);
  254.     byte_addr = sector_addr;

  255.     for(i = 0; i < USED_BYTE_QTY_IN_ONE_SECTOR; i++)
  256.     {
  257.         protect_buffer[i] = IapReadByte(byte_addr++);
  258.     }

  259.     /* 將要寫入的數據寫入保護緩沖區的相應區域,其余部分保留 */
  260.     for(i = 0; i < counter; i++)
  261.     {
  262.         protect_buffer[in_sector_begin_addr++] = array[i];
  263.     }

  264.     /* 擦除 要修改/寫入 的扇區 */
  265.     IapEraseSector(sector_addr);

  266.     /* 將保護緩沖區的數據寫入 Data Flash, EEPROM */
  267.     byte_addr = sector_addr;
  268.     for(i = 0; i< USED_BYTE_QTY_IN_ONE_SECTOR; i++)
  269.     {
  270.         /* 寫一個字節 */
  271.         IapProgramByte(byte_addr, protect_buffer[i]);
  272.         /*  比較對錯 */
  273.         if (SendData(IapReadByte(begin_addr)) != protect_buffer[i])
  274.         {
  275.             IapIdle();
  276.             return ERROR;
  277.         }
  278.         byte_addr++;
  279.     }
  280.     IapIdle();
  281.     return OK;
  282. }

  283. /*----------------------------
  284. 初始化串口
  285. ----------------------------*/
  286. void InitUart()
  287. {
  288.     SCON = 0x5a;                //設置串口為8位可變波特率
  289. #if URMD == 0
  290.     T2L = (65536 - (FOSC/4/BAUD));
  291.     T2H = (65536 - (FOSC/4/BAUD)) >> 8;
  292.     AUXR = 0x14;                //T2為1T模式, 并啟動定時器2
  293.     AUXR |= 0x01;               //選擇定時器2為串口1的波特率發生器
  294. #elif URMD == 1
  295.     AUXR = 0x40;                //定時器1為1T模式
  296.     TMOD = 0x00;                //定時器1為模式0(16位自動重載)
  297.     TL1 = (65536 - (FOSC/4/BAUD));
  298.     TH1 = (65536 - (FOSC/4/BAUD)) >> 8;
  299.     TR1 = 1;                    //定時器1開始啟動
  300. #else
  301.     TMOD = 0x20;                //設置定時器1為8位自動重裝載模式
  302.     AUXR = 0x40;                //定時器1為1T模式
  303.     TH1 = TL1 = (256 - (FOSC/32/BAUD));
  304.     TR1 = 1;
  305. #endif
  306. }

  307. /*----------------------------
  308. 發送串口數據
  309. ----------------------------*/
  310. BYTE SendData(BYTE dat)
  311. {
  312.     while (!TI);                 //等待前一個數據發送完成
  313.     TI = 0;                      //清除發送標志
  314.     SBUF = dat;                  //發送當前數據
  315.    
  316.     return dat;
  317. }

復制代碼
回復

使用道具 舉報

35#
ID:232366 發表于 2025-4-12 21:17 | 只看該作者
WL0123 發表于 2025-4-12 07:29
樓主聲稱“程序的問題已經可以排除”,其實問題就在樓主程序本身。硬件MCU 99.99%沒有問題。樓主并沒有完 ...

首先非常感謝壇友如此認真回復我的問題!!!!那我應該如何測試呢!!!目前我能想到的是不行的,本著使用對比法,兩片單片機對比同樣的程序新的單片機就可以正常,下載時選擇將EEPROM清除為FF用串口讀出來全部都是FF狀態!!!!!
回復

使用道具 舉報

36#
ID:1133081 發表于 2025-4-13 07:32 | 只看該作者
SHANWAZI 發表于 2025-4-12 21:17
首先非常感謝壇友如此認真回復我的問題!!!!那我應該如何測試呢!!!目前我能想到的是不行的,本著使 ...

宏晶公司MCU片內EEPROM是采用ISP/IAP技術用Fiash當EEPROM使用。其特點是只能寫0不能寫1,并且有擦除使用壽命。官方說10萬次以上。也就是不可以過于頻繁擦寫。新片的EEPROM原始數據全部為0xff。要改寫內容必須先按扇區為單位擦除整個扇區,哪怕只寫1個字節也要擦除整個扇區,然后才能正確寫入數據,否則出錯是大概率事件。從你的測試程序看,你在寫數據前并沒有先擦除扇區。新片第一次能正確讀出數據是因為新片EEPROM的原始狀態全部是0xff。當你再次寫數據時其之前的數據并沒有擦除。所以出錯就是必然的。只要你在程序中先擦除再寫入,就不必糾結是否在下載時是否選擇擦除EEPROM選項。在沒有十分把握的情況下最好直接使用官方測試程序。各種型號的測試程序在stc-isp軟件里都能找到。
回復

使用道具 舉報

37#
ID:1109793 發表于 2025-4-13 08:09 | 只看該作者
不要糾結這個問題,偶爾會有某些方面不良的芯片的,盡管概率很低。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品日韩欧美一区二区三区 | 精品国产乱码久久久久久图片 | 久久久精品一区二区三区 | 日韩成人在线免费视频 | 男女免费观看在线爽爽爽视频 | 日日日日日日bbbbb视频 | 国产精品二区三区 | 日韩一区二区三区视频 | 99免费视频| 可以在线观看av的网站 | 羞羞在线视频 | 视频在线h | 精品国产欧美一区二区三区不卡 | 久久久久久国模大尺度人体 | 欧美高清一区 | 欧美一级在线免费 | 成人久久久久久久久 | 国产日韩欧美在线 | 视频在线观看亚洲 | 精品人伦一区二区三区蜜桃网站 | 国产a级黄色录像 | av网站免费在线观看 | 色www精品视频在线观看 | 91精品久久久久久久久中文字幕 | 成人不卡视频 | 欧美日韩国产中文字幕 | 中文字幕1区 | 亚洲视频二区 | 亚洲精品国产偷自在线观看 | 黑人巨大精品欧美黑白配亚洲 | 久久久久久久久久影视 | 日韩精品一区二区三区在线观看 | 九九综合 | 精品国产乱码久久久久久图片 | 超碰在线97国产 | 中文字幕日韩欧美一区二区三区 | 久久国产亚洲 | 亚洲电影在线播放 | 日韩精品一区二区三区中文在线 | 男女国产网站 | 色综合久久天天综合网 |