⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 独创的使用51单片机模拟I2C总线协议 每个功能函数都有详细的说明
💻 C
字号:
 /**————————————————————
 〖说明〗I2C总线驱动程序(用两个普通IO模拟I2C总线)
 包括100Khz(T=10us)的标准模式(慢速模式)选择,
 和400Khz(T=2.5us)的快速模式选择,
 默认11.0592Mhz的晶振。
 〖文件〗I2C.C 
 〖作者〗yeaman
 〖修改〗2006/12/21  命令:BB 接收8个数据并写入;FF 读出所有内容。
 〖版本〗V1.00 Build 1221
 —————————————————————*/
 #include<at89x51a.h> 
 #include <intrins.h> 
 #ifndef SDA
 #define SDA P0_0
 #define SCL P0_1
 #endif

 

 #define uchar unsigned char
 #define uint unsigned int
 #define Byte unsigned char
 #define Word unsigned int
 #define bool bit
 #define true 1
 #define false 0

 #define SomeNOP(); _nop_();_nop_();_nop_();_nop_();_nop_();
 /**--------------------------------------------------------------------------------
 调用方式:void I2CStart(void) 
 函数说明:私有函数,I2C专用
 ---------------------------------------------------------------------------------*/
 void I2CStart(void)
 {
 //EA=0;
 SDA=1; SCL=1; SomeNOP();//INI
 SDA=0; SomeNOP(); //START
 SCL=0;
 }

 /**--------------------------------------------------------------------------------
 调用方式:void I2CStop(void) ﹫2001/07/0 4
 函数说明:私有函数,I2C专用
 ---------------------------------------------------------------------------------*/
 void I2CStop(void)
 {
 SCL=0; SDA=0; SomeNOP(); //INI
 SCL=1; SomeNOP(); SDA=1; //STOP
 //EA=1;
 }

 /**--------------------------------------------------------------------------------
 调用方式:bit I2CAck(void) ﹫2001/07/0 4
 函数说明:私有函数,I2C专用,等待从器件接收方的应答
 ---------------------------------------------------------------------------------*/
 bool WaitAck(void)
 {
 uchar errtime=255;//因故障接收方无ACK,超时值为255。
 SDA=1;SomeNOP();
 SCL=1;SomeNOP();
 while(SDA) 
 {errtime--; 
 if (!errtime) 
 {I2CStop();
 //SystemError=0x11;
 return false;
 }
 }
 SCL=0;
 return true;

 }

 /**--------------------------------------------------------------------------------
 调用方式:void SendAck(void) ﹫2001/07/0 4
 函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
 ---------------------------------------------------------------------------------*/
 /*void SendAck(void)
 {
 SDA=0; SomeNOP();
 SCL=1; SomeNOP();
 SCL=0;
 }
 /**--------------------------------------------------------------------------------
 调用方式:void SendAck(void) ﹫2001/07/0 4
 函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。
 }**--------------------------------------------------------------------------------*/
 void SendNotAck(void)
 {
 SDA=1; SomeNOP();
 SCL=1; SomeNOP();
 SCL=0;
 }

 /**--------------------------------------------------------------------------------
 调用方式:void I2CSend(uchar ch) ﹫2001/07/0 5
 函数说明:私有函数,I2C专用
 ---------------------------------------------------------------------------------*/
 /*void I2CSendByte(Byte ch)
 {
 uchar i=8;
 while (i--)
 {
 SCL=0;_nop_();
 SDA=(bit)(ch&0x80); ch<<=1; SomeNOP();
 SCL=1; SomeNOP();
 }
 SCL=0;
 }*/

 //-------------------------------------------------------------------------
void I2CSendByte(uchar Data)
{
uchar BitCounter=8; 				//位数控制
uchar temp; 						//中间变量控制
do
{
temp=Data;
SCL=0;
SomeNOP();
if((temp&0x80)==0x80)			//如果最高位是1
SDA=1;
else
SDA=0;
SCL=1;
SomeNOP();
temp=Data<<1; 					//RLC
Data=temp;
BitCounter--;
}while(BitCounter);
SCL=0;
}

 /**--------------------------------------------------------------------------------
 调用方式:uchar I2CReceive(void) ﹫2001/07/0 5
 函数说明:私有函数,I2C专用
 ---------------------------------------------------------------------------------*/
 Byte I2CReceiveByte(void)
 {
 uchar i=8;
 Byte ddata=0;
 SDA=1;
 while (i--)
 {
 ddata<<=1;
 SCL=0;SomeNOP();
 SCL=1;SomeNOP();
 ddata|=SDA;
 }
 SCL=0;
 return ddata;
 }

 //---------------------------------------------------------------------------
void Readi2c(uchar Data[],uchar Address,uchar Num)
{
uchar i;
uchar *PData;
PData=Data;
for(i=0;i<Num;i++)		//读出连续的8个地址的内容
{
I2CStart();				//发送启动信号
I2CSendByte(0xa0);		//写入器件地址启动写操作
WaitAck();//
I2CSendByte(Address+i);	//写入指定地址
WaitAck();
I2CStart();
I2CSendByte(0xa1);		//启动读操作
WaitAck();
*(PData+i)=I2CReceiveByte();
SCL=0;
SendNotAck();
I2CStop();
}
}



 //----------------------------------------------------------------------------
void WrToROM(uchar Data[],uchar Address,uchar Num)
{
uchar i;
uchar *PData;
PData=Data;
I2CStart(); 					//发送启动信号
I2CSendByte(0xa0); 				//发送SLA+W
WaitAck();
I2CSendByte(Address); 			//发送地址
WaitAck();
for(i=0;i<Num;i++)
{
I2CSendByte(*(PData+i));
WaitAck();
}
I2CStop();
}

//----------------------------------------------------------------------------

void main()
{
	uchar Data[8]={0,0,0,0,0,0,0,0};
	uchar i;
	uchar a;
	uchar j;
	uchar resum=0;
	TMOD=0x20; //01000000B,定时器工作方式2
	TL1=0xfd;TH1=0xfd;//波特率9600
	SCON=0x50;//0101 0000  SM2=0 串口工作方式1,允许接收
	PCON=0x00;//SMOD=0,
	TR1=1;//开始计时 
	
	while(RI==0);
	RI=0;
	a=SBUF;
	SBUF=a;
    
	switch (a)
	{
    /* case 0x00:
	WrToROM( Data,resum,7);	
	delayms(10);	
	break;*/

	case 0xbc:    
	for(i=0;i<8;i++)        //接收8个数据并写入
	 {
	  while(RI==0);
	  RI=0;
	  a=SBUF;
	  Data[i]=a;	
	 }	 
	 WrToROM( Data,1,8);		//数据写入08H地址
	 delayms(10);	 
	break;		

	case 0xbb:    
	for(i=0;i<8;i++)        //接收8个数据并写入
	 {
	  while(RI==0);
	  RI=0;
	  a=SBUF;
	  Data[i]=a;	
	 }	 
	 WrToROM( Data,16,8);		//数据写入地址
	 delayms(10);	 
	break;		
	
	case 0xff:
	for (j=0;j<16;j++)		//读出128字节的内容
	{		
		Readi2c( Data,resum,8);
		for (i=0;i<8;i++)	//通过串口发送数据给PC
		{
		a=Data[i];		
		SBUF=a;
		while(TI==0);
		TI=0;
		}
		resum=resum+8;		  
	}
	break;
}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -