24c04读写程序详解
SCL BIT P1.7;定义24C02的串行时钟线 ClimberWin 2005.8.4
SDA BIT P1.6;定义24C02的串行数据线
ORG 00H
START:
MOV R1,#20H ; 数据保存地址
MOV R7,#120 ; 取数据的个数
;;**********************************
CALL FIRST ;开始命令
MOV A,#0A0H ;写器件地址
CALL SUBS
;;**********************************
MOV A,#00h ;所要读的器件的地址
CALL SUBS
;;**********************************
CALL FIRST ;开始命令
MOV A,#0A1H ;开始读数据
CALL SUBS
;;**********************************
WIN: CALL SUBR
MOV @R1,A
INC R1
DJNZ R7,WIN
CLR SDA
CALL DELAY
SETB SCL
CALL DELAY
SETB SDA
JMP $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SUBR: MOV R0,#08H
LOOP2: SETB SCL
CALL DELAY
MOV C,SDA
RLC A
CLR SCL
CALL DELAY
DJNZ R0,LOOP2
CJNE R7,#00h,LOW1 ;改
SETB SDA
JMP CLIMBER
LOW1: CLR SDA
CLIMBER:CALL DELAY
SETB SCL
CALL DELAY
CLR SCL
CALL DELAY
SETB SDA
RET
SUBS: MOV R5,#08H
LOOP: CLR SCL
RLC A
MOV SDA ,C
NOP
SETB SCL
CALL DELAY
DJNZ R5,LOOP
CLR SCL
CALL DELAY
SETB SCL
REP: MOV C, SDA
JC REP
CLR SCL
RET
DELAY: NOP
NOP
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FIRST: SETB SDA
SETB SCL
CALL DELAY
CLR SDA
CALL DELAY
CLR SCL ;开始传数据
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
END
调用Write_Flash()和Read_Flash()前,先把page07填好对应的页数,下面的
函数声明处有说明
需要在主程序处定义一些参数,如下:
bit f_rom; //eprom应答标志,=1不应答
uchar xdata epromerr; //用来统计写入出错的次数
uint xdata epadd; //用来作为rom目标写入的首地址,要进行计算
uchar xdata page07; //每256个字节当一页,请注意不要写错页
uchar xdata *ncon; //用来处理写入或读入的缓存地址
uchar xdata len1; //rom第一段数据长度,看eprom.c
uchar xdata len2; //rom中间段数据页数,看eprom.c
uchar xdata len3; //rom末尾段数据长度,看eprom.c
如果不用外部存储器件,把关键字xdata去掉,然后再修改Write_Flash()
和Read_Flash()的声明部分参数
*/
//定义使用的IC,容量超过了这些IC就不能用了
#define d_24c01a 8 //定义IC每一页的字节数
#define d_24c02 8
#define d_24c04 16
#define d_24c08a 16
#define d_24c16a 16
#define numbyte_page d_24c16a
#define WriteDeviceAddress 0xa0 //写驱动地址指令
#define ReadDeviceAddress 0xa1 //读驱动地址指令
void nod2()
{unsigned char i; //4.6us延时
for (i=0;i《13;i++)
_nop_();
}
/*-------------------------------------------------------------
功能:发起始信号
------------------------------------------------------------*/
void Start_Cond()
{
SDA = 1;
nod2();
SCL = 1;
nod2();
SDA = 0;
nod2();
SCL = 0;
nod2();
}
/*-------------------------------------------------------------
功能:发停止信号
------------------------------------------------------------*/
void Stop_Cond()
{
SDA = 0;
nod2();
SCL = 1;
nod2();
SDA = 1;
nod2();
SCL = 0;
nod2();
}
/*-------------------------------------------------------------
功能:发确认信号
------------------------------------------------------------*/
void Ack()
{
SDA = 0;
nod2();
SCL = 1;
nod2();
SCL = 0;
nod2();
SDA = 1;
nod2();
}
/*-------------------------------------------------------------
功能:发无确认信号
------------------------------------------------------------*/
void NoAck()
{
SDA = 1;
nod2();
SCL = 1;
nod2();
SCL = 0;
nod2();
SDA = 0;
nod2();
}
/*-------------------------------------------------------------
功能:读一个字节数据
------------------------------------------------------------*/
unsigned char Read8Bit()
{
unsigned char temp,rbyte=0;
for (temp = 0;temp《8;temp++)
{ SDA=1;
nod2();
SCL = 1;
nod2();
rbyte=(rbyte《《1)|SDA;
SCL = 0;
nod2();
}
return(rbyte);
}
/*-------------------------------------------------------------
功能:写一个字节数据
------------------------------------------------------------*/
Write8Bit(unsigned char input)
{
unsigned char i;
for (i=0;i《8;i++)
{ input 《《= 1;
SDA = CY;
nod2();
SCL = 1;
nod2();
SCL = 0;
nod2();
SDA = 0;
nod2();
}
f_rom=0; //chack
SDA=1;
nod2();
nod2();
SCL=1;
nod2();
nod2();
f_rom=SDA;
SCL=0;
nod2();
nod2();
}
/*------------------------------------------------------------
功能:从EEPROM中给定一个地址连续读NLEN个字节数据存放在以指针
nContent开头的往下内容。
写地址为0x000~0x7ff,用参数page07代表最高位的页数(0~7)
------------------------------------------------------------*/
Read_Flash ( unsigned char xdata *nContent, unsigned char nAddr, unsigned int nLen ) large reentrant
{
unsigned char i,j;
//例如目标首地址为5,要写入20个字节,用24c02(每页8个字节)
//那么len1=8-5%8=3,第一页只能读3个字节
//len3=(20-3)%8=1,最后页只能读1个字节
//len2=(20-3-1)/8=2,中间能完整的读2页,刚好20个字节读完
//目标rom首地址离一页末要读的字节数
len1=numbyte_page-nAddr%numbyte_page;
//目标rom最后页读入的字节数
len3=(nLen-len1)%numbyte_page;
//目标rom中间能够完整读入的页数
len2=(nLen-len1-len3)/numbyte_page;
if(len1》nLen) //假如读入长度不足把第一页写完,要更正参数
{ len1=nLen;
len2=0;
len3=0;
}
epromerr=0;
wrstart2:
epromerr++;
ncon=nContent;
if(epromerr》200)
goto errdo2;
//===========================
//读第一段数据
//===========================
Start_Cond();
Write8Bit(WriteDeviceAddress+(page07《《1)); //写写控制字
if(f_rom==1)
goto wrstart2;
Write8Bit(nAddr); //写地址
if(f_rom==1)
goto wrstart2;
Start_Cond();
Write8Bit(ReadDeviceAddress+(page07《《1)); //写读控制字
if(f_rom==1)
goto wrstart2;
if(len1》1) //读第一段数据
{ for(i=0;i《(len1-1);i++)
{ *ncon=Read8Bit();
Ack();
ncon++;
}
}
*ncon=Read8Bit(); //读1个数
NoAck();
ncon++;
Stop_Cond(); //停止
nod2();
//===========================
//读中间段数据
//===========================
if(len2》0)
{ for(j=0;j《len2;j++)
{
epadd=nAddr+(numbyte_page)*j+len1; //修正写入目标偏移地址
Start_Cond();
Write8Bit(WriteDeviceAddress+(page07《《1)); //写写控制字
if(f_rom==1)
goto wrstart2;
Write8Bit(epadd); //写地址
if(f_rom==1)
goto wrstart2;
Start_Cond();
Write8Bit(ReadDeviceAddress+(page07《《1)); //写读控制字
if(f_rom==1)
goto wrstart2;
for(i=0;i《(numbyte_page-1);i++) //读numbyte_page-1个字节
{ *ncon=Read8Bit();
Ack();
ncon++;
}
*ncon=Read8Bit(); //读1个字节
NoAck();
ncon++;
Stop_Cond(); //停止
nod2();
}
}
//===========================
//读末尾段数据
//===========================
if(len3》0)
{ epadd=nAddr+(numbyte_page)*len2+len1; //修正写入目标偏移地址
Start_Cond();
Write8Bit(WriteDeviceAddress+(page07《《1)); //写写控制字
if(f_rom==1)
goto wrstart2;
Write8Bit(epadd); //写地址
if(f_rom==1)
goto wrstart2;
Start_Cond();
Write8Bit(ReadDeviceAddress+(page07《《1)); //写读控制字
if(f_rom==1)
goto wrstart2;
if(len3》1) //读末尾段数据
{ for(i=0;i《(len3-1);i++)
{ *ncon=Read8Bit();
Ack();
ncon++;
}
}
*ncon=Read8Bit(); //读1个数
NoAck();
ncon++;
Stop_Cond(); //停止
nod2();
}
/*
j=0;
restart: j++;
if (j==255)
goto errdo2;
Start_Cond(); //写开始信号
Write8Bit(WriteDeviceAddress); //写写控制字
if(f_rom==1) goto restart;
Write8Bit(nAddr); //写地址
if(f_rom==1) goto restart;
Start_Cond(); //写开始信号
Write8Bit(ReadDeviceAddress); //写读控制字
if(f_rom==1) goto restart;
for(i=0;i《(nLen-1);i++) //读7个数
{ *nContent=Read8Bit();
Ack();
nContent++;
}
*nContent=Read8Bit(); //读1个数
NoAck();
Stop_Cond(); //停止
nod2();
*/
errdo2:;//////////////////////////////////////读数据超时处理
//outr:;
}
/*-------------------------------------------------------------
功能:从EEPROM中给定一个地址nAddr,连续写NLEN个字节数据存放在以指针
nContent开头的往下内容
写地址为0x000~0x7ff,用参数page07代表最高位的页数(0~7)
------------------------------------------------------------*/
Write_Flash ( unsigned char xdata *nContent,unsigned char nAddr, unsigned int nLen) large reentrant
{
//unsigned char epromerr; //用来统计写入出错的次数
unsigned char i,j; //for循坏用
//unsigned char xdata epadd; //用来作为rom目标地址,要进行计算
//unsigned char xdata len1; //rom第一段数据长度,看eprom.c
//unsigned char xdata len2; //rom中间段数据页数,看eprom.c
//unsigned char xdata len3; //rom末尾段数据长度,看eprom.c
//例如目标首地址为5,要写入20个字节,用24c02(每页8个字节)
//那么len1=8-5%8=3,第一页只能写3个字节
//len2=(20-3)%8=1,最后页只能写1个字节
//len3=(20-3-1)/8=2,中间能完整的写2页,刚好20个字节写完
//目标rom首地址离一页末要写的字节数
len1=numbyte_page-nAddr%numbyte_page;
//目标rom最后页写入的字节数
len3=(nLen-len1)%numbyte_page;
//目标rom中间能够完整写入的页数
len2=(nLen-len1-len3)/numbyte_page;
if(len1》nLen) //假如写入长度不足把第一页写完,要更正参数
{ len1=nLen;
len2=0;
len3=0;
}
epromerr=0;
wrstart:
++epromerr;
ncon=nContent; //重新修正缓存对应地址
if(epromerr》200)
goto errdo1;
//===========================
//写第一段数据
//===========================
Start_Cond();
Write8Bit(WriteDeviceAddress+(page07《《1)); //写写控制字
if(f_rom==1)
goto wrstart;
Write8Bit(nAddr); //写地址
if(f_rom==1)
goto wrstart;
for(i=0;i《len1;i++) //写第一段数据
{ Write8Bit(*ncon);
if(f_rom==1)
goto wrstart;
ncon++;
}
Stop_Cond(); //首段写完
//===========================
//写中间的完整段数据
//===========================
if(len2》0)
{ for(j=0;j《len2;j++) //写len2页
{ epadd=nAddr+(numbyte_page)*j+len1; //修正写入目标偏移地址
Start_Cond();
Write8Bit(WriteDeviceAddress+(page07《《1)); //写写控制字
if(f_rom==1)
goto wrstart;
Write8Bit(epadd); //写地址
if(f_rom==1)
goto wrstart;
for(i=0;i《numbyte_page;i++) //写完整的一页
{ Write8Bit(*ncon);
if(f_rom==1)
goto wrstart;
ncon++;
}
Stop_Cond(); //一段写完
}
}
//===========================
//写末尾段数据
//===========================
if(len3》0)
{ epadd=nAddr+(numbyte_page)*len2+len1; //修正写入目标偏移地址
Start_Cond();
Write8Bit(WriteDeviceAddress+(page07《《1)); //写写控制字
if(f_rom==1)
goto wrstart;
Write8Bit(epadd); //写地址
if(f_rom==1)
goto wrstart;
for(i=0;i《len3;i++) //写末尾段数据
{ Write8Bit(*ncon);
if(f_rom==1)
goto wrstart;
ncon++;
}
Stop_Cond(); //末尾段写完
}
errdo1:;
评论
查看更多