您的位置 首页 分销

STC89C5x系列单片机内部EEPROM

//(c)Copyright2007-2017,GuozhouChen.AllRightsReserved./*********************************************

//(c)Copyright2007-2017,GuozhouChen.AllRightsReserved.

/********************************************************************************
*个人声明:*
*自己在运用STC89C5x系列单片机内部EEPROM时,了解其对非0xff值的存储空间*
*不能经过字节编程直接写入。这一约好可能给一些人带来运用的费事,所以本*
*人决议编写一能够让程序员不考虑这一约好的API。经过几个小时的编写和调*
*试,基本能到达自己本来想象的方针。因为时刻匆促及个人水平有限,难免会*
*有些算法低效,还望高手指导。Email:chenguozhou1982@yahoo.com.cn。*
**
*本程序经过改几个宏界说能够运用到STC的许多类型MCU上,自己只测试了*
*STC89C5x系列*

*本程序能够恣意修正和传达,修正者请注明修正人、修正时刻,传达进程请注*
*明原著。不得用于任何商业意图。*
**
********************************************************************************
*FileName:EEPROM.C,V0.2.0*
*Author:GuozhouChen*
*Date:2007.09.15*
**
********************************************************************************
*运用数据类型阐明:*
*UINT:16位无符号整形*
*BYTE:8位无符号字符型*
*BOOL:1位布尔类型*
**
********************************************************************************
*直接调用的API阐明:*
**
*读函数原形:UINTEEPROM_ReadBytes(UINTaddr,BYTE*buf,UINTsize)*
*函数回来为UINT类型的实践读出数据字节数。*
*参数阐明:addr为需求读取EEPROM区域的榜首字节地址,取值规模为内部*
*EEPROM除最终一扇区外的地址,因最终一扇区被献身做为缓存。*
*buf为意图数据区指针,即指向保存读出数据区域的首地址。*
*size为要求读出数据的字节数*
**
*写函数原形:UINTEEPROM_WritBytes(UINTaddr,BYTE*buf,UINTsize)*
*函数回来为UINT类型的实践写入数据字节数。*
*参数阐明:addr为需求写入EEPROM区域的榜首字节地址,取值规模为内部*
*EEPROM除最终一扇区外的地址,因最终一扇区被献身做为缓存。*
*buf为源数据区指针,即指向需求写入数据区域的首地址。*
*size为要求写入数据的字节数*
**
********************************************************************************
*运用阐明:*
*1、依据MCU和编译器的实践情况修正几个宏界说和数据类型界说。宏界说和数据类*
*型界说部分能够独自写成头文件。*
*2、在需求运用EEPROM_ReadBytes()和EEPROM_WritBytes()函数的文件中做个*
*原形声明。*
*3、在需求的当地直接添入实参调用即可。*
**
********************************************************************************/

/********************************************************************************
**
*头文件*
**
********************************************************************************/
#include”STC89C5x.h”

/********************************************************************************
**
*数据类型界说*
**
********************************************************************************/
typedefunsignedintUINT;
typedefunsignedcharBYTE;
typedefbitBOOL;

/********************************************************************************
**
*宏界说*
**
********************************************************************************/
#defineBYTES_EACH_SECTOR512//MCUEEPROM每扇区的字节数

//CPU等待时刻,晶振0-5M设置为3,5-10M为2,10-20M为1,大于20M为0
#defineWAIT_TIME0

#defineUSEING_EACH_SECTOR512//方案每扇区要用的字节数,用量越小写速度越快

#defineEEPROM_ADDR_START0x2000//EEPROM开始地址
#defineEEPROM_ADDR_END0x2fff//EEPROM完毕地址

/********************************************************************************
**
*从指定首地址为addr的EEPROM区域读出size字节数据到buf指向的区域内,并回来实践读*
*出数据的字节数*
**
********************************************************************************/

