//STC 12C5A60S2系列單片機EEPROM/IAP 功能測試程序演示 #include "reg5 1.h" #include "intrins.h" typedef unsigned char BYTE; typedef unsigned int WORD; //IAP相關端口定義 sfr IAP_DATA = 0xC2; //Flash 數據寄存器 sfr IAP_ADDRH = 0xC3; //Flash 高位地址 sfr IAP_ADDRL = 0xC4; //Flash 低位地址 sfr IAP_CMD = 0xC5; //Flash 命令寄存器 sfr IAP_TRIG = 0xC6; //Flash 命令觸發 sfr IAP_CONTR = 0xC7; //Flash 控制寄存器 //IAP命令定義 #define CMD_IDLE 0 //待機 #define CMD_READ 1 //位-讀 #define CMD_WRITE 2 //位-程序 #define CMD_ERASE 3 //扇區-擦除 //IAP時間常數 //#define ENABLE_IAP 0x80 //如果系統時鐘<30MHz //#define ENABLE_IAP 0x81 //如果系統時鐘<24MHz //#define ENABLE_IAP 0x82 //如果系統時鐘<20MHz //#define ENABLE_IAP 0x83 //如果系統時鐘<12MHz //#define ENABLE_IAP 0x84 //如果系統時鐘<6MHz //#define ENABLE_IAP 0x85 //如果系統時鐘<3MHz //#define ENABLE_IAP 0x86 //如果系統時鐘<2MHz //#define ENABLE_IAP 0x87 //如果系統時鐘<1MHz #define IAP_ADDRESS 0x0000 //STC12C5A60S2 系列 EEPROM 起點地址 void Delay(unsigned char n); void IapIdle(); //保護 unsigned char IapReadByte(unsigned int addr); void IapWriteByte(unsigned int addr, unsigned char dat); void IapEraseSector(unsigned int addr); //擦除扇區 void main() { unsigned int i; //unsigned int i P1 = 0xfe; // 1111 ,1110 系統復位 OK Delay(10); //延時 IapEraseSector(IAP_ADDRESS); //擦除扇區(60s2兩個扇區) for (i=0; i<512; i++) //校驗全部扇區數據是否是0xFF { if (IapReadByte(IAP_ADDRESS+i) != 0xff) goto Error; //如果錯誤, break } P1 = 0xfc; // 1111 ,11 00 P1指示擦除完成 Delay(10); //延時 for (i=0; i<512; i++) //Program 512 字節數據 into data flash { IapWriteByte(IAP_ADDRESS+i, (unsigned char)i); } P1 = 0xf8; // 1111 ,1000 P1指示程序完成 Delay(10); //延時 for (i=0; i<512; i++) //確認 512 字節數據 { if (IapReadByte(IAP_ADDRESS+i) != (unsigned char)i) goto Error; //如果錯誤, break } P1 = 0xf0; // 1111 ,0000 確認完成 while ( 1); Error: P1 &= 0x7f; //0xxx,xxxx IAP 操作失敗 while ( 1); } /*----------------------------Software delay function----------------------------*/ void Delay(unsigned char n) { unsigned int x; while (n--) { x = 0; while (++x); } } /********************************************************** ** 函數名稱: void IapIdle(); ** 功能描述: 退出IAP功能 **********************************************************/ void IapIdle() { IAP_CONTR = 0; //關閉 IAP 功能 IAP_CMD = 0; //清除命令寄存器進入待機模式 IAP_TRIG = 0; //清除觸發寄存器 IAP_ADDRH = 0xFF; //IAP指針移動到非 EEPROM 區域 IAP_ADDRL = 0xFF; } /********************************************************** ** 函數名稱: unsigned char IapReadByte(unsigned int addr); ** 功能描述: 讀EEPROM ** 輸 入: unsigned int addr 地址 ** 輸 出: unsigned char dat 數據 **********************************************************/ unsigned char IapReadByte(unsigned int addr) { unsigned char dat; //數據緩沖 IAP_CONTR = ENABLE_IAP; //打開 IAP 過程, 并設置等待時間 IAP_CMD = CMD_READ; //設置 ISP/IAP/EEPROM 為讀命令 IAP_ADDRL = addr; //設置 ISP/IAP/EEPROM 低位地址 IAP_ADDRH = addr >> 8; //設置 ISP/IAP/EEPROM 高位地址 IAP_TRIG = 0x5a; //發送觸發命令 1 (0x5a) IAP_TRIG = 0xa5; //發送觸發命令 2 (0xa5) _nop_(); //MCU 延遲等待 ISP/IAP/EEPROM 作業完成 _nop_(); //兼容15F104E一個bug,NOP3次 _nop_(); // dat = IAP_DATA; //讀取 ISP/IAP/EEPROM 數據 IapIdle(); //關閉 ISP/IAP/EEPROM 過程 return dat; //返回 Flash 數據 } /********************************************************** ** 函數名稱: void IapWriteByte(unsigned int addr, unsigned char dat); ** 功能描述: 寫EEPROM扇區 ** 輸 入: unsigned int addr 寫地址 unsigned char dat 寫數據 **********************************************************/ void IapWriteByte(unsigned int addr, unsigned char dat) { IAP_CONTR = ENABLE_IAP; //打開 IAP 過程, 并設置等待時間 IAP_CMD = CMD_WRITE; //設置 ISP/IAP/EEPROM 為寫命令 IAP_ADDRL = addr; //設置 ISP/IAP/EEPROM 低位地址 IAP_ADDRH = addr >> 8; //設置 ISP/IAP/EEPROM 高位地址 IAP_DATA = dat; //寫 ISP/IAP/EEPROM 數據 IAP_TRIG = 0x5a; //發送觸發命令 1 (0x5a) IAP_TRIG = 0xa5; //發送觸發命令 2 (0xa5) _nop_(); //MCU 延遲等待 ISP/IAP/EEPROM 作業完成 _nop_(); //兼容15F104E一個bug,NOP3次 _nop_(); // IapIdle(); //關閉 ISP/IAP/EEPROM 過程 } /********************************************************** ** 函數名稱: void IapEraseSector(unsigned int addr); ** 功能描述: 擦除EEPROM扇區 ** 輸 入: unsigned int addr 擦除地址 **********************************************************/ void IapEraseSector(unsigned int addr) { IAP_CONTR = ENABLE_IAP; //打開 IAP 過程, 并設置等待時間 IAP_CMD = CMD_ERASE; //設置 ISP/IAP/EEPROM 為擦除命令 IAP_ADDRL = addr; //設置 ISP/IAP/EEPROM 低位地址 IAP_ADDRH = addr >> 8; //設置 ISP/IAP/EEPROM 高位地址 IAP_TRIG = 0x5a; //發送觸發命令 1 (0x5a) IAP_TRIG = 0xa5; //發送觸發命令 2 (0xa5) _nop_(); //MCU 延遲等待 ISP/IAP/EEPROM 作業完成 _nop_(); //兼容15F104E一個bug,NOP3次 _nop_(); // IapIdle(); //關閉 ISP/IAP/EEPROM 過程 }