STC单片机EEPROM读写程序
- 格式:doc
- 大小:51.50 KB
- 文档页数:7
stc单片机eeprom读写程序以下是STC单片机使用EEPROM进行读写的示例程序:#include <reg52.h>#include <intrins.h>#define EEPROM_ADDR 0xA0 // EEPROM的I2C地址sbit SDA = P2^0; // I2C的数据线sbit SCL = P2^1; // I2C的时钟线// I2C开始信号void I2C_Start(){SDA = 1;_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间SDA = 0;_nop_(); // 延时一段时间SCL = 0;_nop_(); // 延时一段时间}// I2C停止信号void I2C_Stop(){SDA = 0;_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间SDA = 1;_nop_(); // 延时一段时间}// I2C发送一个字节的数据void I2C_SendByte(unsigned char dat){unsigned char i;for (i = 0; i < 8; i++){SDA = dat & 0x80; // 获取最高位dat <<= 1;_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间SCL = 0;_nop_(); // 延时一段时间}SDA = 1;_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间SCL = 0;_nop_(); // 延时一段时间}// I2C接收一个字节的数据unsigned char I2C_ReceiveByte(){unsigned char i, dat = 0;SDA = 1;for (i = 0; i < 8; i++){_nop_(); // 延时一段时间SCL = 1;_nop_(); // 延时一段时间dat <<= 1;dat |= SDA;SCL = 0;}return dat;}// 在EEPROM中写入一个字节的数据void EEPROM_WriteByte(unsigned char addr, unsigned char dat) {I2C_Start();I2C_SendByte(EEPROM_ADDR | 0); // 发送写入指令I2C_SendByte(addr); // 发送地址I2C_SendByte(dat); // 发送数据I2C_Stop();}// 从EEPROM中读取一个字节的数据unsigned char EEPROM_ReadByte(unsigned char addr){unsigned char dat;I2C_Start();I2C_SendByte(EEPROM_ADDR | 0); // 发送写入指令 I2C_SendByte(addr); // 发送地址I2C_Start();I2C_SendByte(EEPROM_ADDR | 1); // 发送读取指令 dat = I2C_ReceiveByte(); // 读取数据I2C_Stop();return dat;}。
eeprom读写程序详解EEPROM(Electrically Erasable Programmable Read-Only Memory) 是一种可编程只读存储器,可以在电信号的作用下进行擦写和改写。
它通常用于存储单片机或其他嵌入式系统中的数据、设置参数、配置文件等。
对于 EEPROM 的读写程序,需要考虑以下几个方面:1. 读操作:读操作通常包括以下步骤:- 等待上次读操作完成。
- 获取要读取的数据的单元地址。
- 将 EEPGD 位和 CFGS 位清零。
- 启动读操作控制位 RD。
- 等待本次读操作完成。
- 将该单元地址中对应的数据返回。
在读取 EEPROM 数据时,为了避免芯片在一瞬间无法获取到数据,需要给芯片一定的时间来稳定获取数据。
因此,在读取操作中需要加入等待步骤。
2. 写操作:写操作通常包括以下步骤:- 等待上次写操作完成。
- 获取要写的数据的单元地址。
- 将要写的数据写入 EEPROM 的单元中。
- 将 EEPGD 位和 CFGS 位清零。
- 启动写操作控制位 WP。
- 等待写操作完成。
在写操作中,为了确保数据的可靠性,需要将要写的数据写入EEPROM 的单元中,并等待写操作完成。
同时,在写操作过程中,需要注意避免对无关的单元进行写操作,以免损坏 EEPROM 芯片。
3. 中断处理:在 EEPROM 的读写操作中,通常需要加入中断处理机制,以便在读写过程中及时响应和处理异常情况。
例如,在读取 EEPROM 数据时,如果 EEPROM 芯片出现故障,可能会导致读取失败。
为了避免这种情况,可以在读取操作中加入中断处理机制,在读取失败时及时报警或采取相应的应对措施。
总之,EEPROM 读写程序的实现需要考虑多个方面的因素,包括读操作、写操作、中断处理等。
同时,需要考虑 EEPROM 芯片的特性和限制,以便实现高效、稳定、可靠的 EEPROM 读写操作。
dzjk2010-11-14 09:58貌似使用STC单片机内部EEPROM有一定的局限wieke982010-11-14 10:41 要分块的,如果两个字节是同时写入的可以放在一个块里,如果不是要放在两个块里!fang32010-11-14 13:11MOV DPTR,#2000H;指针指向第一扇区EEPROMW:;写MOV ISP_CONTR,#1;设置等等待时间ORL ISP_CONTR,#80h;允许ISP/IAP操作MOV ISP_CMD,#02H ;送写命令MOV ISP_ADDRH,DPH ;送高地址MOV ISP_ADDRL,DPL ;送低地址MOV ISP_DATA,A ;A是要写入的数据ACALL ISPXX ;触发RET上面的只是写一个字节A而已wieke982010-11-14 14:33EEPROMW:;写MOV R1,#30H;30h和31H是要写的数据MOV R3,#2;要写的字节数FGRW:MOV ISP_CONTR,#1;设置等等待时间ORL ISP_CONTR,#80h;允许ISP/IAP操作MOV ISP_CMD,#02H ;送写命令MOV ISP_ADDRH,DPH ;送高地址MOV ISP_ADDRL,DPL ;送低地址MOV A,@R1;将要写的数据传入累加器MOV ISP_DATA,A ;A是要写入的数据ACALL ISPXX ;触发INC DPTRINC R1DJNZ R3,FGRW;是否写完,没写继续fang32010-11-14 21:18FGRW:MOV ISP_CONTR,#1;设置等等待时间ORL ISP_CONTR,#80h;允许ISP/IAP操作MOV ISP_CMD,#02H ;送写命令MOV ISP_ADDRH,DPH ;送高地址MOV ISP_ADDRL,DPL ;送低地址MOV A,@R1;将要写的数据传入累加器MOV ISP_DATA,A ;A是要写入的数据ACALL ISPXX ;触发因为说扇区是空的才能写还是搞不明白,如果写完一个字节,那么这个扇区已经不是空的了,还能写第二个字节吗wieke982010-11-15 10:30所谓空就是是0FFH,在擦除之后就是0FFH都可以写入了!fang32010-11-15 22:35 哦,有点明白了,,,就是说,在一个扇区里,只要是空的单元就可以写入,谢谢哪么,你说的要分块的,如果两个字节是同时写入的可以放在一个块里,如果不是要放在两个块里!怎么解释?wieke982010-11-16 08:19因为是整块擦除的,每一块中的每一个字节只能写入一次第二次要写入就必须重新擦除,一擦除整块的数据都会被擦除,所以不是同时修改的数据要放在不同的块中。
STC单片机EEPROM的应用和程序STC单片机EEPROM的应用和程序(2009-04-22 21:58:34)转载▼标签:杂谈分类:Program最近,由于工作的需要,用STC89C52来开发新产品,要用天STC的Eeprom的功能,上网也找了一点资料,得到很大帮助,真的非常感谢。
程序是我在网上摘录的,调试通过了,不过我产品在用动态扫描显示的,由于在Eeprom擦除时要用几十毫秒,会有一闪烁的。
不过这是正常的。
单片机运行时的数据都存在于RAM(随机存储器)中,在掉电后RAM 中的数据是无法保留的,那么怎样使数据在掉电后不丢失呢?这就需要使用EEPROM 或FLASHROM 等存储器来实现。
在传统的单片机系统中,一般是在片外扩展存储器,单片机与存储器之间通过IIC 或SPI 等接口来进行数据通信。
这样不光会增加开发成本,同时在程序开发上也要花更多的心思。
在STC 单片机中内置了EEPROM(其实是采用IAP 技术读写内部FLASH 来实现EEPROM),这样就节省了片外资源,使用起来也更加方便。
下面就详细介绍STC 单片机内置EEPROM 及其使用方法。
STC 各型号单片机内置的EEPROM 的容量各有不同,见下表:(内部EEPROM 可以擦写100000 次以上)上面提到了IAP,它的意思是"在应用编程",即在程序运行时程序存储器可由程序自身进行擦写。
正是是因为有了IAP,从而可以使单片机可以将数据写入到程序存储器中,使得数据如同烧入的程序一样,掉电不丢失。
当然写入数据的区域与程序存储区要分开来,以使程序不会遭到破坏。
要使用IAP 功能,与以下几个特殊功能寄存器相关:ISP_DATA:ISP/IAP 操作时的数据寄存器。
ISP/IAP 从Flash 读出的数据放在此处,向Flash 写的数据也需放在此处ISP_ADDRH:ISP/IAP 操作时的地址寄存器高八位。
ISP_ADDRL:ISP/IAP 操作时的地址寄存器低八位。
STC89C52单片机内部EEPROM保存数据的应用例子程序STC89C51、52内部都自带有2K字节的EEPROM,54、55和58都自带有16K字节的EEPROM,STC单片机是利用IAP技术实现的EEPROM,内部Flash擦写次数可达100,000 次以上,先来介绍下ISP与IAP的区别和特点。
知识点:ISP与IAP介绍ISP:In System Programable 是指在系统编程,通俗的讲,就是片子已经焊板子上,不用取下,就可以简单而方便地对其进行编程。
比如我们通过电脑给STC单片机下载程序,或给AT89S51单片机下载程序,这就是利用了ISP技术。
IAP:In Application Programable 是指在应用编程,就是片子提供一系列的机制(硬件/软件上的)当片子在运行程序的时候可以提供一种改变flash数据的方法。
通俗点讲,也就是说程序自己可以往程序存储器里写数据或修改程序。
这种方式的典型应用就是用一小段代码来实现程序的下载,实际上单片机的ISP功能就是通过IAP技术来实现的,即片子在出厂前就已经有一段小的boot程序在里面,片子上电后,开始运行这段程序,当检测到上位机有下载要求时,便和上位机通信,然后下载数据到存储区。
大家要注意千万不要尝试去擦除这段ISP引导程序,否则恐怕以后再也下载不了程序了。
STC单片机内部有几个专门的特殊功能寄存器负责管理ISP/IAP功能的,见表1。
每个扇区为512字节,建议大家在写程序时,将同一次修改的数据放在同一个扇区,方便修改,因为在执行擦除命令时,一次最少要擦除一个扇区的数据,每次在更新数据前都必须要擦除原数据方可重新写入新数据,不能直接在原来数据基础上更新内容。
下面通过一个例子来讲解STC系列单片机EEPROM的具体用法。
【例】:在TX-1C实验板上实现如下描述,操作STC单片机自带的EEPROM,存储一组按秒递增的二位数据,并且将数据实时显示在数码管上,数据每变化一次就往EEPROM中写入一次,当关闭实验板电源,再次开启电源时,从EEPROM中读取先前存储的数据,接着递增显示。
STC单片机EEPROM读写程序在单片机中,EEPROM(Electrically Erasable Programmable Read-Only Memory)是一种非易失性存储器,可以用于存储数据,即使在断电情况下,数据也会被保留。
因此,掌握STC单片机的EEPROM读写程序对于开发嵌入式系统非常重要。
一、EEPROM简介EEPROM是一种可重复擦写的存储器,可用于存储小量数据。
与Flash存储器相比,EEPROM具有更快的写入和擦除速度。
在STC单片机中,EEPROM的存储容量通常较小,一般在几个字节到几千字节之间。
二、EEPROM读操作在STC单片机中,进行EEPROM读操作需要按照以下步骤进行:1. 初始化I2C总线:STC单片机使用I2C总线进行EEPROM读写操作,因此需要先初始化I2C总线。
通过设置相关寄存器,设置I2C 总线的速度和地址。
2. 发送设备地址:确定要读取的EEPROM设备的地址,并发送到I2C总线。
3. 发送寄存器地址:确定要读取的EEPROM寄存器地址,并将其发送到I2C总线。
4. 发送读命令:向EEPROM发送读命令,以启动读操作。
5. 读取数据:从EEPROM中读取数据,并保存到变量中。
6. 结束读操作:完成读操作后,关闭I2C总线。
三、EEPROM写操作类似于读操作,进行EEPROM写操作也需要按照一定的步骤进行:1. 初始化I2C总线:同样地,首先需要初始化I2C总线。
2. 发送设备地址:确定要写入的EEPROM设备的地址,并发送到I2C总线。
3. 发送寄存器地址:确定要写入的EEPROM寄存器地址,并将其发送到I2C总线。
4. 发送写命令:向EEPROM发送写命令,以启动写操作。
5. 写入数据:将要写入EEPROM的数据发送到I2C总线。
6. 结束写操作:完成写操作后,关闭I2C总线。
四、注意事项在进行EEPROM读写操作时,需要注意以下几点:1. 确保正确的设备地址:要与EEPROM的地址匹配,否则无法进行有效的读写操作。
stc89le52rc内部EEPROM的C51读写程序/*stc89le52rc内部EEPROM的C51读写程序串口命令(9600)1.0x35可以写eeprom第一个字节数据0x0c2.0x34可以使用检查eeprom第一个字节的数据,正确就会反馈一串字符3.0x33可以读取eeprom前256个字节数据*/#include<math.h>#include<stdio.h>#include<reg52.h>#include <intrins.h>#define NOP5 _nop_();_nop_();_nop_(); _nop_();_nop_();#define uchar unsigned char#define uint unsigned intsfr AUXR = 0x8e;sfr AUXR1 = 0xa2;sfr P4 = 0xe8;sfr XICON = 0xc0;sfr IPH = 0xb7;sfr WDT_CONTR = 0xe1;sfr ISP_DATA = 0xe2;sfr ISP_ADDRH = 0xe3;sfr ISP_ADDRL = 0xe4;sfr ISP_CMD = 0xe5;sfr ISP_TRIG = 0xe6;sfr ISP_CONTR = 0xe7;#define ENABLE_ISP 0x81 //小于20MHZ使用#define DATA_FLASH_START_ADDR 0x2000//stc89le52rc eeprom起始地址#define TEST_CODE 0x34uchar code start_string[]={"EEPROM first data correct!\n"}; uint i=0,k;uchar EEPROM_READ(uint flash_addres);void IAP_disable();void EEPROM_FORMAT(uint flash_addres);void EEPROM_WRITE(uint flash_addres, isp_data);void test_read();void send_byte(uchar bt);void send_string(uchar *ptr, uchar len);void read_string(uint start_addr,uint num);void read_string(uint start_addr, uint num)static uint j,temp;for(j=0;j<num;j++){temp=EEPROM_READ(start_addr+j);NOP5;send_byte(temp);}}void send_string(uchar * ptr, uchar len) {static uint j;for(j=0;j<len;j++){send_byte(*(ptr+j));}}void send_byte(uchar by){SBUF=by;while(!TI);TI=0;void IAP_disable(){ISP_CONTR=0;ISP_CMD=0;ISP_TRIG=0;}uchar EEPROM_READ(uint flash_addres) //读取数据{uchar read;ISP_ADDRH=flash_addres>>8;ISP_ADDRL=flash_addres;ISP_CONTR=ENABLE_ISP;ISP_CMD=0x01 ;EA=0;ISP_TRIG=0x46;ISP_TRIG=0xb9 ;NOP5;read=ISP_DATA;IAP_disable();EA=1;return(ISP_DATA);void EEPROM_WRITE(uint flash_addres,isp_data) //写入数据{ISP_ADDRH=flash_addres>>8;ISP_ADDRL=flash_addres;ISP_CONTR=ENABLE_ISP;ISP_CMD=0x02 ;EA=0;ISP_DATA=isp_data;ISP_TRIG=0x46;ISP_TRIG=0xb9;IAP_disable();EA=1;}void EEPROM_FORMAT(uint flash_addres) //擦除{ISP_ADDRH=flash_addres>>8;ISP_ADDRL=flash_addres;ISP_CONTR=ENABLE_ISP;ISP_CMD=0x03;EA=0;ISP_TRIG=0x46;ISP_TRIG=0xb9;IAP_disable();EA=1;}void test_read(){if(RI){RI=0;switch(SBUF){case 0x34:k=EEPROM_READ(DATA_FLASH_START_ADDR);NOP5;if(0x0c==k){send_string(start_string,sizeof(start_string));}send_byte(k);k=0;break;case 0x33:read_string(DATA_FLASH_START_ADDR, 256);break;case 0x35:EEPROM_FORMAT(DATA_FLASH_START_ADDR); //写已经有数据的扇区前要写擦除NOP5;NOP5;NOP5; //可以适当增减延时NOP5;NOP5;NOP5;NOP5;EEPROM_WRITE(DATA_FLASH_START_ADDR,TEST_CO DE);//写一个0x0cbreak;default:if(0xff==i){i=0;}k=EEPROM_READ(DATA_FLASH_START_ADDR+(i++));send_byte(DATA_FLASH_START_ADDR+i);send_byte(k);k=0;break;}}}void init(){TMOD=0x20;SCON=0x50;TL1=0xfd;TH1=0xfd;TR1=1;ET1=1;ES=1;}void main(){init();while(1){test_read();}}。
/* STC89C54RD+的flash空间从0x4000~0xf3ff 共90个扇区,每扇区512字节*/ // #define BaseAddr 0x1000 /* 51rc */// #define EndSectoraddr 0x3d00 /* 51rc */// #define EndAddr 0x3fff /* 51rc 12K eeprom */#define BaseAddr 0x4000#define EndSectoraddr 0xf200#define EndAddr 0xf3ff#define UseAddr 0x1000/* ------------- 定义扇区大小------------- */#define PerSector 512/* 用户程序需要记忆的数组, 用户实际使用了n-1个数据,数组长度规整到2 4 8 16 32 64 上*/uchar Ttotal[16] ={0x55, /* 作为判别引导头使用,用户程序请不要修改它*//* 用户保存记忆的数据*/0x01, /* 用途说明....*/0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,};uint timerForDelay, /* 专供延时用的变量*/i, /* 循环变量*/EepromPtr; /* eeprom读写指针*//* --------------- 命令定义--------------- */#define RdCommand 0x01 /* 字节读*/#define PrgCommand 0x02 /* 字节写*/#define EraseCommand 0x03 /* 扇区擦除*//* 定义常量*/#define Error 1#define Ok 0/* 定义Flash对应于20MHz晶振系统的操作等待时间*//* 时钟倍频时WaitTime用0x00*/#define WaitTime 0x01/* ================ 打开ISP,IAP 功能================= */ void ISP_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 功能================== */ void ISP_IAP_disable(void){ISP_CONTR = 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_();}/* ==================== 字节读======================== */ uchar byte_read(uint byte_addr){ISP_ADDRH = (uchar)(byte_addr >> 8); /* 地址赋值*/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); /* 返回读到的数据*/}/* ================== 扇区擦除======================== */ void SectorErase(uint sector_addr){uint iSectorAddr;iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址*/ISP_ADDRH = (uchar)(iSectorAddr >> 8);ISP_ADDRL = 0x00;ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位*/ ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */ISPgoon(); /* 触发执行*/ISP_IAP_disable(); /* 关闭ISP,IAP功能*/}/* ==================== 字节写======================== */ void byte_write(uint byte_addr, uchar original_data){ISP_ADDRH = (uchar)(byte_addr >> 8); /* 取地址*/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功能*/}/* =================== 字节写并校验=================== */ uchar byte_write_verify(uint byte_addr, uchar original_data){ISP_ADDRH = (uchar)(byte_addr >> 8); /* 取地址*/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){ /* 读写数据校验*/return Ok; /* 返回校验结果*/ }else{return Error;}}/* ===================== 数组写入===================== */ uchar ArrayWrite(uint begin_addr, uint len, uchar *array){uint i;uint 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 = (uchar)(in_addr >> 8);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_DA TA != array[i]){ISP_IAP_disable();return Error;}in_addr++; /* 指向下一个字节*/ }ISP_IAP_disable();return Ok;}/* ========================= 扇区读出========================= */ /* 程序对地址没有作有效性判断,请调用方事先保证他在规定范围内*/void ArrayRead(uint begin_addr, uchar len){// uchar xdata data_buffer[]; /* 整个扇区读取缓存区*/ uint iSectorAddr;uint i;iSectorAddr = begin_addr; // & 0xfe00; /* 取扇区地址*/ISP_IAP_enable();for(i = 0; i < len; i++){ISP_ADDRH = (uchar)(iSectorAddr >> 8);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_DA TA;iSectorAddr++;}ISP_IAP_disable(); /* 关闭IAP功能*/}/* ============================================================== 从eeprom中读取数据============================================================== */ void DataRestore(){EepromPtr = BaseAddr; /* 指向eeprom的起始点*/while(EepromPtr < EndAddr) /* 在eeprom的可用区域内 */{if(byte_read(EepromPtr) == 0x55)/* 找到了上一次有效纪录*/{break; /* 寻找完成*/ }EepromPtr += 0x10; /* 指向下一个小区*/ }if(EepromPtr >= EndAddr) /* 如果照遍都没有,是新片*/{EepromPtr = BaseAddr; /* 指向eeprom的起始点*/for(i=0;i<90;i++){SectorErase(EepromPtr+0x200*i); /* 全部扇区擦除*/}while(ArrayWrite(EepromPtr, 0x10, Ttotal)) /* 写默认值*/{ /* 写入失败才运行的部分*/byte_write(EepromPtr, 0); /* 该单元已经失效*/if(EepromPtr < EndAddr){EepromPtr += 0x10; /* 换一块新的小区*/}else{P1=0; /* 指示芯片内eeprom全坏 */EA= 0; /* 不再做任何事*/while(1); /* 死机*/}}}ArrayRead(EepromPtr, 16);}/* ============================================================== 将需要记忆的数据保存到eeprom============================================================== */ void DataSave(){uint wrPtr; /* 临时指针*/NextArea:byte_write_verify(EepromPtr, 0); /* 将原来的标记清除*/wrPtr = EepromPtr & 0xfe00; /* 上一个扇区的起始地址*/EepromPtr += 0x10; /* 目标存入地址*//* ------------------ 判断是否启用新的扇区---------------- */if((EepromPtr & 0x1ff)==0){SectorErase(wrPtr); /* 将上一个扇区擦除,备用*/if(EepromPtr>=EndAddr) /* 已经用完了最后一个区域*/{EepromPtr = BaseAddr; /* 从头开始*/}}/* -------------------- 数据存入前的准备------------------ *//* 。