IIC通讯协议

IIC通讯协议

简单介绍下IIC的通讯时序,然后给出51单片机实现的代码。

1. 通讯协议

IIC总线在传送数据过程中有三种类型信号,分别是:开始信号、结束信号和应答信号。

  • 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
  • 结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
  • 应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况做出是否继续传递信号的判断。若未接收到应答信号,则判断为受控单元出现故障。

IIC总线时序图片如下。

IIC总线时序图

2. 51单片机程序代码

2.1 使用的IO口

//---定义IIC接口---//
sbit IIC_SCL = P2^1;
sbit IIC_SDA = P2^0;

2.2 延时函数

/**************************************
延时4微秒(STC89C51,晶振频率12MHz)
不同的单片机,需要调整此函数
**************************************/
void Delay_4us(void)
{
	_nop_();
	_nop_();
	_nop_();
    _nop_();
}

2.3 IIC驱动代码

/*******************************************************************************
* 函数名   	   	: IIC_Start
* 功能			: IIC启动信号
* 输入			: 无
* 输出			: 无
*******************************************************************************/
void IIC_Start(void)
{
	IIC_SDA = 1;
	IIC_SCL = 1;
	Delay_4us();
	IIC_SDA = 0;
	Delay_4us();
	IIC_SCL = 0;
}

/*******************************************************************************
* 函数名   		: IIC_Stop
* 功能			: IIC停止信号
* 输入			: 无
* 输出			: 无
*******************************************************************************/
void IIC_Stop(void)
{
	IIC_SCL = 0;
	IIC_SDA = 0;
	Delay_4us();
	IIC_SCL = 1;
	Delay_4us();
	IIC_SDA = 1;
}

/*******************************************************************************
* 函数名   		: IIC_WaitAck
* 功能			: 等待Ack应答
* 输入			: 无
* 输出			: BYTE 1接收应答失败 0接收应答成功
*******************************************************************************/
BYTE IIC_WaitAck(void)
{
	BYTE errtime = 0;
	IIC_SDA = 1;
	_nop_();
	IIC_SCL = 1;
	_nop_();

	while (IIC_SDA)
	{
		errtime++;
		if(errtime>250)
		{		
			IIC_Stop();
			return 1;
		}
	}

	IIC_SCL = 0;
	return 0;
}

/*******************************************************************************
* 函数名   		: IIC_Ack
* 功能			: 产生Ack应答
* 输入			: 无
* 输出			: 无
*******************************************************************************/
void IIC_Ack(void)
{
	IIC_SCL = 0;
	Delay_4us();
	IIC_SDA = 0;
	Delay_4us();
	IIC_SCL = 1;
	Delay_4us();
	IIC_SCL = 0;
}

/*******************************************************************************
* 函数名   		: IIC_nAck
* 功能			: 不产生Ack应答
* 输入			: 无
* 输出			: 无
*******************************************************************************/
void IIC_nAck(void)
{
	IIC_SCL = 0;
	Delay_4us();
	IIC_SDA = 1;
	Delay_4us();
	IIC_SCL = 1;
	Delay_4us();
	IIC_SCL = 0;
}


/*******************************************************************************
* 函数名   		: IIC_Send_Byte
* 功能			: 发送一个字节
* 输入			: BYTE dat
* 输出			: 无
*******************************************************************************/
void IIC_Send_Byte(BYTE dat)
{
	BYTE t = 0;
	IIC_SCL = 0;
	for(t=0;t<8;t++)
	{
		IIC_SDA = ((dat&0x80)>>7);
		dat <<= 1;
		_nop_();
		IIC_SCL = 1;
		Delay_4us();
		IIC_SCL = 0;
	}
}

/*******************************************************************************
* 函数名   		: IIC_Read_Byte
* 功能			: 读取一个字节
* 输入			: BYTE ack 1为发送ACK 0为发送nACK
* 输出			: BYTE
*******************************************************************************/
BYTE IIC_Read_Byte(BYTE ack)
{
	BYTE i,receive = 0;
	for(i=0;i<8;i++)
	{
		IIC_SCL = 0;
		Delay_4us();
		IIC_SCL = 1;
		receive <<= 1;
		if(IIC_SDA==1)
		{
			receive++;
		}
		Delay_4us();
	}
	if(ack)
	{
		IIC_Ack();
	}
	else
	{
		IIC_nAck();
	}
	return receive;
}

posted @ 2025-08-03 13:37  路痴的兔子  阅读(9)  评论(0)    收藏  举报