EEPROM 读写驱动 (AT24C256 , C8051F020)

吃了一根大葱 2009-07-02 09:58:16
MCU是 8051F020 ,,,,, EEPROM 是AT24C256

当初设计板子没注意, 结果SDA用的P45 ,SCL用的P46 。 因为P4口不能按位寻址,所以SDA和SCL都是用直接操作,很麻烦。
比如SDA = 1 就要写成P4 = P4 | 0x20 了。 所以把同学用的程序(AT89C52上调试通过的程序,用P3口调试的,比如P3 = P3 | 0x20 )改写了下,但是再自己的MCU上就是读取不成功。郁闷了2天了 ,说请高手看下,希望能有意见。谢谢!




/////////////////////////////////////
// Generated Initialization File //
/////////////////////////////////////

#include "C8051F020.h"
#include "INTRINS.H"

// Peripheral specific initialization functions,
// Called from the Init_Device() function
void Reset_Sources_Init()
{
WDTCN = 0xDE;
WDTCN = 0xAD;
}

void Oscillator_Init()
{
int i = 0;
OSCXCN = 0x67;
for (i = 0; i < 3000; i++); // Wait 1ms for initialization
while ((OSCXCN & 0x80) == 0);
OSCICN = 0x08;
}

// Initialization function for device,
// Call Init_Device() from your main program
void Init_Device(void)
{
Reset_Sources_Init();
Oscillator_Init();
}
//////////////////////////////以上部分是MCU的初始化,晶振的设置,关看门狗。



#include "INTRINS.H"
#define unchar unsigned char
#define unint unsigned int
#define uchar unsigned char
#define uint unsigned int
#define unlong unsigned long

data bank0=0x00 , addr=0x00 ;
uchar FromIIC = 0 , FromIIC2 ;
uchar pp ;

bit ISDA , ISCL ;

//*************** 端口分配 SDA=>P45 ; SCL=>P46 ; WP=>P47*************************/
/********************************************************************************
ISDA = 1 <===> P4 = P4 | 0x20 ; ISDA = 0 <===> P4 = P4 & 0xDF ;
ISCL = 1 <===> P4 = P4 | 0x40 ; ISCL = 0 <===> P4 = P4 & 0xBF ;
*******************************************************************************/

/*****************************延时程序****************************************/
void delay_ms (uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<1000;j++)
;
}


//-----------EEPROM读写模块开始-----------------------------------------------
//=============================================

//Wait for some time to get proper I2C timing //EEPROM 开始
void I2cWait (void)
{
_nop_();
_nop_();
}
/*=============================================
I2c start condition
SDA high->low while SCL=high
=============================================*/
void I2cStart(void)
{
P4 = P4 | 0x20 ; //ISDA = 1;
P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();
P4 = P4 & 0xDF ; //ISDA = 0;
I2cWait();
P4 = P4 & 0xBF ; //ISCL = 0;
}
/*=============================================
I2c stop condition
SDA low->high while SCL=high
=============================================*/
void I2cStop(void)
{
P4 = P4 & 0xDF ; //ISDA = 0;
I2cWait();
P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();
P4 = P4 | 0x20 ; //ISDA = 1;
}
//master transfer data to slave and return acknowledge bit
bit I2cSentByte(uchar bytedata)
{
uchar i;
bit ack;

P4 = P4 | 0x20 ; //ISDA = 1;
for(i=0; i<8; i++)
{
bytedata = _crol_(bytedata, 1);
if(bytedata & 0x01)
P4 = P4 | 0x20 ; //ISDA = 1;
else
P4 = P4 & 0xDF ; //ISDA = 0;

P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();
P4 = P4 & 0xBF ; //ISCL = 0;
I2cWait();
}
P4 = P4 | 0x20 ; //ISDA = 1;
I2cWait();
P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();
ack = P4 & 0x20 ; //ack = ISDA;
P4 = P4 & 0xBF ; //ISCL = 0;
I2cWait();
return ack;
}

