STC单片机EEPROM读写程序

合集下载

单片机EEPROM读写程序

单片机EEPROM读写程序
uint iSectorAddr; iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */ ISP_ADDRH = (uchar)(iSectorAddr >> 8); ISP_ADDRL = 0x00;
ISP_CMD = ISP_CMD & 0xf8;
/* 清空低 3 位 */
/* 指向下一个字节 */
/* ========================= 扇区读出 ========================= */
/* 程序对地址没有作有效性判断,请调用方事先保证他在规定范围内 */
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_DATA = 0;
ISP_TRIG = 0x46;
/* 触发 ISP_IAP 命令字节 1 */
ISP_TRIG = 0xb9;
/* 触发 ISP_IAP 命令字节 2 */
_nop_();
Ttotal[i] = ISP_DATA; iSectorAddr++; } ISP_IAP_disable(); }
ISP_TRIG = 0x46; ISP_TRIG = 0xb9; _nop_();

stc单片机eeprom读写程序

stc单片机eeprom读写程序

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读写程序详解

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 读写操作。

STC系列单片机片内EEPROM的应用

STC系列单片机片内EEPROM的应用

(2)向STC12C5A60S2单片机片内EEPROM中某单元写入数据 (假设系统时钟频率为20MHz):
MOV IAP_DATA,#DATA;先将要写入旳数据送至IAP_DATA寄 存器
MOV IAP_ADDRH,#BYTE_ADDRH;送单元地址旳高8位 MOV IAP_ADDRL,#BYTE_ADDRL;送单元地址旳低8位 MOV IAP_CONTR,#10000010B;设置等待时间且允许对
MS1 MS0 • 操作任务旳选择
0
0
待机模式,不操作
0
1
对EEPROM进行读操作
1
0
对EEPROM进行写操作
1
1 对EEPROM进行擦除操作
2.控制寄存器IAP_CONTR
WT2 WT1 WT0 读(2个 时钟)
1 1 1 2个时钟
写(55us) 55个时钟
扇区擦除( 21ms) 21012个时钟
MOV IAP_ADDRH,DPH;送地址旳高8位
MOV IAP_TRIG,#5AH;开启写操作
MOV IAP_TRIG ,#0A5H
LCALL DELAY_55μs ;延时等待
RET
BYTE_READ:
;读
MOV IAP_CONTR,#82H
MOV IAP_CMD,#01H ;读EEPROM命令
• EEPROM分为若干个扇区,每个扇区旳大小为512B,数据 存储器旳擦除操作是按扇区进行旳,能够擦写旳次数在10 万次以上。
• 使用时,同一次修改旳数据应该存储于同一种扇区,不是 同一次修改旳数据最佳存储在不同旳扇区,不一定要存满 。内部EEPROM旳扇区地址如表10-1所示。
起始地址 结束地址 起始地址 结束地址

STC单片机EEPROM的读写问题

STC单片机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的应用和程序

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保存数据的应用例子程序

STC89C52单片机内部EEPROM保存数据的应用例子程序

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读写程序

STC单片机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的地址匹配,否则无法进行有效的读写操作。

Stc12c5a60s2 eeprom读写程序

Stc12c5a60s2   eeprom读写程序

