//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 过程 }