UINTEEPROM_ReadBytes(UINTaddr,BYTE*buf,constUINTsize)
{
BOOLold_EA;

BYTE*p_buf;
UINTi,current_size;

p_buf=buf;
current_size=0;

ISP_CMD=0x01;
ISP_CONTR=0x80|WAIT_TIME;

for(i=0;i{
//地址越界检测
if((addrEEPROM_ADDR_END))
{
break;
}

ISP_ADDRH=addr>>8;
ISP_ADDRL=addr&0x00ff;

old_EA=EA;
EA=0;

ISP_TRIG=0x46;
ISP_TRIG=0xB9;

EA=old_EA;

*p_buf=ISP_DATA;

addr++;
p_buf++;
current_size++;

}
ISP_CMD=0x00;
ISP_CONTR=0x00;

returncurrent_size;
}

/********************************************************************************
**
*把buf指向单元内的数据写入地址为addr的EEPROM单元内,成功回来1,或则回来0*
**
********************************************************************************/
BOOLEEPROM_WritByte(UINTaddr,BYTE*buf)
{
BOOLold_EA;

if((addrEEPROM_ADDR_END))
{
return0;
}

ISP_CMD=0x02;
ISP_CONTR=0x80|WAIT_TIME;

ISP_DATA=(*buf);

ISP_ADDRH=addr>>8;
ISP_ADDRL=addr&0x00ff;

old_EA=EA;
EA=0;

ISP_TRIG=0x46;
ISP_TRIG=0xB9;

EA=old_EA;

ISP_CMD=0x00;
ISP_CONTR=0x00;

return1;
}

/********************************************************************************
**
*擦除AddrInSector地址地点的整个扇区*
**
********************************************************************************/
voidErasureAllSector(UINTAddrInSector)
{
BOOLold_EA;

ISP_CMD=0x03;
ISP_CONTR=0x80|WAIT_TIME;

ISP_ADDRH=AddrInSector>>8;
ISP_ADDRL=AddrInSector&0x00ff;

old_EA=EA;
EA=0;

ISP_TRIG=0x46;
ISP_TRIG=0xB9;

EA=old_EA;

ISP_CMD=0x00;
ISP_CONTR=0x00;
}

/********************************************************************************
**
*从首地址为src扇区单元复制接连size字节数据到首地址为des的接连扇区单元内,并返*
*回实践复制的字节数*
**
********************************************************************************/
UINTCopySector(UINTsrc,UINTdes,constUINTsize)
{
BYTEtemp;
UINTcurrent_size,i;

current_size=0;

for(i=0;i{
if(!EEPROM_ReadBytes(src,&temp,1))
{
break;
}

if(!EEPROM_WritByte(des,&temp))
{
break;
}

des++;
src++;
current_size++;
}

returncurrent_size;
}

/********************************************************************************
**
*把buf指向区域内的size字节数据写入首地址为addr的EEPROM接连区域,并回来实践写入*
*数据的字节数*
**
********************************************************************************/
UINTEEPROM_WritBytes(UINTaddr,BYTE*buf,constUINTsize)
{
BYTE*p_buf,temp,move;

UINTi,bufaddr,current_size,cur_sector_start_addr;

p_buf=buf;

move=0;
current_size=0;

for(i=0;i{
if(!EEPROM_ReadBytes(addr,&temp,1))
{
break;
}

if(temp==0xff)
{
EEPROM_WritByte(addr,p_buf);
}
//发现榜首个单元不是0xff,要重新写入数据需求做擦除整个扇区
else
{
//擦除用作缓冲的这个扇区
ErasureAllSector(EEPROM_ADDR_END);

cur_sector_start_addr=addr&0xfe00;

//把榜首个非0xff单元前的数据复制到缓冲扇区
CopySector(cur_sector_start_addr
,(EEPROM_ADDR_END+1-BYTES_EACH_SECTOR)
,(addr-cur_sector_start_addr));

//核算剩下需求存储的数据需写入缓冲扇区的首个单元地址
bufaddr=(addr-cur_sector_start_addr)
+(EEPROM_ADDR_END+1-BYTES_EACH_SECTOR);

//把剩下要存储的数据写入缓冲扇区
for(;i{
EEPROM_WritByte(bufaddr,p_buf);

addr++;
bufaddr++;
p_buf++;
current_size++;
}

//把需求改动区域后的数据写入缓冲扇区
if(addr{
CopySector(addr,bufaddr,USEING_EACH_SECTOR
-(addr-cur_sector_start_addr));
}

//擦除当时扇区
ErasureAllSector(cur_sector_start_addr);
move=1;
break;
}

addr++;
p_buf++;
current_size++;
}

if(move)
{
//把缓冲扇区数据复制到当时扇区
CopySector((EEPROM_ADDR_END-BYTES_EACH_SECTOR+1)
,cur_sector_start_addr,USEING_EACH_SECTOR);
}

returncurrent_size;
}
/*****************************Nothingbelowthisline***************************/

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/fenxiao/275020.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部