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

📄 iic.c

📁 8051单片机模拟IIC总线驱动程序。非常适合初学者
💻 C
字号:
#include <reg51.h>				/*头文件的包含*/
#include <intrins.h>

#define	BYTE	unsigned char	/*宏定义*/
#define	WORD	unsigned int

#define  _Nop()  _nop_()			/*定义空指令*/

/* 常量、变量定义区 */
/*端口位定义*/
sbit SDA = P1^3;				/*模拟I2C数据传送位*/
sbit SCL = P1^2;					/*模拟I2C时钟控制位*/
/*状态标志*/
bit ack;						/*应答标志位*/

/*******************************************************************
起动总线函数 
函数原型:	
void  Start_I2C();  
功能:		
启动I2C总线,即发送I2C起始条件。
参数:
	无。
返回值:
	无。
********************************************************************/
void Start_I2C()
{
	SDA = 1;   /*发送起始条件的数据信号*/
	_Nop();
	SCL = 1;
	_Nop();		/*	起始条件建立时间大于4us,延时	*/
	_Nop();
	_Nop();
	_Nop();
	_Nop();    
	SDA = 0;		/*	发送起始信号	*/
	_Nop();		/*	起始条件锁定时间大于4 us	*/
	_Nop();
	_Nop();
	_Nop();
	_Nop();       
	SCL = 0;		/*	准备发送或接收数据	*/
	_Nop();
	_Nop();
}

/*******************************************************************
结束总线函数               
函数原型:
void  Stop_I2C();  
功能:
结束I2C总线,即发送I2C结束条件。
参数:
	无。
返回值:
	无。  
********************************************************************/
void Stop_I2C()
{
	SDA = 0;		/*	发送结束条件的数据信号	*/
	_Nop();		/*	发送结束条件的时钟信号	*/
	SCL = 1;		/*	结束条件建立时间大于4 us	*/
	_Nop();
	_Nop();
	_Nop();
	_Nop();
	_Nop();
	SDA = 1;		/*	发送I2C总线结束信号	*/
	_Nop();
	_Nop();
	_Nop();
	_Nop();
}

/*******************************************************************
字节数据传送函数               
函数原型:
 void  SendByte(BYTE data);
功能:
将数据data发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态
位进行操作。(不应答或非应答都使ack = 0) 发送数据正常,ack=1;ack=0
表示接收器无应答或损坏。
参数:
	需要发送的数据。
返回值:
	无。
********************************************************************/
void  SendByte(BYTE data)
{
	BYTE BitCount;

	for(BitCount = 0; BitCount < 8; BitCount ++)  /*	要传送的数据长度为8位	*/
	{
		if((data << BitCount) & 0x80) SDA = 1;   /*	判断发送位	*/
		else  SDA = 0;                
		_Nop();
		SCL = 1;					/*	置时钟线为高,通知被控器开始接收数据位	*/
		_Nop(); 
		_Nop();					/*	保证时钟高电平周期大于4 us	*/
		_Nop();
		_Nop();
		_Nop();
		SCL = 0; 
	}
	_Nop();
	_Nop();
	SDA = 1;					/*	8位发送完后释放数据线,准备接收应答位*/
	_Nop();
	_Nop();   
	SCL=1;
	_Nop();
	_Nop();
	_Nop();
	if(SDA == 1) ack = 0;     
	else ack = 1;				/*	判断是否接收到应答信号*/
	SCL=0;
	_Nop();
	_Nop();
}

/*******************************************************************
字节数据传送函数               
函数原型:
BYTE  RecByte();
功能:
用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用
应答函数。  
参数:
	无。
返回值:
	读取到的数据。
********************************************************************/	
BYTE  RecByte()
{
	BYTE RecData;
	BYTE BitCount;

	RecData = 0; 
	SDA = 1;				/*	置数据线为输入方式	*/
	for(BitCount = 0; BitCount < 8; BitCount ++)
	{
		_Nop(); 
		SCL=0;			/*	置时钟线为低,准备接收数据位	*/
		_Nop();
		_Nop();			/*	时钟低电平周期大于4.7us	*/
		_Nop();
		_Nop();
		_Nop();
		SCL= 1;			/*	置时钟线为高使数据线上数据有效	*/
		_Nop();
		_Nop();
		RecData = RecData << 1;
		if(SDA==1) RecData = RecData +1;	/*	读数据位,接收的数据位放入retc中	*/
		_Nop();
		_Nop(); 
	}
	SCL= 0;    
	_Nop();
	_Nop();
	return(RecData);
}