//slave transfer data to master
uchar I2cReceiveByte(void)
{
uchar i, bytedata = 0;

//Receive byte (MSB first)
for(i=0; i<8; i++)
{
P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();

bytedata <<= 1;
ISDA = P4 & 0x20 ;
if ( ISDA ) bytedata |= 0x01; ///////////

P4 = P4 & 0xBF ; //ISCL = 0;
I2cWait();
}
return bytedata;
}

//Master send acknowledge bit to slave
//acknowledge="0",non-acknowledge="1"
void SendAcknowledge (bit ack)
{
//ISDA = ack
if ( ack )
P4 = P4 | 0x20 ; //ISDA = 1 ;
else
P4 = P4 & 0xDF ; //ISDA = 0 ;
P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();
P4 = P4 & 0xBF ; //ISCL = 0;
}


//do 1 times, and un-check acknowledge
void I2cByteWrite(uchar device, uchar address, uchar bytedata)
{
I2cStart();
I2cSentByte (device);
I2cSentByte (address);
I2cSentByte (bytedata);
I2cStop();
delay_ms(10);
}
uchar I2cByteRead(uchar device, uchar address)
{
uchar bytedata;

I2cStart();
I2cSentByte(device);
I2cSentByte(address);
I2cStart();
// I2cSentByte (device|0x01);
I2cSentByte(device+0x01);
bytedata = I2cReceiveByte();
SendAcknowledge(1);
I2cStop();
return bytedata;
}


//Write byte data into EEPROM
void EEPROMByteWrite0(uchar bank, uchar addr, uchar value) //bank,addr->地址,value->所写值
{
I2cByteWrite((0xA0|bank), addr, value);
}
void EEPROMDataWrite(uchar bank, uchar addr, uchar *dat, uchar n) //写数组
{
uchar i;
for(i=0x00;i<n;i++)
EEPROMByteWrite0( bank, addr+i,*(dat+i));
}
//Read byte data from EEPROM
uchar EEPROMByteRead0(uchar bank, uchar addr) //bank,addr->地址
{
return(I2cByteRead((0xA0|bank), addr));
}
void EEPROMDataRead(uchar bank, uchar addr, uchar *dat, uchar n) //读数组
{
uchar i;
for(i=0x00;i<n;i++)
*(dat+i)=EEPROMByteRead0(bank,addr+i);
}
//-----------EEPROM读写模块结束-----------------------------------------------



void main ()
{
Init_Device();
pp = 2 ;
P4 = 0x00 ;

while ( 1 )
{
delay_ms ( 1000 ) ; //调试用的看P4口是不是通的
P4 = P4 | 0x01 ; //调试用的看P4口是不是通的
delay_ms ( 1000 ) ;
P4 = P4 & 0xFE ;
delay_ms ( 1000 ) ;

EEPROMByteWrite0 ( bank0 , 0x00 + addr , pp ) ; //写
FromIIC = EEPROMByteRead0( bank0 , addr) ; //总是读出来的255 ,而不是2
}

}
...全文
966 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
吃了一根大葱 2009-07-05
  • 打赏
  • 举报
回复
多谢各位的关注
最终问题得以解决,硬件这东西,出问题会有太多的原因
谢谢!大家
Great_Bug 2009-07-04
  • 打赏
  • 举报
回复
把标准51的程序移植到C8051要注意IO配置...
guetcw 2009-07-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 youngbird221 的回复:]
应该有速度不一样 ,但是等几秒总会写进去吧
但是都没有成功!
[/Quote]
你怎么不拿个酷睿2去模拟I2C,一般I2C的最高速度就是400K,I2cWait就两个NOP,你算算你的时序的速度都是多少了,
C8051F的速度都是c51的十几倍,你就是等一年也写不进去
dceacho 2009-07-03
  • 打赏
  • 举报
回复
检查下口线是不是缺上拉电阻
EEPROMByteWrite0 ( bank0 , 0x00 + addr , pp ) ; bank0这个器件地址和EEPROM得A0,A1,(A2)是对应的?
附一个我用的程序

