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; //用來統(tǒng)計寫入出錯的次數
uint xdata epadd; //用來作為rom目標寫入的首地址,要進行計算
uchar xdata page07; //每256個字節(jié)當一頁,請注意不要寫錯頁
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每一頁的字節(jié)數
#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_();
}
/*-------------------------------------------------------------
功能:發(fā)起始信號
------------------------------------------------------------*/
void Start_Cond()
{
SDA = 1;
nod2();
SCL = 1;
nod2();
SDA = 0;
nod2();
SCL = 0;
nod2();
}
/*-------------------------------------------------------------
功能:發(fā)停止信號
------------------------------------------------------------*/
void Stop_Cond()
{
SDA = 0;
nod2();
SCL = 1;
nod2();
SDA = 1;
nod2();
SCL = 0;
nod2();
}
/*-------------------------------------------------------------
功能:發(fā)確認信號
------------------------------------------------------------*/
void Ack()
{
SDA = 0;
nod2();
SCL = 1;
nod2();
SCL = 0;
nod2();
SDA = 1;
nod2();
}
/*-------------------------------------------------------------
功能:發(fā)無確認信號
------------------------------------------------------------*/
void NoAck()
{
SDA = 1;
nod2();
SCL = 1;
nod2();
SCL = 0;
nod2();
SDA = 0;
nod2();
}
/*-------------------------------------------------------------
功能:讀一個字節(jié)數據
------------------------------------------------------------*/
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);
}
/*-------------------------------------------------------------
功能:寫一個字節(jié)數據
------------------------------------------------------------*/
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中給定一個地址連續(xù)讀NLEN個字節(jié)數據存放在以指針
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個字節(jié),用24c02(每頁8個字節(jié))
//那么len1=8-5%8=3,第一頁只能讀3個字節(jié)
//len3=(20-3)%8=1,最后頁只能讀1個字節(jié)
//len2=(20-3-1)/8=2,中間能完整的讀2頁,剛好20個字節(jié)讀完
//目標rom首地址離一頁末要讀的字節(jié)數
len1=numbyte_page-nAddr%numbyte_page;
//目標rom最后頁讀入的字節(jié)數
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個字節(jié)
{ *ncon=Read8Bit();
Ack();
ncon++;
}
*ncon=Read8Bit(); //讀1個字節(jié)
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,連續(xù)寫NLEN個字節(jié)數據存放在以指針
nContent開頭的往下內容
寫地址為0x000~0x7ff,用參數page07代表最高位的頁數(0~7)
------------------------------------------------------------*/
Write_Flash ( unsigned char xdata *nContent,unsigned char nAddr, unsigned int nLen) large reentrant
{
//unsigned char epromerr; //用來統(tǒng)計寫入出錯的次數
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個字節(jié),用24c02(每頁8個字節(jié))
//那么len1=8-5%8=3,第一頁只能寫3個字節(jié)
//len2=(20-3)%8=1,最后頁只能寫1個字節(jié)
//len3=(20-3-1)/8=2,中間能完整的寫2頁,剛好20個字節(jié)寫完
//目標rom首地址離一頁末要寫的字節(jié)數
len1=numbyte_page-nAddr%numbyte_page;
//目標rom最后頁寫入的字節(jié)數
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:;
評論
查看更多