/********************************************************************
应答子函数
原型:
void Ack_I2C(bit a);
功能:
主控器进行应答信号,,(可以是应答或非应答信号)
参数:
	应答信号。
返回值:
	无。
********************************************************************/
void Ack_I2c(bit a)
{
	if(a == 0) SDA = 0;		/*	在此发出应答或非应答信号	*/
	else SDA=1;
	_Nop();
	_Nop();
	_Nop();      
	SCL = 1;
	_Nop();
	_Nop();				/*	时钟低电平周期大于4us	*/
	_Nop();
	_Nop();
	_Nop();  
	SCL = 0;				/*	清除时钟线,以便继续接收	*/
	_Nop();
	_Nop();    
}

/*******************************************************************
向无子地址器件发送字节数据函数               
函数原型: 
bit  SendByteData(BYTE Slave,BYTE Data);  
功能:
从启动总线到发送地址,数据,结束总线的过程。
参数:
	slave--从器件地址。
	data --要发送的数据。
返回值:
	如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bit SendByteData (BYTE Slave, BYTE Data)
{
	Start_I2C();			/*	启动总线	*/
	SendByte(Slave);			/*	发送器件地址	*/
	if(ack == 0) return(0);
	SendByte(Data);			/*	发送数据	*/
	if(ack == 0) return(0);
	Stop_I2C();			/*	结束总线	*/ 
	return(1);
}

/*******************************************************************
向有子地址器件发送多字节数据函数               
函数原型: 
bit  SendStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num);  
功能:
从启动总线到发送地址,子地址,数据,结束总线的过程。
参数:
Slave--从器件地址
SubAddress--子地址
Source--指向发送内容的指针
Num--发送字节个数
返回值:
如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bit SendStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num)
{
	BYTE i;

	Start_I2C();			/*	启动总线	*/
	SendByte(Slave);		/*	发送器件地址	*/
	if(ack == 0) return(0);
	SendByte(SubAddress);			/*	发送器件子地址	*/
	if(ack == 0) return(0);

	for(i = 0; i < Num; i++)
	{   
		SendByte(*Source);			/*	发送数据	*/
		if(ack == 0) return(0);
		Source ++;
	} 
	Stop_I2C();					/*	结束总线	*/ 
	return(1);
}

/*******************************************************************
向无子地址器件读字节数据函数               
函数原型:
bit  RecByteData(BYTE Slave,BYTE *Data);  
功能:
从启动总线到发送地址,读数据,结束总线的过程。
参数:
从器件地址Slave,返回值在Data。
返回值:
如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bit RecByteData(BYTE Slave,BYTE *Data)
{
	Start_I2C();				/*	启动总线	*/
	SendByte(Slave+1);			/*	发送器件地址	*/
	if(ack == 0) return(0);
	*Data = RecByte();			/*	读取数据	*/
	Ack_I2C(1);				/*	发送非就答位	*/
	Stop_I2C();				/*	结束总线	*/ 
	return(1);
}

/*******************************************************************
向有子地址器件读取多字节数据函数               
函数原型:
 bit  RecStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num);  
功能:
从启动总线到发送地址,子地址,读数据,结束总线的过程。
参数:
Slave--从器件地址。
SubAddress--子地址
Source--指向读出的内容放入的存储区的指针
Num--读字节个数。
返回值:	
如果返回1表示操作成功,否则操作有误。
注意:
使用前必须已结束总线。
********************************************************************/
bit RecStr(BYTE Slave, BYTE SubAddress, BYTE *Source, BYTE Num)
{
	BYTE i;

	Start_I2C();					/*	启动总线	*/
	SendByte(Slave);				/*	发送器件地址	*/
	if(ack == 0) return(0);
	SendByte(SubAddress);			/*	发送器件子地址	*/
	if(ack == 0) return(0);

	Start_I2C();
	SendByte(Slave+1);
	if(ack == 0) return(0);

	for(i = 0; i < Num-1; i++)
	{   
		*Source = RecByte();			/*	发送数据	*/
		Ack_I2C(0);				/*	发送就答位	*/  
		Source++;
	} 
	* Source =RecByte();
	Ack_I2C(1);					/*	发送非应位	*/
	Stop_I2C();					/*	结束总线	*/ 
	return(1);
}

⌨️ 快捷键说明

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