#include "W79E824.H"
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char

//#define WP=0 _nop_()
//#define WP=1 _nop_()
bit flag;
#define SCL P12
sbit SDA1=P1^3;
//sbit WP=P3^4;

/*EEPROM Fuction*/
void delay(void)
{
uchar i;
for(i=20;i>0;i--)
_nop_();
}
/*
void delayij(uchar i,uchar j)
{
uchar m,n;
for(m=0;m<i;m++)
{
for(n=j;n>0;n--); //ÑÓʱ124*8+10=1002us
{
_nop_();
}
}
}
*/

/*********************************************************
**Ãû³Æ£ºI2C_Start
**¹¦ÄÜ£ºÆô¶¯I2C
**ÊäÈ룺ÎÞ
**·µ»Ø£ºÎÞ
*********************************************************/
void I2C_Start()
{
SDA1=1;
delay();
SCL=1;
delay();
SDA1=0;
delay();
SCL=0;
}

/**********************************************************
**Ãû³Æ£ºI2C_Stop
**¹¦ÄÜ£ºÍ£Ö¹I2C
**ÊäÈ룺ÎÞ
**·µ»Ø£ºÎÞ
**********************************************************/
void I2C_Stop()
{
SDA1=0;
delay();
SCL=1;
delay();
SDA1=1;
delay();
}




/**********************************************************
**Ãû³Æ£ºAck
**¹¦ÄÜ£ºÓ¦´ðÐźÅ
**ÊäÈ룺ÎÞ
**·µ»Ø£ºÎÞ
**********************************************************/
void Ack()
{
SDA1=0;
delay();
SCL=1;
delay();
SCL=0;
delay();
SDA1=1;
delay();
}



/********************************************************
**Ãû³Æ£ºNoAck
**¹¦ÄÜ£º·¢ËÍ·ÇÓ¦´ðÐźÅ
**ÊäÈ룺ÎÞ
**·µ»Ø£ºÎÞ
********************************************************/
void NoAck()
{
SDA1=1;
delay();
SCL=1;
delay();
SCL=0;
delay();
SDA1=0;
delay();
}




/********************************************************
**Ãû³Æ£ºTest_Ack()
**¹¦ÄÜ£º¼ì²âÓ¦´ðλ
**ÊäÈ룺ÎÞ
**·µ»Ø£ºflag,ÓÐÓ¦´ðʱflagΪ0£¬ÎÞÓ¦´ðʱflagΪ1
*********************************************************/
bit Test_Ack()
{
SCL=0;
SDA1=1;//¶ÁÈëÊý¾Ý
_nop_();_nop_();_nop_();_nop_();
SCL=1;
_nop_();_nop_();_nop_();_nop_();
if(SDA1==0)
flag=1;
else flag=0;
SCL=0;
return(flag);
}



/********************************************************
**Ãû³Æ£ºSendData()
**¹¦ÄÜ£º·¢ËÍÒ»×Ö½ÚÊý¾Ý
**ÊäÈ룺buffer
**·µ»Ø£º
*******************************************************/
void SendData(uchar buffer)
{
uchar BitCnt=8;//Ò»×Ö½Ú8λ
uchar temp=0;
do
{
temp=buffer;
SCL=0;
delay();
if((temp&0x80)==0) //
SDA1=0;
else
SDA1=1;
delay();
SCL=1;
temp=_crol_(buffer,1);//rl buff
buffer=temp;
BitCnt--;
}
while(BitCnt);
SCL=0;
}