IapId
{
uchar temp=0;
Lnum=IapReadByte(0x0000);
P0=Lnum;
//连接 led
KEY_ADD=1; //按键输入端口电平置高
KEY_DEC=1;
if(IapReadByte(0x0000)==0xff||h==0)
{
IapEraseSector(0x0000); IapProgramByte(0x0000,0x0a); Lnum=10;
// 去 stc 官网下载 or stc 最新下载程序有 stc 系列头文件
sbit h=P3^0; sbit KEY_ADD=P3^4; sbit KEY_DEC=P3^5; uchar Lnum;
//定义按键输入端口
void delay(uchar i) {
uchar j; while(i--) { for(j=0;j<125;j++); } } void IapIdle() { IAP_CONTR=0; IAP_CMD=0; IAP_TRIG=0; IAP_ADDRH=0X80; IAP_ADDRL=0; } uchar IapReadByte(uint addr) {
nop();
IapIdle();
}
void IapEraseSector(uint addr)
{
IAP_CONTR=ENABLE_IAP;
IAP_CMD=CMD_ERASE;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_TRIG=0x5a;
IAP_TRIG=0xa5;
nop();
//按一下 P3^0,会把修改后的数据存入 eeprom 的 0x0000 地址内。关闭单片机,再次打开,

stc89le52rc内部EEPROM的C51读写程序

stc89le52rc内部EEPROM的C51读写程序

stc89le52rc内部EEPROM的C51读写程序/*stc89le52rc内部EEPROM的C51读写程序串口命令(9600)1.0x35可以写eeprom第一个字节数据0x0c2.0x34可以使用检查eeprom第一个字节的数据,正确就会反馈一串字符3.0x33可以读取eeprom前256个字节数据*/#include&lt;math.h&gt;#include&lt;stdio.h&gt;#include&lt;reg52.h&gt;#include &lt;intrins.h&gt;#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&lt;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&lt;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&gt;&gt;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&gt;&gt;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&gt;&gt;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();}}。

STC单片机内部EEPROM使用程序

STC单片机内部EEPROM使用程序

END
;定义Flash 操作等待时间及允许IAP/ISP/EEPROM操作的常数
;ENABLE_IAP EQU 80H ;系统工作时钟<30MHz时,对IAP_CONTR寄存器设置此值
ENABLE_IAP EQU 81H ;系统工作时钟<24MHz时,对IAP_CONTR寄存器设置此值
MOV IAP_ADDRL, DPL ;设置目标单元地址的低8位地址
CLR EA
MOV IAP_TRIG, #46H ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG, #0B9H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
MOV A, IAP_DATA ;读出的数据在IAP_DATA单元中,送入累加器A
ACALL IAP_Disable ;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,
;一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
CLR EA
MOV IAP_TRIG, #46H ;先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
MOV IAP_TRIG, #0B9H ;送完A5h后,ISP/IAP命令立即被触发起动
NOP
MOV IAP_TRIG, #0 ;清命令触发寄存器,使命令触发寄存器无触发,此句可不用
MOV IAP_ADDRH, #0FFH ;送地址高字节单元为00,指向非EEPROM区
MOV IAP_ADDRL, #0FFH ;送地址低字节单元为00,防止误操作
ACALL IAP_Disable ;关闭 IAP 功能, 清相关的特殊功能寄存器,使CPU处于安全状态,

stc系列单片机eeprom操作

stc系列单片机eeprom操作

stc系列单片机eeprom操作前言: stc单片机在中国大陆在中低端市场中占有大半壁江山.片内EEPROM是掉电保存数据的最理想选择.stc单片机的片内eeprom以扇区为单位,每个扇区大小是512 字节.以下是我亲自编写的对stc单片机(89系列除外)操作子函数,可以模块化使用,欢迎电子爱好者与我多多交流.本人QQ704157083 tel :186******** .工作地点:深圳..南山区. 从事软件和电子这行,爱好交朋友,一起开发有创意的产品.过目请留言!----------------------------------------------------------------------------------------------------------------------//增加寄存器sfr IAP_CONTR =0xC7; // ;软复位寄存器sfr IAP_DATA =0xC2 ; //数据寄存器;寄存器的地址不能改sfr IAP_adrRH =0xC3; // 地址高8位寄存器sfr IAP_adrRL = 0xC4; //命令触发器sfr IAP_CMD=0xC5; //;命令寄存器sfr IAP_TRIG=0xC6; //;命令触发器//************************************************************* **************** ****//增加通用函数.//(1) eeprom 函数写一个数据eg1: rom_writearea(1,100,0x99,12); 在片区1 地址100 中写入0x99 晶振12M// 读一个数据: eg2: rom_readarea(1,100,12); 在片区1 地址100 中读出数据晶振12M// 写一个数组:eg3: rom_write_array(1,100,a,10,12); 在片区1,起始地址100, 写入数组a ,数组大小10,晶振12Mxdata char xram[512] ; // 定义一个备份片区的数组.rom_readbyte(unsigned int adr,unsigned char fso);rom_readarea(unsigned int area,unsigned int adr_toread,unsigned char fso);void rom_writebyte(unsigned int adr,unsigned char dat,unsigned char fso);void rom_clear(unsigned int adr,unsigned char fso) ;void iap_disable();void rom_writearea(unsigned int area,unsigned int adr,unsigned char dat,unsigned char fso); // 写之前备份,扇区地址,字节地址,数据内容void rom_write_array(unsigned int area,unsigned int adr_towrite,unsigned char *p,unsigned int num,unsigned char fso);choose_area(unsigned char area); //选择片区//^^^^^^^^^^^^^^^^^^^^^^^^rom_readbyte(unsigned int adr,unsigned char fso){DPH=adr>>8; //取高字节DPL=adr; //取低字节if(fso==6){IAP_CONTR=0X84 ;}else if(fso==12){IAP_CONTR=0X8B; //;,<=12m晶振固定写法允许改变rom <=6M IAP_CONTR=0X84}IAP_CMD=0X01; //;01h为读取命令IAP_adrRH=DPH; //获取指针高八位IAP_adrRL=DPL; //获取指针低八位//EA=0;IAP_TRIG=0X5A; //两条触发命令,使命令执行IAP_TRIG=0XA5;// a=IAP_DATA; //;获取数据iap_disable();return(IAP_DATA);}//^^^^^^^^^^^^^^^^^^^^^^^^rom_readarea(unsigned int area,unsigned int adr_toread,unsigned char fso){unsigned int adr ; //扇区首地址adr=choose_area(area);IAP_DATA= rom_readbyte(adr+adr_toread,fso);//读取数据return(IAP_DATA);}//^^^^^^^^^^^^^^^^^^^^^^^^void rom_writebyte(unsigned int adr,unsigned char dat,unsigned char fso){DPH=adr>>8; //取高字节DPL=adr; //取低字节if(fso==6){IAP_CONTR=0X84 ;}else if(fso==12){IAP_CONTR=0X8B; //;,<=12m晶振固定写法允许改变rom <=6M IAP_CONTR=0X84}IAP_CMD=0X02; //;02h为写入命令IAP_adrRH=DPH; //获取指针高八位IAP_adrRL=DPL; //获取指针低八位IAP_DATA=dat; //把数据放入数据寄存器中,用于写//EA=0;IAP_TRIG=0X5A; //两条触发命令,使命令执行IAP_TRIG=0XA5;iap_disable();}//^^^^^^^^^^^^^^^^^^^^^^^^void rom_writearea(unsigned int area,unsigned int adr_towrite,unsigned char dat,unsigned char fso){unsigned int i,j ; //循环变量unsigned int adr ; //扇区首地址adr=choose_area(area);for (i=0;i<512;i++) //读扇区的所有数据,进行备份.{xram[i]=rom_readbyte(adr+i,fso);}rom_clear(area,fso); //清除要写入的扇区xram[adr_towrite]=dat ; //要写入的数据先放到数组中来for (j=0;j<512;j++) //将数组中的数据写入扇区中..{rom_writebyte(adr+j,xram[j],fso);}}//^^^^^^^^^^^^^^^^^^^^^^^^void rom_write_array(unsigned int area,unsigned int adr_towrite,unsigned char *p,unsigned int num,unsigned char fso){unsigned int i,j ; //循环变量unsigned int adr ; //扇区首地址adr=choose_area(area);for (i=0;i<512;i++) //读扇区的所有数据,进行备份.xram[i]=rom_readbyte(adr+i,fso);}rom_clear(area,fso); //清除要写入的扇区for(i=0;i<num;i++)< p="">{xram[adr_towrite+i]=*(p+i); //将数组的内容写入备份数组XRAM中}for (j=0;j<512;j++) //将数组中的数据写入扇区中..{rom_writebyte(adr+j,xram[j],fso);}}//^^^^^^^^^^^^^^^^^^^^^^^^void rom_clear(unsigned int area,unsigned char fso) //清除一片扇区{unsigned int adr ; //扇区首地址adr=choose_area(area);DPH=adr>>8; //取高字节DPL=adr; //取低字节if(fso==6){IAP_CONTR=0X84 ;}else if(fso==12){IAP_CONTR=0X8B; //;,<=12m晶振固定写法允许改变rom <=6M IAP_CONTR=0X84}IAP_CMD=0X03; //;03h为擦除命令IAP_adrRH=DPH; //获取指针高八位IAP_adrRL=DPL; //获取指针低八位//EA=0;IAP_TRIG=0X5A; //两条触发命令,使命令执行IAP_TRIG=0XA5;iap_disable();}//^^^^^^^^^^^^^^^^^^^^^^^^void iap_disable() // 关闭iap编程{IAP_CONTR=0X00; //关闭rom控制器命令IAP_CMD=0X00; //清除读写擦命令choose_area(unsigned char area){unsigned int adr;switch (area) //扇区编号从1开始到16扇区. {case 1: adr=0x0000;break;case 2: adr=0x0200;break;case 3: adr=0x0400;break;case 4: adr=0x0600;break;case 5: adr=0x0800;break;case 6: adr=0x0A00;break;case 7: adr=0x0C00;break;case 8: adr=0x0E00;break;case 9: adr=0x1000;break;case 10: adr=0x1200;break;case 11: adr=0x1400;break;case 12: adr=0x1600;break;case 13: adr=0x1800;break;case 14: adr=0x1A00;break;case 15: adr=0x1C00;break;case 16: adr=0x1E00;break;}return (adr);}//**********************************************************en d</num;i++)<>。

单片机EEPROM读写数据流程解析

单片机EEPROM读写数据流程解析

单片机EEPROM读写数据流程解析EEPROM 写数据流程第一步,首先是I2C 的起始信号,接着跟上首字节,也就是我们前边讲的I2C 的器件地址,并且在读写方向上选择“写”操作。

第二步,发送数据的存储地址。

24C02 一共256 个字节的存储空间,地址从0x00~0xFF,我们想把数据存储在哪个位置,此刻写的就是哪个地址。

第三步,发送要存储的数据第一个字节、第二个字节??注意在写数据的过程中,EEPROM 每个字节都会回应一个“应答位0”,来告诉我们写EEPROM 数据成功,如果没有回应答位,说明写入不成功。

在写数据的过程中,每成功写入一个字节,EEPROM 存储空间的地址就会自动加1,当加到0xFF 后,再写一个字节,地址会溢出又变成了0x00。

EEPROM 读数据流程第一步,首先是I2C 的起始信号,接着跟上首字节,也就是我们前边讲的I2C 的器件地址,并且在读写方向上选择“写”操作。

这个地方可能有同学会诧异,我们明明是读数据为何方向也要选“写”呢?刚才说过了,24C02 一共有256 个地址,我们选择写操作,是为了把所要读的数据的存储地址先写进去,告诉EEPROM 我们要读取哪个地址的数据。

这就如同我们打电话,先拨总机号码(EEPROM 器件地址),而后还要继续拨分机号码(数据地址),而拨分机号码这个动作,主机仍然是发送方,方向依然是“写”。

第二步,发送要读取的数据的地址,注意是地址而非存在EEPROM 中的数据,通知EEPROM 我要哪个分机的信息。

第三步,重新发送I2C 起始信号和器件地址,并且在方向位选择“读”操作。

这三步当中,每一个字节实际上都是在“写”,所以每一个字节EEPROM 都会回应一个“应答位0”。

第四步,读取从器件发回的数据,读一个字节,如果还想继续读下一个字节,就发送一个“应答位ACK(0)”,如果不想读了,告诉EEPROM,我不想要数据了,别再发数据了,那就发送一个“非应答位NAK(1)”。

stc89c52单片机EEPROM地址读写数据库函数

stc89c52单片机EEPROM地址读写数据库函数
EA = 1; /*开中断*/
Read_isp_data=isp_data;
return(Read_isp_data);
}
/**************************************************************/
/*******************************************************************************/
isp_trig = 0;
isp_addrh = 0;
isp_addrl = 0;
EA = 1; /*开中断*/
}
/**************************************************************/
/***************STC89CXX_EEPROM字节读程序*************************/
STC89CXX_EEPROM_Char_Write(0x20,0x01,0x11);
STC89CXX_EEPROM_Char_Write(0x20,0x02,0x22);
STC89CXX_EEPROM_Char_Write(0x20,0x03,0x33);
STC89CXX_EEPROM_Char_Write(0x20,0x04,0x44);
void main (void)
{
unsigned char temp;
Delay1ms(10); //开机延时
STC89CXX_EEPROM_Erase(0x20); //擦除整个扇区
STC89CXX_EEPROM_Char_Write(0x20,0x00,0x00); //指定EEPROM地址写数据

关于STC单片机内部EEPROM问题的解决

关于STC单片机内部EEPROM问题的解决

关于STC单片机内部EEPROM问题的解决关于STC单片机内部EEPROM问题的解决由于STC单片机的IAP功能比较好用,不需要仿真器就可以下载程序。

在一些简单的业余设计中,采用STC芯片确实比较方便。

STC芯片可以采用内部FLASH做成EEPROM功能来使用。

这个功能其实几乎所有现在出来的芯片都支持。

但STC做的有点让人不适应。

我刚开始做的时候,从官网下载了程序源代码,建好了工程。

试了一下,功能可以实现。

认为没有问题。

这东西也简单。

但到了后来,折腾了我两天。

让我头痛了。

最后终于解决了。

总结一下。

STC内部FLASH分的块挺小的.512Byte一个区。

毕竟是FLASH。

所以擦除一定是一片【512Byte】,写也简单,只要调用官网的程序就行了。

官网的程序还用了P1端口做为输出指示。

我把这些去掉了。

刚开始只是做了个按键调试一下,显示出来,然后修改完成后,又存进去。

所以没有发现问题。

后来,程序量大了。

同时,做为EEPROM,我是一上电就去读取。

如果读取的数据不对,我的程序会强行重新刷一次默认值进去。

结果问题出来了。

读取出来的数据偶尔会不正确。

总是被我给刷成默认值。

电路本身很简单,就一个通讯和显示【速按键调整】。

所以,硬件不会有问题,有问题的一定是软件本身。

STC的烧录中有一项,禁止低压时操作EEPROM。

当时,只是认为这个主要管理掉电的时候不要去写EEPROM。

后来才觉得不对。

上电时,是否也会有这种问题?由于有数据码显示,所以,上电后不久,数码管就会被点亮。

此时,电源电压会有所下降。

这个时候,写EEPROM肯定有问题。

其实,在这个时候,不光是写,读取也不行。

所以,我在程序中,做了处理,上电200ms以内,不去读取EEPROM的数据,同时220ms以内,不开启数码管显示。

这样有效地保证了电源电压的稳定。

这样,我还不放心,原来读取EEPROM只读取一次。

现在改为带校验。

每16个数据后面带一个校验字。

如果读取出来以后,校验不通过,则重新读取,三次都不正确则重新加载默认值,向EEPROM写一次数据。

(完整word版)STC单片机EEPROM读写程序

(完整word版)STC单片机EEPROM读写程序
ISP_CMD= ISP_CMD | EraseCommand;/*擦除命令3*/
ISPgoon();/*触发执行*/
ISP_IAP_disable();/*关闭ISP,IAP功能*/
}
/* ====================字节写======================== */
void byte_write(uint byte_addr, uchar original_data){
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*/
ISPgoon();/*触发执行*/
ISP_IAP_disable();/*关闭ISP,IAP功能*/
return (ISP_DATA);/*返回读到的数据*/
}
/* ==================扇区擦除======================== */
void SectorErase(uint sector_addr){
0x0e,
0x0f,
};
uinttimerForDelay,/*专供延时用的变量*/
i,/*循环变量*/
EepromPtr;/* eeprom读写指针*/
/* ---------------命令定义--------------- */
#define RdCommand0x01/*字节读*/
#define PrgCommand0x02/*字节写*/

STC单片机EEPROM的读写程序

STC单片机EEPROM的读写程序

STC单片机EEPROM的读写程序汇编语言写的,依据stc单片机官方提供的资料,测试ok,另外还有c语言的大家可到论坛去找。

stc的eeprom 功能还是不错的,可以简化我们的外围电路,但是缺点是是有就那就是写入速度太慢了,只能按扇区的写,不能字节写.下面是代码AUXR1 EQU 0A2HISPDATA EQU 0E2HISPADDRH EQU 0E3HISPADDRL EQU 0E4HISPCMD EQU 0E5HISPTRIG EQU 0E6HISPCONTR EQU 0E7HORG 0000HAJMP MAINORG 0030HMAIN:MOV AUXR1,#0INC AUXR1MOV DPTR,#2000H ACALL ERASEMOV A,#0FEH ACALL EEPROMW ACALL EEPROMR INC AUXR1AJMP MAIN ERASE:;擦除MOV ISPCONTR,#81H MOV ISPCMD,#03H MOV ISPADDRH,DPH MOV ISPADDRL,DPL CLR EAMOV ISPTRIG,#46H MOV ISPTRIG,#0B9H NOPSETB EAACALL ISPXXRET EEPROMW:;写MOV ISPCONTR,#81H MOV ISPCMD,#02HMOV ISPADDRH,DPH MOV ISPADDRL,DPL MOV ISPDATA,A CLR EAMOV ISPTRIG,#46H MOV ISPTRIG,#0B9H NOPSETB EAACALL ISPXXRET EEPROMR:;读MOV ISPCONTR,#81H MOV ISPCMD,#01H MOV ISPADDRH,DPH MOV ISPADDRL,DPL CLR EAMOV ISPTRIG,#46H MOV ISPTRIG,#0B9H NOPMOV A,ISPDATA SETB EAACALL ISPXXRETISPXX:MOV ISPCONTR,#0 MOV ISPCMD,#0 MOV ISPTRIG,#0 RETDEL:MOV R2,#0FFHD1:MOV R1,#0FFH DJNZ R1,$DJNZ R2,D1RETEND。

STC_EEPROM延长使用寿命的大数据记录C程序详解

STC_EEPROM延长使用寿命的大数据记录C程序详解

STC_EEPROM延长使用寿命的大数据记录C程序在我们华清士科技公司的产品研发中,使用很多远程传感器的记录方案,在单片机编程的时候,觉得以下程序切实提高了STC单片机的EEPROM使用灵活性和寿命。

特此分享出来,期待可以抛砖引玉。

原理是这样的:STC-eeprom一个字节的写入,只能将1的状态写成0。

这样一个字节就可以被写8次,记录8个状态(分别是0xFE 0XFB 0XF8 0XE0 0XB0 0X80 0X00)。

当然其实还有一个状态是0XFF ,这是扇区被整个擦写后的状态。

我们就每记录一个数据,就在检索区加写1/8个字节,作为记录次数标识。

这样一组数据(示例之中为6个字节)所占用的空间实际上是6+1/8字节。

以此我们可以根据STC单片机型号的不同,将策划好的扇区数填入程序函数里面,每一次加电重启,都有一个程序来读取检索区的记忆次数,顺便,记录区的地址,都会有了。

(EEPROM_start0-EEPROM_start1 作为次数记录区,总共记录EEPROM_mu_MAX组数据。

)(x_ready_ok,x_ready_out,x_eeprom_need为该示例eeprom的标志)这个程序我们已经上机演示调试成功。

类似的应用也在华清士公司的几种除湿模块产品上得到广泛使用。

效果良好。

写此文是希望为我们钟爱的STC单片机开发做一些支持。

希望也得到广大工程师的交流沟通,共同提高。

下面是该C语言的程序。

应该在STC公司的IAP型号上面都可以调试成功。

当然在别的型号上面,比如STC12F04XE等上面,程序之中的起始扇区当然是1了,因为eeprom记录地址是从0x00(第一个扇区)开始的。

20170504_STC_EEPROM连续存储示例.c//------------------------------------------------------------------// 程序开始宏定义硬件接口定义//------------------------------------------------- ----------------#include "STC15F2K60S2.h"#include "intrins.h"//#include "absacc.h"//#include "math.h"#define _Nop() _nop_()//STC15W413AS -TSSOP20 单片机封装//该程序为演示程序20170508 ——演示EEPROM 13k 空间的自动分配以及多次记录数据检索//原始目的:利用STC-eeprom读写规则,尽量减少擦写次数,以延长EEPROM使用寿命。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

/* 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; /* 从头开始*/}}/* -------------------- 数据存入前的准备------------------ *//* 。

相关文档
最新文档