24c04讀寫程序詳解
SCL BIT P1.7;定義24C02的串行時(shí)鐘線 ClimberWin 2005.8.4
SDA BIT P1.6;定義24C02的串行數(shù)據(jù)線
ORG 00H
START:
MOV R1,#20H ; 數(shù)據(jù)保存地址
MOV R7,#120 ; 取數(shù)據(jù)的個(gè)數(shù)
;;**********************************
CALL FIRST ;開始命令
MOV A,#0A0H ;寫器件地址
CALL SUBS
;;**********************************
MOV A,#00h ;所要讀的器件的地址
CALL SUBS
;;**********************************
CALL FIRST ;開始命令
MOV A,#0A1H ;開始讀數(shù)據(jù)
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 ;開始傳數(shù)據(jù)
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
END
先把下面的#define numbyte 改為對(duì)應(yīng)IC型號(hào)
調(diào)用Write_Flash()和Read_Flash()前,先把page07填好對(duì)應(yīng)的頁(yè)數(shù),下面的
函數(shù)聲明處有說(shuō)明
需要在主程序處定義一些參數(shù),如下:
bit f_rom; //eprom應(yīng)答標(biāo)志,=1不應(yīng)答
uchar xdata epromerr; //用來(lái)統(tǒng)計(jì)寫入出錯(cuò)的次數(shù)
uint xdata epadd; //用來(lái)作為rom目標(biāo)寫入的首地址,要進(jìn)行計(jì)算
uchar xdata page07; //每256個(gè)字節(jié)當(dāng)一頁(yè),請(qǐng)注意不要寫錯(cuò)頁(yè)
uchar xdata *ncon; //用來(lái)處理寫入或讀入的緩存地址
uchar xdata len1; //rom第一段數(shù)據(jù)長(zhǎng)度,看eprom.c
uchar xdata len2; //rom中間段數(shù)據(jù)頁(yè)數(shù),看eprom.c
uchar xdata len3; //rom末尾段數(shù)據(jù)長(zhǎng)度,看eprom.c
如果不用外部存儲(chǔ)器件,把關(guān)鍵字xdata去掉,然后再修改Write_Flash()
和Read_Flash()的聲明部分參數(shù)
*/
//定義使用的IC,容量超過(guò)了這些IC就不能用了
#define d_24c01a 8 //定義IC每一頁(yè)的字節(jié)數(shù)
#define d_24c02 8
#define d_24c04 16
#define d_24c08a 16
#define d_24c16a 16
#define numbyte_page d_24c16a
#define WriteDeviceAddress 0xa0 //寫驅(qū)動(dòng)地址指令
#define ReadDeviceAddress 0xa1 //讀驅(qū)動(dòng)地址指令
void nod2()
{unsigned char i; //4.6us延時(shí)
for (i=0;i《13;i++)
_nop_();
}
/*-------------------------------------------------------------
功能:發(fā)起始信號(hào)
------------------------------------------------------------*/
void Start_Cond()
{
SDA = 1;
nod2();
SCL = 1;
nod2();
SDA = 0;
nod2();
SCL = 0;
nod2();
}
/*-------------------------------------------------------------
功能:發(fā)停止信號(hào)
------------------------------------------------------------*/
void Stop_Cond()
{
SDA = 0;
nod2();
SCL = 1;
nod2();
SDA = 1;
nod2();
SCL = 0;
nod2();
}
/*-------------------------------------------------------------
功能:發(fā)確認(rèn)信號(hào)
------------------------------------------------------------*/
void Ack()
{
SDA = 0;
nod2();
SCL = 1;
nod2();
SCL = 0;
nod2();
SDA = 1;
nod2();
}
/*-------------------------------------------------------------
功能:發(fā)無(wú)確認(rèn)信號(hào)
------------------------------------------------------------*/
void NoAck()
{
SDA = 1;
nod2();
SCL = 1;
nod2();
SCL = 0;
nod2();
SDA = 0;
nod2();
}
/*-------------------------------------------------------------
功能:讀一個(gè)字節(jié)數(shù)據(jù)
------------------------------------------------------------*/
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);
}
/*-------------------------------------------------------------
功能:寫一個(gè)字節(jié)數(shù)據(jù)
------------------------------------------------------------*/
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中給定一個(gè)地址連續(xù)讀NLEN個(gè)字節(jié)數(shù)據(jù)存放在以指針
nContent開頭的往下內(nèi)容。
寫地址為0x000~0x7ff,用參數(shù)page07代表最高位的頁(yè)數(shù)(0~7)
------------------------------------------------------------*/
Read_Flash ( unsigned char xdata *nContent, unsigned char nAddr, unsigned int nLen ) large reentrant
{
unsigned char i,j;
//例如目標(biāo)首地址為5,要寫入20個(gè)字節(jié),用24c02(每頁(yè)8個(gè)字節(jié))
//那么len1=8-5%8=3,第一頁(yè)只能讀3個(gè)字節(jié)
//len3=(20-3)%8=1,最后頁(yè)只能讀1個(gè)字節(jié)
//len2=(20-3-1)/8=2,中間能完整的讀2頁(yè),剛好20個(gè)字節(jié)讀完
//目標(biāo)rom首地址離一頁(yè)末要讀的字節(jié)數(shù)
len1=numbyte_page-nAddr%numbyte_page;
//目標(biāo)rom最后頁(yè)讀入的字節(jié)數(shù)
len3=(nLen-len1)%numbyte_page;
//目標(biāo)rom中間能夠完整讀入的頁(yè)數(shù)
len2=(nLen-len1-len3)/numbyte_page;
if(len1》nLen) //假如讀入長(zhǎng)度不足把第一頁(yè)寫完,要更正參數(shù)
{ len1=nLen;
len2=0;
len3=0;
}
epromerr=0;
wrstart2:
epromerr++;
ncon=nContent;
if(epromerr》200)
goto errdo2;
//===========================
//讀第一段數(shù)據(jù)
//===========================
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) //讀第一段數(shù)據(jù)
{ for(i=0;i《(len1-1);i++)
{ *ncon=Read8Bit();
Ack();
ncon++;
}
}
*ncon=Read8Bit(); //讀1個(gè)數(shù)
NoAck();
ncon++;
Stop_Cond(); //停止
nod2();
//===========================
//讀中間段數(shù)據(jù)
//===========================
if(len2》0)
{ for(j=0;j《len2;j++)
{
epadd=nAddr+(numbyte_page)*j+len1; //修正寫入目標(biāo)偏移地址
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個(gè)字節(jié)
{ *ncon=Read8Bit();
Ack();
ncon++;
}
*ncon=Read8Bit(); //讀1個(gè)字節(jié)
NoAck();
ncon++;
Stop_Cond(); //停止
nod2();
}
}
//===========================
//讀末尾段數(shù)據(jù)
//===========================
if(len3》0)
{ epadd=nAddr+(numbyte_page)*len2+len1; //修正寫入目標(biāo)偏移地址
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) //讀末尾段數(shù)據(jù)
{ for(i=0;i《(len3-1);i++)
{ *ncon=Read8Bit();
Ack();
ncon++;
}
}
*ncon=Read8Bit(); //讀1個(gè)數(shù)
NoAck();
ncon++;
Stop_Cond(); //停止
nod2();
}
/*
j=0;
restart: j++;
if (j==255)
goto errdo2;
Start_Cond(); //寫開始信號(hào)
Write8Bit(WriteDeviceAddress); //寫寫控制字
if(f_rom==1) goto restart;
Write8Bit(nAddr); //寫地址
if(f_rom==1) goto restart;
Start_Cond(); //寫開始信號(hào)
Write8Bit(ReadDeviceAddress); //寫讀控制字
if(f_rom==1) goto restart;
for(i=0;i《(nLen-1);i++) //讀7個(gè)數(shù)
{ *nContent=Read8Bit();
Ack();
nContent++;
}
*nContent=Read8Bit(); //讀1個(gè)數(shù)
NoAck();
Stop_Cond(); //停止
nod2();
*/
errdo2:;//////////////////////////////////////讀數(shù)據(jù)超時(shí)處理
//outr:;
}
/*-------------------------------------------------------------
功能:從EEPROM中給定一個(gè)地址nAddr,連續(xù)寫NLEN個(gè)字節(jié)數(shù)據(jù)存放在以指針
nContent開頭的往下內(nèi)容
寫地址為0x000~0x7ff,用參數(shù)page07代表最高位的頁(yè)數(shù)(0~7)
------------------------------------------------------------*/
Write_Flash ( unsigned char xdata *nContent,unsigned char nAddr, unsigned int nLen) large reentrant
{
//unsigned char epromerr; //用來(lái)統(tǒng)計(jì)寫入出錯(cuò)的次數(shù)
unsigned char i,j; //for循壞用
//unsigned char xdata epadd; //用來(lái)作為rom目標(biāo)地址,要進(jìn)行計(jì)算
//unsigned char xdata len1; //rom第一段數(shù)據(jù)長(zhǎng)度,看eprom.c
//unsigned char xdata len2; //rom中間段數(shù)據(jù)頁(yè)數(shù),看eprom.c
//unsigned char xdata len3; //rom末尾段數(shù)據(jù)長(zhǎng)度,看eprom.c
//例如目標(biāo)首地址為5,要寫入20個(gè)字節(jié),用24c02(每頁(yè)8個(gè)字節(jié))
//那么len1=8-5%8=3,第一頁(yè)只能寫3個(gè)字節(jié)
//len2=(20-3)%8=1,最后頁(yè)只能寫1個(gè)字節(jié)
//len3=(20-3-1)/8=2,中間能完整的寫2頁(yè),剛好20個(gè)字節(jié)寫完
//目標(biāo)rom首地址離一頁(yè)末要寫的字節(jié)數(shù)
len1=numbyte_page-nAddr%numbyte_page;
//目標(biāo)rom最后頁(yè)寫入的字節(jié)數(shù)
len3=(nLen-len1)%numbyte_page;
//目標(biāo)rom中間能夠完整寫入的頁(yè)數(shù)
len2=(nLen-len1-len3)/numbyte_page;
if(len1》nLen) //假如寫入長(zhǎng)度不足把第一頁(yè)寫完,要更正參數(shù)
{ len1=nLen;
len2=0;
len3=0;
}
epromerr=0;
wrstart:
++epromerr;
ncon=nContent; //重新修正緩存對(duì)應(yīng)地址
if(epromerr》200)
goto errdo1;
//===========================
//寫第一段數(shù)據(jù)
//===========================
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++) //寫第一段數(shù)據(jù)
{ Write8Bit(*ncon);
if(f_rom==1)
goto wrstart;
ncon++;
}
Stop_Cond(); //首段寫完
//===========================
//寫中間的完整段數(shù)據(jù)
//===========================
if(len2》0)
{ for(j=0;j《len2;j++) //寫len2頁(yè)
{ epadd=nAddr+(numbyte_page)*j+len1; //修正寫入目標(biāo)偏移地址
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++) //寫完整的一頁(yè)
{ Write8Bit(*ncon);
if(f_rom==1)
goto wrstart;
ncon++;
}
Stop_Cond(); //一段寫完
}
}
//===========================
//寫末尾段數(shù)據(jù)
//===========================
if(len3》0)
{ epadd=nAddr+(numbyte_page)*len2+len1; //修正寫入目標(biāo)偏移地址
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++) //寫末尾段數(shù)據(jù)
{ Write8Bit(*ncon);
if(f_rom==1)
goto wrstart;
ncon++;
}
Stop_Cond(); //末尾段寫完
}
errdo1:;
評(píng)論
查看更多