/**************************************************************
**Ãû³Æ£ºuint ReceiveData()
**¹¦ÄÜ£º½ÓÊÕÒ»×Ö½ÚÊý¾Ý
**ÊäÈ룺
**·µ»Ø£ºucReceData
**˵Ã÷£º½«½ÓÊÕµÄÊý¾Ý´æ·ÅÔÚucReceDataÖÐ
**************************************************************/
uchar ReceiveData()
{
uchar ucReceData;
uchar BitCnt=8;
uchar temp=0;
SDA1=1;//¶ÁÈëÊý¾Ý
do
{
SCL=0;
delay();
SCL=1;
delay();
if(SDA1==1)
ucReceData=ucReceData|0x01;
else
ucReceData=ucReceData&0x0fe;
if(BitCnt-1)
{
temp=_crol_(ucReceData,1);
ucReceData=temp;
}
BitCnt--;
}
while(BitCnt);
SCL=0;
return(ucReceData);
}

/*************************************************************
**bit WriteNByte()
**24C64ÖÐдÈë¶à×Ö½ÚÊý¾Ý
**
** *s-data to write sbbab-data address 8bits low
**sla-device address suba-data address 8bits high n-bytes(n<=32)
**************************************************************
bit WriteNByte(uchar sla,uchar suba,uchar subab,uchar *s,uint n)
{
uchar i;
I2C_Start();
SendData(sla);
Test_Ack();
if(flag==0) return(0);
SendData(suba);
Test_Ack();
if(flag==0) return(0);

SendData(subab);
Test_Ack();
if(flag==0) return(0);

for(i=0;i<n;i++)
{
SendData(*(s+i));
Test_Ack();
if(flag==0) return(0);
}
I2C_Stop();
return(1);
}
*/
bit WriteNByte(uchar sla,uint addr,uchar *s,uint n)
{
uchar i;
uchar suba;
uchar subab;
suba=(addr>>8);
subab=addr&0x00ff;
I2C_Start();
SendData(sla);
Test_Ack();
if(flag==0) return(0);
SendData(suba);
Test_Ack();
if(flag==0) return(0);

SendData(subab);
Test_Ack();
if(flag==0) return(0);

for(i=0;i<n;i++)
{
SendData(*(s+i));
Test_Ack();
if(flag==0) return(0);
}
I2C_Stop();
return(1);
}

/*************************************************************
**bit ReadNByte()
**24C64ÖжÁ³öN×Ö½ÚÊý¾Ý£¨n<=32)
**
**
**
**************************************************************
bit ReadNByte(uchar sla,uchar suba,uchar subab,uchar *p,uint n)
{
uchar i;
I2C_Start();
SendData(sla);
Test_Ack();
if(flag==0){return(0);}
SendData(suba);
Test_Ack();
if(flag==0){return(0);}

SendData(subab);
Test_Ack();
if(flag==0){return(0);}

I2C_Start();
SendData(sla+1);
Test_Ack();
if(flag==0){return(0);}
for(i=0;i<n-1;i++)
{
*(p+i)=ReceiveData();
Ack();
}
*(p+n-1)=ReceiveData();

NoAck();
I2C_Stop();
return(1);
}
*/
bit ReadNByte(uchar sla,uint addr,uchar *p,uint n)
{
uchar i;
uchar suba;
uchar subab;
suba=(addr>>8);
subab=addr&0x00ff;
I2C_Start();
SendData(sla);
Test_Ack();
if(flag==0){return(0);}
SendData(suba);
Test_Ack();
if(flag==0){return(0);}

SendData(subab);
Test_Ack();
if(flag==0){return(0);}

I2C_Start();
SendData(sla+1);
Test_Ack();
if(flag==0){return(0);}
for(i=0;i<n-1;i++)
{
*(p+i)=ReceiveData();
Ack();
}
*(p+n-1)=ReceiveData();

NoAck();
I2C_Stop();
return(1);
}

/*
bit ReadNByte(uchar sla,uchar suba,uchar subab,uchar *p,uint n)
{
uchar i;
ENS1=1;
I2DAT=sla;
STA=1;
while(SI==0);
SI=0;
// if(AA==0)return(0);
I2DAT=suba;
while(SI==0);
SI=0;
// if(AA==0)return(0);
I2DAT=subab;
while(SI==0);
SI=0;
// if(AA==0)return(0);
for(i=0;i<n-1;i++)
{
while(SI==0);
*(p+i)=I2DAT;
SI=0;
}
*(p+n-1)=I2DAT;
STO=1;
ENS1=0;
return(1);
}*/

