樓主聲稱“程序的問題已經可以排除”,其實問題就在樓主程序本身。硬件MCU 99.99%沒有問題。樓主并沒有完全按照官方測試程序運行,只是把官方測試程序想當然的修改后用來測試,當然得不到預想結果。首先要確定被測MCU型號系列,STC不同型號MCU的EEPROM扇區地址范圍有可能不同。測試步驟通常是先擦除扇區,然后寫數據,再讀取數據校驗。STC15F2K60S2官方測試程序如下:
- //本示例在Keil開發環境下請選擇Intel的8058芯片型號進行編譯
- //若無特別說明,工作頻率一般為11.0592MHz
- #include "reg51.h"
- #include "intrins.h"
- #define FOSC 11059200UL
- #define BAUD 115200
- typedef bit BOOL;
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- #define ERROR 0
- #define OK 1
- //-----------------------------------------------
- sfr IAP_DATA = 0xC2; //IAP數據寄存器
- sfr IAP_ADDRH = 0xC3; //IAP地址寄存器高字節
- sfr IAP_ADDRL = 0xC4; //IAP地址寄存器低字節
- sfr IAP_CMD = 0xC5; //IAP命令寄存器
- sfr IAP_TRIG = 0xC6; //IAP命令觸發寄存器
- sfr IAP_CONTR = 0xC7; //IAP控制寄存器
- sbit Begin_LED = P1^0;
- sbit ERROR_LED = P1^3;
- sbit OK_LED = P1^7;
- #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位自動重載模式)作為波特率發生器
- sfr P0M1 = 0x93;
- sfr P0M0 = 0x94;
- sfr P1M1 = 0x91;
- sfr P1M0 = 0x92;
- sfr P2M1 = 0x95;
- sfr P2M0 = 0x96;
- sfr P3M1 = 0xb1;
- sfr P3M0 = 0xb2;
- sfr P4M1 = 0xb3;
- sfr P4M0 = 0xb4;
- sfr P5M1 = 0xC9;
- sfr P5M0 = 0xCA;
- sfr P6M1 = 0xCB;
- sfr P6M0 = 0xCC;
- sfr P7M1 = 0xE1;
- sfr P7M0 = 0xE2;
- sfr T2H = 0xd6; //定時器2高8位
- sfr T2L = 0xd7; //定時器2低8位
- sfr AUXR = 0x8e; //輔助寄存器
- //#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);
- #define display_Begin_LED() Begin_LED = 0
- #define off_Begin_LED() Begin_LED = 1
- #define display_OK_LED() OK_LED = 0
- #define off_OK_LED() OK_LED = 1
- #define display_ERROR_LED() ERROR_LED = 0
- #define off_ERROR_LED() ERROR_LED = 1
- //#define USED_BYTE_QTY_IN_ONE_SECTOR 1
- //#define USED_BYTE_QTY_IN_ONE_SECTOR 2
- //#define USED_BYTE_QTY_IN_ONE_SECTOR 4
- //#define USED_BYTE_QTY_IN_ONE_SECTOR 8
- //#define USED_BYTE_QTY_IN_ONE_SECTOR 16
- //#define USED_BYTE_QTY_IN_ONE_SECTOR 32
- //#define USED_BYTE_QTY_IN_ONE_SECTOR 64
- #define USED_BYTE_QTY_IN_ONE_SECTOR 128
- //#define USED_BYTE_QTY_IN_ONE_SECTOR 256
- //#define USED_BYTE_QTY_IN_ONE_SECTOR 512
- #define DEBUG_Data_Memory_Begin_Sector_addr 0x0400
- BYTE xdata protect_buffer[USED_BYTE_QTY_IN_ONE_SECTOR];
- /* 測試常量數組 */
- BYTE code Test_array_total[512] =
- {
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
- 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
- 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
- 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
- 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
- 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
- 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
- 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
- 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
- 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
- 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
- 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
- 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
- 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
- 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
- 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0,
- 0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe5,0xe4,0xe3,0xe2,0xe1,0xe0,
- 0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd0,
- 0xcf,0xce,0xcd,0xcc,0xcb,0xca,0xc9,0xc8,0xc7,0xc6,0xc5,0xc4,0xc3,0xc2,0xc1,0xc0,
- 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0,
- 0xaf,0xae,0xad,0xac,0xab,0xaa,0xa9,0xa8,0xa7,0xa6,0xa5,0xa4,0xa3,0xa2,0xa1,0xa0,
- 0x9f,0x9e,0x9d,0x9c,0x9b,0x9a,0x99,0x98,0x97,0x96,0x95,0x94,0x93,0x92,0x91,0x90,
- 0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x84,0x83,0x82,0x81,0x80,
- 0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x71,0x70,
- 0x6f,0x6e,0x6d,0x6c,0x6b,0x6a,0x69,0x68,0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x60,
- 0x5f,0x5e,0x5d,0x5c,0x5b,0x5a,0x59,0x58,0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50,
- 0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40,
- 0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x33,0x36,0x35,0x34,0x33,0x32,0x31,0x30,
- 0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,
- 0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,
- 0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00
- };
- void main()
- {
- P0M0 = 0x00;
- P0M1 = 0x00;
- P1M0 = 0x00;
- P1M1 = 0x00;
- P2M0 = 0x00;
- P2M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P4M0 = 0x00;
- P4M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
- P6M0 = 0x00;
- P6M1 = 0x00;
- P7M0 = 0x00;
- P7M1 = 0x00;
- InitUart();
-
- // if(sequential_write_flash_in_one_sector(DEBUG_Data_Memory_Begin_Sector_addr, USED_BYTE_QTY_IN_ONE_SECTOR, Test_array_total))
- // display_OK_LED();
- // else
- // display_ERROR_LED();
- 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))
- display_OK_LED();
- else
- display_ERROR_LED();
- 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();
- }
- /* 寫數據進 數據Flash存儲器, 只在同一個扇區內寫,不保留原有數據 */
- /* begin_addr,被寫數據Flash開始地址;counter,連續寫多少個字節; array[],數據來源 */
- BYTE sequential_write_flash_in_one_sector(WORD begin_addr, WORD counter, BYTE array[])
- {
- WORD i = 0;
- WORD in_sector_begin_addr = 0;
- WORD sector_addr = 0;
- /* 判是否是有效范圍,此函數不允許跨扇區操作 */
- if(counter > USED_BYTE_QTY_IN_ONE_SECTOR)
- return ERROR;
- in_sector_begin_addr = begin_addr & 0x01ff;
- if((in_sector_begin_addr + counter) > USED_BYTE_QTY_IN_ONE_SECTOR)
- return ERROR;
- /* 擦除 要修改/寫入 的扇區 */
- IapEraseSector(begin_addr);
- for(i=0; i<counter; i++)
- {
- /* 寫一個字節 */
- IapProgramByte(begin_addr, array[i]);
- /* 比較對錯 */
- if (SendData(IapReadByte(begin_addr)) != array[i])
- {
- IapIdle();
- return ERROR;
- }
- begin_addr++;
- }
- IapIdle();
- return OK;
- }
- /* 寫數據進數據Flash存儲器(EEPROM), 只在同一個扇區內寫,保留同一扇區中不需修改的數據 */
- /* begin_addr,被寫數據Flash開始地址;counter,連續寫多少個字節; array[],數據來源 */
- BYTE write_flash_with_protect_in_one_sector(WORD begin_addr, WORD counter, BYTE array[])
- {
- WORD i = 0;
- WORD in_sector_begin_addr = 0;
- WORD sector_addr = 0;
- WORD byte_addr = 0;
- /* 判是否是有效范圍,此函數不允許跨扇區操作 */
- if(counter > USED_BYTE_QTY_IN_ONE_SECTOR)
- return ERROR;
- in_sector_begin_addr = begin_addr & 0x01ff;
- /* 假定從扇區的第0個字節開始,到USED_BYTE_QTY_IN_ONE_SECTOR-1個字節結束,后面部分不用,程序易編寫 */
- if((in_sector_begin_addr + counter) > USED_BYTE_QTY_IN_ONE_SECTOR)
- return ERROR;
- /* 將該扇區數據 0 - (USED_BYTE_QTY_IN_ONE_SECTOR-1) 字節數據讀入緩沖區保護 */
- sector_addr = (begin_addr & 0xfe00);
- byte_addr = sector_addr;
- for(i = 0; i < USED_BYTE_QTY_IN_ONE_SECTOR; i++)
- {
- protect_buffer[i] = IapReadByte(byte_addr++);
- }
- /* 將要寫入的數據寫入保護緩沖區的相應區域,其余部分保留 */
- for(i = 0; i < counter; i++)
- {
- protect_buffer[in_sector_begin_addr++] = array[i];
- }
- /* 擦除 要修改/寫入 的扇區 */
- IapEraseSector(sector_addr);
- /* 將保護緩沖區的數據寫入 Data Flash, EEPROM */
- byte_addr = sector_addr;
- for(i = 0; i< USED_BYTE_QTY_IN_ONE_SECTOR; i++)
- {
- /* 寫一個字節 */
- IapProgramByte(byte_addr, protect_buffer[i]);
- /* 比較對錯 */
- if (SendData(IapReadByte(begin_addr)) != protect_buffer[i])
- {
- IapIdle();
- return ERROR;
- }
- byte_addr++;
- }
- IapIdle();
- return OK;
- }
- /*----------------------------
- 初始化串口
- ----------------------------*/
- 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;
- }
復制代碼 |