您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 单片机EEPROM读写程序
/*STC89C54RD+的flash空间从0x4000~0xf3ff共90个扇区,每扇区512字节*///#defineBaseAddr0x1000/*51rc*///#defineEndSectoraddr0x3d00/*51rc*///#defineEndAddr0x3fff/*51rc12Keeprom*/#defineBaseAddr0x4000#defineEndSectoraddr0xf200#defineEndAddr0xf3ff#defineUseAddr0x1000/*-------------定义扇区大小-------------*/#definePerSector512/*用户程序需要记忆的数组,用户实际使用了n-1个数据,数组长度规整到248163264上*/ucharTtotal[16]={0x55,/*作为判别引导头使用,用户程序请不要修改它*//*用户保存记忆的数据*/0x01,/*用途说明....*/0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,};uinttimerForDelay,/*专供延时用的变量*/i,/*循环变量*/EepromPtr;/*eeprom读写指针*//*---------------命令定义---------------*/#defineRdCommand0x01/*字节读*/#definePrgCommand0x02/*字节写*/#defineEraseCommand0x03/*扇区擦除*//*定义常量*/#defineError1#defineOk0/*定义Flash对应于20MHz晶振系统的操作等待时间*//*时钟倍频时WaitTime用0x00*/#defineWaitTime0x01/*================打开ISP,IAP功能=================*/voidISP_IAP_enable(void){EA=0;/*关中断*/ISP_CONTR=ISP_CONTR&0x18;/*0001,1000*/ISP_CONTR=ISP_CONTR|WaitTime;/*写入硬件延时*/ISP_CONTR=ISP_CONTR|0x80;/*ISPEN=1*/}/*===============关闭ISP,IAP功能==================*/voidISP_IAP_disable(void){ISP_CONTR=ISP_CONTR&0x7f;/*ISPEN=0*/ISP_TRIG=0x00;EA=1;/*开中断*/}/*================公用的触发代码====================*/voidISPgoon(void){ISP_IAP_enable();/*打开ISP,IAP功能*/ISP_TRIG=0x46;/*触发ISP_IAP命令字节1*/ISP_TRIG=0xb9;/*触发ISP_IAP命令字节2*/_nop_();}/*====================字节读========================*/ucharbyte_read(uintbyte_addr){ISP_ADDRH=(uchar)(byte_addr8);/*地址赋值*/ISP_ADDRL=(uchar)(byte_addr&0x00ff);ISP_CMD=ISP_CMD&0xf8;/*清除低3位*/ISP_CMD=ISP_CMD|RdCommand;/*写入读命令*/ISPgoon();/*触发执行*/ISP_IAP_disable();/*关闭ISP,IAP功能*/return(ISP_DATA);/*返回读到的数据*/}/*==================扇区擦除========================*/voidSectorErase(uintsector_addr){uintiSectorAddr;iSectorAddr=(sector_addr&0xfe00);/*取扇区地址*/ISP_ADDRH=(uchar)(iSectorAddr8);ISP_ADDRL=0x00;ISP_CMD=ISP_CMD&0xf8;/*清空低3位*/ISP_CMD=ISP_CMD|EraseCommand;/*擦除命令3*/ISPgoon();/*触发执行*/ISP_IAP_disable();/*关闭ISP,IAP功能*/}/*====================字节写========================*/voidbyte_write(uintbyte_addr,ucharoriginal_data){ISP_ADDRH=(uchar)(byte_addr8);/*取地址*/ISP_ADDRL=(uchar)(byte_addr&0x00ff);ISP_CMD=ISP_CMD&0xf8;/*清低3位*/ISP_CMD=ISP_CMD|PrgCommand;/*写命令2*/ISP_DATA=original_data;/*写入数据准备*/ISPgoon();/*触发执行*/ISP_IAP_disable();/*关闭IAP功能*/}/*===================字节写并校验===================*/ucharbyte_write_verify(uintbyte_addr,ucharoriginal_data){ISP_ADDRH=(uchar)(byte_addr8);/*取地址*/ISP_ADDRL=(uchar)(byte_addr&0xff);ISP_CMD=ISP_CMD&0xf8;/*清低3位*/ISP_CMD=ISP_CMD|PrgCommand;/*写命令2*/ISP_DATA=original_data;ISPgoon();/*触发执行*//*开始读,没有在此重复给地址,地址不会被自动改变*/ISP_DATA=0x00;/*清数据传递寄存器*/ISP_CMD=ISP_CMD&0xf8;/*清低3位*/ISP_CMD=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){/*读写数据校验*/returnOk;/*返回校验结果*/}else{returnError;}}/*=====================数组写入=====================*/ucharArrayWrite(uintbegin_addr,uintlen,uchar*array){uinti;uintin_addr;/*判是否是有效范围,此函数不允许跨扇区操作*/if(lenPerSector){returnError;}in_addr=begin_addr&0x01ff;/*扇区内偏移量*/if((in_addr+len)PerSector){returnError;}in_addr=begin_addr;/*逐个写入并校对*/ISP_IAP_enable();/*打开IAP功能*/for(i=0;ilen;i++){/*写一个字节*/ISP_ADDRH=(uchar)(in_addr8);ISP_ADDRL=(uchar)(in_addr&0x00ff);ISP_DATA=array[i];/*取数据*/ISP_CMD=ISP_CMD&0xf8;/*清低3位*/ISP_CMD=ISP_CMD|PrgCommand;/*写命令2*/ISP_TRIG=0x46;/*触发ISP_IAP命令字节1*/ISP_TRIG=0xb9;/*触发ISP_IAP命令字节2*/_nop_();/*读回来*/ISP_DATA=0x00;ISP_CMD=ISP_CMD&0xf8;/*清低3位*/ISP_CMD=ISP_CMD|RdCommand;/*读命令1*/ISP_TRIG=0x46;/*触发ISP_IAP命令字节1*/ISP_TRIG=0xb9;/*触发ISP_IAP命令字节2*/_nop_();/*比较对错*/if(ISP_DATA!=array[i]){ISP_IAP_disable();returnError;}in_addr++;/*指向下一个字节*/}ISP_IAP_disable();returnOk;}/*=========================扇区读出=========================*//*程序对地址没有作有效性判断,请调用方事先保证他在规定范围内*/voidArrayRead(uintbegin_addr,ucharlen){//ucharxdatadata_buffer[];/*整个扇区读取缓存区*/uintiSectorAddr;uinti;iSectorAddr=begin_addr;//&0xfe00;/*取扇区地址*/ISP_IAP_enable();for(i=0;ilen;i++){ISP_ADDRH=(uchar)(iSectorAddr8);ISP_ADDRL=(uchar)(iSectorAddr&0x00ff);ISP_CMD=ISP_CMD&0xf8;/*清低3位*/ISP_CMD=ISP_CMD|RdCommand;/*读命令1*/ISP_DATA=0;ISP_TRIG=0x46;/*触发ISP_IAP命令字节1*/ISP_TRIG=0xb9;/*触发ISP_IAP命令字节2*/_nop_();Ttotal[i]=ISP_DATA;iSectorAddr++;}ISP_IAP_disable();/*关闭IAP功能*/}/*==============================================================从eeprom中读取数据==============================================================*/voidDataRestore(){EepromPtr=BaseAddr;/*指向eeprom的起始点*/while(EepromPtrEndAddr)/*在eeprom的可用区域内*/{if(byte_read(EepromPtr)==0x55)/*找到了上一次有效纪录*/{break;/*寻找完成*/}EepromPtr+=0x10;/*指向下一个小区*/}if(EepromPtr=EndAddr)/*如果照遍都没有,是新片*/{EepromPtr=BaseAddr;/*指向eeprom的起始点*/for(i=0;i90;i++){SectorErase(EepromPtr+0x200*i);/*全部扇区擦除*/}while(ArrayWrite(EepromPtr,0x10,Ttotal))/*写默认值*/{/*写入失败才运行的部分*/byte_write(EepromPtr,0);/*该单元已经失效*/if(EepromPtrEndAddr){EepromPtr+=0x10;/*换一块新的小区*/}else{P1=0;/*指示芯片内eeprom全坏*/EA=0;/*不再做任何事*/while(1);/*死机*/}}}ArrayRead(EepromPtr,16);}/*==============================================================将需要记忆的数据保存到eeprom==========================================
本文标题:单片机EEPROM读写程序
链接地址:https://www.777doc.com/doc-4436281 .html