/*
bit ClearROM(uchar s)
{
uint i;
// uchar j;
I2C_Start();
SendData(0xa0);
Test_Ack();
if(flag==0) return(0);
SendData(0x00);
Test_Ack();
if(flag==0) return(0);

SendData(0x00);
Test_Ack();
if(flag==0) return(0);

for(i=0;i<0x8000;i++)
{
// j=i*100/0x8000;
// PrintNumber(36,5,j);
SendData(s);
Test_Ack();
if(flag==0) return(0);
}
I2C_Stop();
return(1);
}
/*========================================*/
iknowjeanzxf 2009-07-03
  • 打赏
  • 举报
回复
你用的单片机资料我没有找到,你如果能确认P4口已经能输入输出了,就可以了。
请将各函数按如下方式修改。然后试验一下。如果编译不过去,有可能是网页导致的格式不正确,请理解意思自己修改就可以了。
另看最后的说明。如果仍然解决不了你的问题,那么请再仔细阅读EEPROM的时序图,查看一下时序,和你的延时时间。最主要是要理解过程。
另,请不要认为别人的程序都是对的,因为有时候环境不一样,或者考虑不周全,包括我写的这些。


void I2cStart(void)
{
P4 = P4 | 0x20 ; //ISDA = 1;
P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();
P4 = P4 & 0xDF ; //ISDA = 0;
I2cWait();
P4 = P4 & 0xBF ; //ISCL = 0;
I2cWait(); //这个是我加的 090703
}

//应该在函数后边加 SCL=0;。
void I2cStop(void)
{
P4 = P4 & 0xDF ; //ISDA = 0;
P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();
P4 = P4 | 0x20 ; //ISDA = 1;
P4 = P4 & 0xBF ; //ISCL = 0; 这个是我加的 090703
I2cWait(); //这个是我加的 090703
}

bit I2cSentByte(uchar bytedata)
{
uchar i;
bit ack;

P4 = P4 | 0x20 ; //ISDA = 1;
for(i=0; i <8; i++)
{
//*******请确认这段代码是将数据按从高到低发送,因为我不知道_crol_()这个函数的作用
bytedata = _crol_(bytedata, 1);
if(bytedata & 0x01)
P4 = P4 | 0x20 ; //ISDA = 1;
else
P4 = P4 & 0xDF ; //ISDA = 0;
//*******请确认上边代码是将数据按从高到低发送,因为我不知道_crol_()这个函数的作用


P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();
P4 = P4 & 0xBF ; //ISCL = 0;
I2cWait();
}

//P4 = P4 | 0x20 ; //ISDA = 1; 这个是我去掉的 090703
I2cWait();
P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();

//ack = P4 & 0x20 ; //ack = ISDA; 这个是我去掉的 090703
while( (P4 & 0x20) == 0x20){} //我加的,等待回复ACK 有可能导致死循环。090703
P4 = P4 & 0xBF ; //ISCL = 0;
I2cWait();
return ack;
}

uchar I2cByteRead(uchar device, uchar address)
{
uchar bytedata;

I2cStart();
I2cSentByte(device);
I2cSentByte(address);
I2cStart();
// I2cSentByte (device|0x01);
I2cSentByte(device+0x01);
bytedata = I2cReceiveByte();
//SendAcknowledge(1); // 这个是我去掉的 090703
I2cStop();
return bytedata;
}

uchar I2cReceiveByte(void)
{
uchar i, bytedata = 0;

//Receive byte (MSB first)
for(i=0; i <8; i++)
{
P4 = P4 | 0x40 ; //ISCL = 1;
I2cWait();
//bytedata < <= 1; //这句话能编译过去吗 <<中间有空格
bytedata <<= 1; // 我修改的。090703
ISDA = P4 & 0x20 ;
if ( ISDA ) bytedata |= 0x01; ///////////
P4 = P4 & 0xBF ; //ISCL = 0;
I2cWait();
}
return bytedata;
}

