#include<reg52.h>

#define W_cmd 0xa0   //写指令，以A开头，后有地址 ，参见手册 
#define R_cmd 0xa1   //读指令，以A开头，后有地址    

sbit SCL=P2^5;
sbit SDA=P2^4;
sbit WP=P2^6;

void delay(int x)
{
	int i,j;
	for(i=x;i>0;i--)
	for(j=110;j>0;j--);
}

void Dely24(void) 
{unsigned char i;
   for(i=0;i<20;i++); 
  //这个时间与器件、上拉电阻有很大关系，一般宜大不宜小
}

/*
void Dely24_10ms(void)
{unsigned int i;
   for(i=0;i<1000;i++);
}
//*************************************
void star24(void)      
{ Dely24();
  SDA=0;            
  Dely24();
  SCL=0;
  Dely24();           //产生开始时序
}
//**************************************
void stop24(void)
{ Dely24();
  SCL=1;
  Dely24();
  SDA=1;
  Dely24();           //产生结束时序
}
	*/ 

  unsigned char ReadByte(void)	//时钟下降沿读取一位
{
  unsigned char i,j;
  for(i=0;i<8;i++)      //循环读8位
     {
      SDA=1;         //置高，不影响后续读取，而且是必须的
      //Dely24();
      SCL=1;
      //Dely24();
      j<<=1;
      j|=(bit)SDA;   //读1位
    //  Dely24();
      SCL=0;
     // Dely24();

	  //SDA=0;
     }
   SDA=0;	      //必须的拉低
   return(j);
}


void SendByte(unsigned char SendDat)//时钟上升沿发送一位
{
   unsigned char i,j;
   for(i=0;i<8;i++)       //循环8次
    {j=SendDat;
     SDA=j&0x80;          //送出1位
     Dely24();             //必要的延时
     SCL=1;
     Dely24();             //必要的延时
     SCL=0;
     SendDat<<=1;         //为下一位做准备
    }
  // SDA=1;
   //Dely24();
   SCL=1;			      //必须拉高
   //Dely24();
   while(SDA==1);         //等待应答
   SCL=0;			      //为确保每写入一个字节前，SDA,SCL必须拉低
   SDA=0;
   //Dely24();
}



void WriIIC(unsigned char Wcmd,add,dat)
{ 
   SCL=1;
   SDA=1;
  // Dely24();
   //star24(); 
   SDA=0;           //开始时，SDA必须先于SCL拉低，必须的
   SCL=0;

   SendByte(Wcmd);      //命令，每写入一个字节前是SDA,SCL必须拉低
   SendByte(add);       //地址
   SendByte(dat);       //数据
  // stop24();
   SCL=1;	        //在写结束时，SCL必须先于SDA拉高，而且是必须的
   SDA=1;

   //Dely24_10ms();
}

 unsigned char ReadIIC(unsigned char Wcmd,add,Rcmd)
{  
   unsigned char i;
   SDA=1;
   SCL=1;
   //Dely24();
   //star24();
   SDA=0;            //开始
   SCL=0;

   SendByte(Wcmd);      //命令
   SendByte(add);       //选取存储区地址
   

   SDA=1;              //注意这里与写结束时的不同，从写到读的转换时，SDA须先于SCL拉高
   SCL=1;


   
//   star24();
   SDA=0;
   SCL=0;
   SendByte(Rcmd);      //读取
   i=ReadByte();
  // stop24();
   SCL=1;  
   SDA=1;
   return(i);
}


   void main(void)
{ 
  unsigned char i,get;
  //a0=a1=a2=0;                       //地址＝000
  //GND=0;                            //地＝0
  //VCC=1;                            //加电
  WP=0;                             // 允许写。
  
  //ls0=0;                               //打开led公共阳极
   
  for(i=0;i<100;i++)                 //向0到100的地址相应写入0到100                     
  WriIIC(W_cmd,i,i);
									 //从地址0到100读取数据
  for(i=0;i<100;i++)
  	{          // 向0x00地址写入0xa5
  		get=ReadIIC(W_cmd,i,R_cmd);      // 读0x00地址数据送P0
  		P1=get;
		delay(1000);

	}                            // 便于习惯，取反得到1=亮0=灭的指示
  while(1);
}