ISPEN:ISP/IAP功能允许位。
0:禁止ISP/IAP编程改变Flash,1:允许编程改变FlashSWBS:软件选择从用户主程序区启动(0),还是从ISP程序区启动(1)。
SWRST:0:不操作,1:产生软件系统复位,硬件自动清零。
ISP_CONTR中的SWBS与SWRST这两个功能位,可以实现单片机的软件启动,并启动到ISP区或用户程序区,这在“STC单片机自动下载”一节,亦有所应用。
如:ISP_CONTR=0x60; 则可以实现从用户应用程序区软件复位到ISP程序区开始运行程序。
ISP_CONTR=0x20; 则可以实现从ISP程序区软件复位到用户应用程序区开始运行程序。
(以上的建议时钟是(WT2、WT1、WT0)取不同的值时的标称时钟,用户系统中的时钟不要过高,否则可能使操作不稳定。
)以下是具体的实现代码:EEPROM操作函数:#define RdCommand 0x01#define PrgCommand 0x02#define EraseCommand 0x03#define Error 1#define Ok 0#define WaitTime 0x01#define PerSector 512unsigned char xdata Ttotal[512];/*---------------------------------------------------------------------打开 ISP,IAP 功能---------------------------------------------------------------------*/void ISP_IAP_enable(void){EA=0;/* 关中断*/ISP_CONTR|=0x18;/*0001,1000*/ISP_CONTR|=WaitTime;/*写入硬件延时*/ISP_CONTR|=0x80;/*ISPEN=1*/}/*---------------------------------------------------------------------关闭 ISP,IAP 功能---------------------------------------------------------------------*/void ISP_IAP_disable(void){ISP_CONTR&=0x7f;/* ISPEN = 0 */ISP_TRIG=0x00;EA=1;/* 开中断 */}/*----------------------------------------------------------------------公用的触发代码----------------------------------------------------------------------*/void ISPgoon(void){ISP_IAP_enable();/* 打开 ISP,IAP 功能 */ISP_TRIG=0x46;/* 触发ISP_IAP命令字节1 */ISP_TRIG=0xb9;/* 触发ISP_IAP命令字节2 */_nop_();}/*-----------------------------------------------------------------------字节读-----------------------------------------------------------------------*/unsigned char byte_read(unsigned int byte_addr){ISP_ADDRH=(unsigned char)(byte_addr>>8); /* 地址赋值*/ ISP_ADDRL=(unsigned char)(byte_addr&0x00ff);ISP_CMD&=0xf8; /* 清除低3位 */ISP_CMD|=RdCommand;/* 写入读命令*/ISPgoon();/* 触发执行*/ISP_IAP_disable();/* 关闭ISP,IAP功能*/return ISP_DATA;/* 返回读到的数据*/}/*------------------------------------------------------------------------扇区擦除------------------------------------------------------------------------*/void sectorerase(unsigned int sector_addr){unsigned int iSectorAddr;iSectorAddr=(sector_addr&0xfe00);/* 取扇区地址*/ISP_ADDRH=(unsigned char)(iSectorAddr>>8);ISP_ADDRL=0x00;ISP_CMD&=0xf8;/* 清空低3位*/ISP_CMD|=EraseCommand;/* 擦除命令3*/ISPgoon();/* 触发执行 */ISP_IAP_disable();/* 关闭ISP,IAP功能*/}/*-------------------------------------------------------------------------------------字节写-------------------------------------------------------------------------------------*/void byte_write(unsigned int byte_addr, unsigned char original_data){ISP_ADDRH=(unsigned char)(byte_addr>>8); /* 取地址*/ISP_ADDRL=(unsigned char)(byte_addr & 0x00ff);ISP_CMD&=0xf8;/* 清低3位*/ISP_CMD|=PrgCommand;/* 写命令2*/ISP_DATA=original_data;/* 写入数据准备*/ISPgoon();/* 触发执行*/ISP_IAP_disable();/* 关闭IAP功能*/}/*-----------------------------------------------------------------字节写并校验-----------------------------------------------------------------*/unsigned char byte_write_verify(unsigned int byte_addr, unsigned char original_data){ISP_ADDRH=(unsigned char)(byte_addr>>8); /* 取地址*/ISP_ADDRL=(unsigned char)(byte_addr&0xff);ISP_CMD&=0xf8;/* 清低3位*/ISP_CMD|=PrgCommand;/* 写命令2*/ISP_DATA=original_data;ISPgoon();/* 触发执行*//* 开始读,没有在此重复给地址,地址不会被自动改变*/ISP_DATA=0x00;/* 清数据传递寄存器*/ISP_CMD&=0xf8;/* 清低3位*/ISP_CMD|=RdCommand;/* 读命令1*/ISP_TRIG=0x46;/* 触发ISP_IAP命令字节1 */ISP_TRIG=0xb9;/* 触发ISP_IAP命令字节2 */_nop_();/* 延时*/ISP_IAP_disable();/* 关闭IAP功能*/if(ISP_DATA==original_data)/* 读写数据校验*/return Ok;/* 返回校验结果*/elsereturn Error;}/*--------------------------------------------------------------------------数组写入--------------------------------------------------------------------------*/unsigned char arraywrite(unsigned int begin_addr, unsigned int len, unsigned char *array){unsigned int i;unsigned int in_addr;/* 判是否是有效范围,此函数不允许跨扇区操作 */if(len > PerSector)return Error;in_addr = begin_addr & 0x01ff;/* 扇区内偏移量 */if((in_addr+len)>PerSector)return Error;in_addr = begin_addr;/* 逐个写入并校对 */ISP_IAP_enable();/* 打开IAP功能 */for(i=0;i<len;i++){/* 写一个字节 */ISP_ADDRH=(unsigned char)(in_addr >> 8);ISP_ADDRL=(unsigned char)(in_addr & 0x00ff);ISP_DATA=array; /* 取数据 */ISP_CMD&=0xf8;/* 清低3位 */ISP_CMD|=PrgCommand;/* 写命令2 */ISP_TRIG=0x46;/* 触发ISP_IAP命令字节1 */ISP_TRIG=0xb9;/* 触发ISP_IAP命令字节2 */_nop_();/* 读回来 */ISP_DATA=0x00;ISP_CMD&=0xf8;/* 清低3位*/ISP_CMD|=RdCommand;/* 读命令1*/ISP_TRIG=0x46;/* 触发ISP_IAP命令字节1 */ISP_TRIG=0xb9;/* 触发ISP_IAP命令字节2 */_nop_();/* 比较对错 */if(ISP_DATA!=array){ISP_IAP_disable();return Error;}in_addr++;/* 指向下一个字节*/}ISP_IAP_disable();return Ok;}/*----------------------------------------------------------------------------- 扇区读出----------------------------------------------------------------------------- *//* 程序对地址没有作有效性判断,请调用前事先保证他在规定范围内 */ void arrayread(unsigned int begin_addr, unsigned char len){unsigned int iSectorAddr;unsigned int i;iSectorAddr = begin_addr; // & 0xfe00; /* 取扇区地址*/ISP_IAP_enable();for(i=0;i<len;i++){ISP_ADDRH=(unsigned char)(iSectorAddr>>8);ISP_ADDRL=(unsigned char)(iSectorAddr & 0x00ff);ISP_CMD&=0xf8;/* 清低3位*/ISP_CMD|=RdCommand;/* 读命令1*/ISP_DATA=0;ISP_TRIG=0x46;/* 触发ISP_IAP命令字节1 */ISP_TRIG=0xb9;/* 触发ISP_IAP命令字节2 */_nop_();Ttotal=ISP_DATA;iSectorAddr++;}ISP_IAP_disable();/* 关闭IAP功能*/}主函数对EEPROM操作函数进行调用:#include <stc51rd.h>#include <intrins.h>#include <stc_eeprom.h>#include <ados.h>int i;void delay(unsigned int time){while(time--);}void main(){_ADOS(22.1184);//ADOS自动下载//for(i=0;i<100;i++)//{//Ttotal=i;//}//arraywrite(0x8000,100,Ttotal);/*第一次运行时向EEPROM中写入数据然后再将写入函数注释掉,将先前写入的数据读出,输出在P2口上。