I2C总线注意事项:
1,要区分什么时候是读操作,什么时候是写操作。比如随机读(目前的程序是随机读),只有读数据周期是读操作,其他几个周期都是写操作。
2,要区分ACK信号由谁发出的。当读的时候,ACK信号由MCU->eeprom SDA输出。当写的时候ACK信号由eeprom->MCU SDA输入。
3,在一帧操作中(例如一个完整的读字节或写字节),有全写的操作,但是没有全读的操作
4,当写完一个字节的时候,或写完一个页(8字节),必须要有延时,否则其他操作不能进行
5,一定要严格遵守时序(顺序,不是时间长短),否则会出错。比如连续读时,最后一个字节是没有ACK位的,如果MCU发出去了,则后边的操作会出错。
6,延时时间可以长,但不可以短。 你可以试下,如果还不成功,可能是延时时间短了。
7,当写页操作时,必须以8的整数倍为起始地址,如果不这样,写的只是本8字节页中,最后的几个字节,剩余从头写(循环写)




吃了一根大葱 2009-07-03
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 zyzhang365 的回复:]
..................
[/Quote]

下面是在同学的AT89C52上测试的程序,只是把P4口改成P3,其他都没改动,AT89C52上测试时通过的,可以读出来。
AT89C52的P3口可以按位寻址,但是为了测试我的程序,改成了字节操作


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "reg52.h"
#include <intrins.h>
#define unint unsigned int
#define uchar unsigned char
#define uint unsigned int
#define unlong unsigned long

bit ISDA , ISCL ;
data bank0=0x00 , bank1=0x01 , addr=0x00 ;
uchar FromIIC = 0 ;
uchar pp ;

//*************** 端口分配 SDA=>P37 ; SCL=>P36 *************************/
/********************************
ISDA = 1 P3 = P3 | 0x80 ;
ISDA = 0 P3 = P3 & 0x7F ;
ISCL = 1 P3 = P3 | 0x40 ;
ISCL = 0 P3 = P3 & 0xBF ;
********************************/

/*****************************延时程序****************************************/
void delay_ms (uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<1000;j++)
;
}


//-----------EEPROM读写模块开始-----------------------------------------------
//=============================================

//Wait for some time to get proper I2C timing //EEPROM 开始
void I2cWait (void)
{
_nop_();
_nop_();
}
/*=============================================
I2c start condition
SDA high->low while SCL=high
=============================================*/
void I2cStart(void)
{
P3 = P3 | 0x80 ; //ISDA = 1;
P3 = P3 | 0x40 ; //ISCL = 1;
I2cWait();
P3 = P3 & 0x7F ; //ISDA = 0;
I2cWait();
P3 = P3 & 0xBF ; //ISCL = 0;
}
/*=============================================
I2c stop condition
SDA low->high while SCL=high
=============================================*/
void I2cStop(void)
{
P3 = P3 & 0x7F ; //ISDA = 0;
I2cWait();
P3 = P3 | 0x40 ; //ISCL = 1;
I2cWait();
P3 = P3 | 0x80 ; //ISDA = 1;
}
//master transfer data to slave and return acknowledge bit
bit I2cSentByte(uchar bytedata)
{
uchar i;
bit ack;

P3 = P3 | 0x80 ; //ISDA = 1;
for(i=0; i<8; i++)
{
bytedata = _crol_(bytedata, 1);
if(bytedata & 0x01)
P3 = P3 | 0x80 ; //ISDA = 1;
else
P3 = P3 & 0x7F ; //ISDA = 0;

P3 = P3 | 0x40 ; //ISCL = 1;
I2cWait();
P3 = P3 & 0xBF ; //ISCL = 0;
I2cWait();
}
P3 = P3 | 0x80 ; //ISDA = 1;
I2cWait();
P3 = P3 | 0x40 ; //ISCL = 1;
I2cWait();
ack = P3 & 0x80 ; //ack = ISDA;
P3 = P3 & 0xBF ; //ISCL = 0;
I2cWait();
return ack;
}

