51模拟IIC

#include <reg52.h> 
#include <intrins.h>

sbit SDA = P3^0;
sbit SCL = P3^1;

typedef unsigned char uchar;
typedef unsigned int  uint;

bit AckFlag;				  //应答标志位
#define At24c02ADDR 0xa0	 //AT24C02硬件地址
#define I2cWrite    0		//写方向位
#define I2cRead     1	   //读方向位

//延时5us函数
void delay5us()
{
    
    
	_nop_();
}


//起始信号
void IIC_START()
{
    
    
   SCL = 1;
   SDA = 1;
   delay5us();
   SDA = 0;
   delay5us();
}


//结束信号
void  IIC_STOP()
{
    
    

	SDA = 0;
	SCL = 1;
	delay5us();
	SDA = 1;
	delay5us();
}

//应答位,主机主动控制是否应答
void SendACK(bit i)
{
    
    
  SCL = 0;
  delay5us();
  if(i ==1)
  {
    
    
  //非应答
	 SDA = 1;
  }
  else SDA = 0;//应答
  	SCL = 1;  //拉高总线,让从机读SDA
	delay5us();//保持5us
	SCL = 0; //拉低时钟总线,允许SDA释放
	SDA = 1;//释放数据总线	

}

//从机应答检测
bit READACK()
{
    
    
  SCL  = 0;
  SCL  = 1;
  if(SDA)//NOACK
	{
    
    
		SCL = 0;
		return(1);//返回1
	}
	else//ACK
	{
    
    
		SCL = 0;
		return(0);//返回0
	}
}





//发送一个字节
void I2cSendByte(uchar dat)
{
    
    
	 uchar temp=0,i=0;
	 for(i = 0;i<8;i++)
	{
    
     	
		 temp = dat&(0x80);// 1000 000取出最高位
		 SCL =0;
		 delay5us();
		 if(temp) SDA = 1;
		 else SDA = 0;
		 delay5us();
		 SCL = 1; //拉高时钟,让从机读SDA
		  dat<<=1;	 
	}
		SCL = 0; //拉低时钟总线,允许SDA释放
		SDA = 1;//释放数据总线

	
}


//读取一个字节
uchar IIC_READ()
{
    
    
	uchar i, DAT;
	for(i=0;i<8;i++)
	{
    
    
	   DAT= DAT<<1;	 //数据左移1位,准备接收一位,或者放再后面写个if(i<7)
	   SCL = 0;	  //拉低时钟总线,允许从机控制SDA变化
	   SCL = 1;	  //拉高时钟总线,读取SDA上的数据
	   if(SDA)	 DAT |= 0X01;
	   else 	 DAT &= ~(1<<0);//这句可以省略	

	}
	  return (DAT);
}

//以上是IIC的初始化,下面的是对AT24C02进行的读操作





void At24c02Write(uchar ADDR,uchar DAT)
{
    
    
	IIC_START();
	I2cSendByte(At24c02ADDR+I2cWrite);	 	
	if(READACK())
	AckFlag = 1;//非应答
	else AckFlag = 0;//应答
	I2cSendByte(ADDR);
	if(READACK())	AckFlag = 1;//非应答
	else AckFlag = 0;//应答
	I2cSendByte(DAT);
	if(READACK())	AckFlag = 1;//非应答
	else AckFlag = 0;//应答
	IIC_STOP();
}

uchar At24c02Read(uchar ADDR)
{
    
    
	uchar DAT;
	IIC_START();//I2C起始信号
	I2cSendByte(At24c02ADDR + I2cWrite);//发送器件地址加读写方向位
	if(READACK())//读从机应答
		AckFlag = 1;	//NOACK
	else
		AckFlag = 0;	//ACK
	I2cSendByte(ADDR);//I2C发送一个字节
	READACK();//读从机应答
	IIC_START();//再次产生I2C起始信号
	I2cSendByte(At24c02ADDR + I2cRead);//发送器件地址加读写方向位 读
	if(READACK())//读从机应答
		AckFlag = 1;	//NOACK
	else
		AckFlag = 0;	//ACK
	DAT = IIC_READ();//读一字节
	SendACK(1);//主机发送非应答
	IIC_STOP(); //I2C停止信号
	return(DAT);//返回读出数据
			
}

int main()
{
    
    
	uchar re;
	At24c02Write(0X00,1000);
	re = At24c02Read(0X00);
	while(1);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/ABCisCOOL/article/details/107788828
IIC
今日推荐