//slave transfer data to master
uchar I2cReceiveByte(void)
{
uchar i, bytedata = 0;

//Receive byte (MSB first)
for(i=0; i<8; i++)
{
P3 = P3 | 0x40 ; //ISCL = 1;
I2cWait();

bytedata <<= 1;
ISDA = P3 & 0x80 ;
if ( ISDA ) bytedata |= 0x01; //////////////////////

P3 = P3 & 0xBF ; //ISCL = 0;
I2cWait();
}
return bytedata;
}

//Master send acknowledge bit to slave
//acknowledge="0",non-acknowledge="1"
void SendAcknowledge (bit ack)
{
//ISDA = ack
if ( ack )
P3 = P3 | 0x80 ; //ISDA = 1 ;
else
P3 = P3 & 0x7F ; //ISDA = 0 ;
P3 = P3 | 0x40 ; //ISCL = 1;
I2cWait();
P3 = P3 & 0xBF ; //ISCL = 0;
}


//do 1 times, and un-check acknowledge
void I2cByteWrite(uchar device, uchar address, uchar bytedata)
{
I2cStart();
I2cSentByte (device);
I2cSentByte (address);
I2cSentByte (bytedata);
I2cStop();
delay_ms(10);
}
uchar I2cByteRead(uchar device, uchar address)
{
uchar bytedata;

I2cStart();
I2cSentByte(device);
I2cSentByte(address);
I2cStart();
// I2cSentByte (device|0x01);
I2cSentByte(device+0x01);
bytedata = I2cReceiveByte();
SendAcknowledge(1);
I2cStop();
return bytedata;
}


//Write byte data into EEPROM
void EEPROMByteWrite0(uchar bank, uchar addr, uchar value) //bank,addr->地址,value->所写值
{
I2cByteWrite((0xA0|bank), addr, value);
}
void EEPROMDataWrite(uchar bank, uchar addr, uchar *dat, uchar n) //写数组
{
uchar i;
for(i=0x00;i<n;i++)
EEPROMByteWrite0( bank, addr+i,*(dat+i));
}
//Read byte data from EEPROM
uchar EEPROMByteRead0(uchar bank, uchar addr) //bank,addr->地址
{
return(I2cByteRead((0xA0|bank), addr));
}
void EEPROMDataRead(uchar bank, uchar addr, uchar *dat, uchar n) //读数组
{
uchar i;
for(i=0x00;i<n;i++)
*(dat+i)=EEPROMByteRead0(bank,addr+i);
}
//-----------EEPROM读写模块结束-----------------------------------------------


void main ()
{
// Init_Device();
pp = 2 ;
P3 = 0x00 ;

while(1){
EEPROMByteWrite0 ( bank0 , 0x00 + addr , pp ) ;
FromIIC = EEPROMByteRead0( bank0 , addr) ;}

}

下面是在同学的AT89C52上测试的程序,只是把P4口改成P3,其他都没改动,AT89C52上测试时通过的,可以读出来。
AT89C52的P3口可以按位寻址,但是为了测试我的程序,改成了字节操作

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
吃了一根大葱 2009-07-03
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 zyzhang365 的回复:]
//master transfer data to slave and return acknowledge bit
bit I2cSentByte(uchar bytedata)
{

for(i=0; i <8; i++)
{

}
P4 = P4 | 0x20 ; //ISDA = 1;
I2cWait();
P4 = P4 | 0x40 ; //ISCL = 1; // 这里为什么还要送一个bit出去?
I2cWait();
ack = P4 & 0x20 ; //ack = ISDA;
P4 = P4 & 0xBF ; //ISCL = 0;

[/Quote]

我也觉得是没写进去 ,感觉是8051F020设置的问题。 EEPROM读写的时序应该没问题,程序测试过可以读写。
吃了一根大葱 2009-07-03
  • 打赏
  • 举报
回复
应该有速度不一样 ,但是等几秒总会写进去吧
但是都没有成功!
zyzhang365 2009-07-03
  • 打赏
  • 举报
回复
//master transfer data to slave and return acknowledge bit
bit I2cSentByte(uchar bytedata)
{

for(i=0; i <8; i++)
{

}
P4 = P4 | 0x20 ; //ISDA = 1;
I2cWait();
P4 = P4 | 0x40 ; //ISCL = 1; // 这里为什么还要送一个bit出去?
I2cWait();
ack = P4 & 0x20 ; //ack = ISDA;
P4 = P4 & 0xBF ; //ISCL = 0;
I2cWait();
return ack;
}


如果你读回的是255,也就是0xff, 说明根本没有写成功。
guetcw 2009-07-03
  • 打赏
  • 举报
回复
人家的用的是C52,你用的8051,速度都不一样,能直接用吗,插入点延时
FPGAEEPROM芯片AT24C02实验Verilog逻辑源码Quartus11.0工程文件, FPGA型号为CYCLONE4E系列中的EP4CE6E22C8,可以做为你的学习设计参考。 module iic_com( clk,rst_n, sw1,sw2, scl,sda, dis_data ); input clk; // 50MHz input rst_n; //复位信号,低有效 input sw1,sw2; //按键1、2,(1按下执行入操作,2按下执行操作) output scl; // 24C02的时钟端口 inout sda; // 24C02的数据端口 output[7:0] dis_data; //数码管显示的数据 //按键检测 reg sw1_r,sw2_r; //键值锁存寄存器,每20ms检测一次键值 reg[19:0] cnt_20ms; //20ms计数寄存器 always @ (posedge clk or negedge rst_n) begin if(!rst_n) cnt_20ms <= 20'd0; else cnt_20ms <= cnt_20ms+1'b1; //不断计数 end always @ (posedge clk or negedge rst_n) begin if(!rst_n) begin sw1_r <= 1'b1; //键值寄存器复位,没有键盘按下时键值都为1 sw2_r <= 1'b1; end else if(cnt_20ms == 20'hfffff) begin sw1_r <= sw1; //按键1值锁存 sw2_r <= sw2; //按键2值锁存 end end //--------------------------------------------- //分频部分 reg[2:0] cnt; // cnt=0:scl上升沿,cnt=1:scl高电平中间,cnt=2:scl下降沿,cnt=3:scl低电平中间 reg[8:0] cnt_delay; //500循环计数,产生iic所需要的时钟 reg scl_r; //时钟脉冲寄存器 always @ (posedge clk or negedge rst_n) begin if(!rst_n) cnt_delay <= 9'd0; else if(cnt_delay == 9'd499) cnt_delay <= 9'd0; //计数到10us为scl的周期,即100KHz else cnt_delay <= cnt_delay+1'b1; //时钟计数 end always @ (posedge clk or negedge rst_n) begin if(!rst_n) cnt <= 3'd5; else begin case (cnt_delay) 9'd124: cnt <= 3'd1; //cnt=1:scl高电平中间,用于数据采样 9'd249: cnt <= 3'd2; //cnt=2:scl下降沿 9'd374: cnt <= 3'd3; //cnt=3:scl低电平中间,用于数据变化 9'd499: cnt <= 3'd0; //cnt=0:scl上升沿 default: cnt <= 3'd5; endcase end end `define SCL_POS (cnt==3'd0) //cnt=0:scl上升沿 `define SCL_HIG (cnt==3'd1) //cnt=1:scl高电平中间,用于数据采样 `define SCL_NEG (cnt==3'd2) //cnt=2:scl下降沿 `define SCL_LOW (cnt==3'd3) //cnt=3:scl低电平中间,用于数据变化 always @ (posedge clk or negedge rst_n) begin if(!rst_n) scl_r <= 1'b0; else if(cnt==3'd0) scl_r <= 1'b1; //scl信号上升沿

27,382

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