IIC通讯协议

一、IIC简介
IIC Inter-Integrated Circuit ,又称为 I2C I²C )是一种串行同步传输通信协议,用于连接微控制器和外部设备,例如传感 器、存储器、显示器等。它是一种简单而灵活的通信协议,由飞利浦公司(现在的恩智浦半导体)在1982 年开发。

IIC通讯协议包括两根线,一根是串行数据线(SDA),另一根是串行时钟线(SCL)。在通讯过程中,数据通过SDA线传输,而SCL线则用来同步数据传输速度。由于只有一根串行数据线(SDA)用来传输数据,在同一时间内只能进行单向的数据传输,即发送或接收不能同时进行,但可以在不同时间交替进行。所以I2C是半双工通信。

主从结构: I2C通信中,设备分为主设备(通常是微控制器)和从设备(例如传感器或存储器)。主设备负责发起通信和控制通信的时序,而从设备响应主设备的指令,可以有多个从设备。

地址寻址: 每个 I2C 设备都有一个唯一的 7位 或10位地址,主设备通过发送目标设备的地址来选择通信对象,我们通常使用的是7位地址
二、IIC通讯协议示意图:
主机发送开始通信信号后,首先发送7位从机地址,选择与哪一个从机进行通信,然后从机发送应答响应,才开始传输数据,最后一次数据传输完成后,主机等不到应答信号,通信结束
三、IIC通信要点:
1、I2C通信设备为什么通常配置为开漏输出:
I2C 总线上的信号(SCL)是开漏输出的,这意味着每个 I2C 设备的输出引脚都是一个开漏输出,可
以通过外部上拉电阻拉高。这种设计允许多个设备共享同一根总线,而不会出现信号冲突和短路。
(当 I2C 设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。)
2、IIC通信逻辑
IIC通讯默认状态下SDA(数据线)SCL(信号线)都为高电平,我们一次IIC通信中,SDA(数据线)的高低电平总是在SCL(信号线)为低电平时转换的;SCL(信号线)为高电平时,读取SDA(数据线)的电平状态(低电平代表接收到0,高电平代表接收到1)。因为SCL(信号线)为高电平时,SDA(数据线)从高电平转换为低电平,代表着一次IIC通信的开始,而SCL(信号线)为高电平时,SDA(数据线)从低电平转换为高电平,则代表着一次IIC通信的结束。
四、IIC协议代码实现:
开始信号:
当SCL保持高电平的时候,SDA从高电平变为低电平,这标志着一个IIC传输的开始。这种电平的变化被IIC主设备用来通知所有连接到IIC总线上的从设备,即将开始一次数据传输。
//IIC开始信号
void IIC_Start(void)
{
	IIC_SDA_OUT();
	IIC_SDA_H;
	IIC_SCL_H;
	Delay_us(4);  //让高电平保持稳定
	
	IIC_SDA_L;  //在SCL高电平时,将SDA拉低
	
	Delay_us(4);
	
	IIC_SCL_L;  //钳住IIC总线,准备发送数据	
}

应答信号(结束信号不需要应答。一旦发出结束信号,从设备会自动释放总线,允许其他设备进行通信):

在每个字节传输后,发送方会释放SDA线,允许接收方发送应答信号。接收方会在第9个时钟周期(SCL为高电平期间)将SDA拉低以发出ACK(应答)信号,或者保持SDA高电平以发出NACK(非应答)信号。

//IIC应答信号
void IIC_ACK(void)
{
	IIC_SDA_OUT();
	IIC_SCL_L;  //在SCL低电平时候,SDA可以进行数据切换的(0/1)
	IIC_SDA_L; //SDA低电平表示应答
	Delay_us(1);  //让电平稳定
	
	IIC_SCL_H; //SCL拉高,表示此刻SDA数据有效,读出来SDA是低电平,表示应答。
	Delay_us(1);  //读取稳定时间
	IIC_SCL_L;  //拉低SCL,表示一个SCL周期结束,为下次读取做准备。	
}


//IIC非应答信号
void IIC_NACK(void)
{
	IIC_SDA_OUT();
	IIC_SCL_L;
	IIC_SDA_H;//SDA低电平表示非应答
	Delay_us(1);
	
	IIC_SCL_H;
	Delay_us(1);
	IIC_SCL_L;
	
}

等待应答;STM32单片机发送完一个字节之后,等待从设备回复应答信号

//IIC等待应答,返回0表示应答了,1表示非应答
uint8_t IIC_WaitACK(void)
{
	IIC_SDA_IN();
	IIC_SDA_H; //先让SDA默认为高电平,如果后面发现变低了,说明从机应答了
	Delay_us(1); //电平平稳	
	
	uint8_t temp=0;
	IIC_SCL_H; //SCL高,SDA数据有效
	Delay_us(1); //电平平稳	
	//设置一个超时应答时间
	while(READ_SDA)
	{
		temp++;
		if(temp>250)
		{
			IIC_Stop();
			return 1;
		}
	
	}
	
	IIC_SCL_L;
	return 0;
	
}

结束信号:
当SCL保持高电平的时候,SDA从低电平变为高电平,这标志着一个IIC传输的结束。
 
//IIC结束信号
void IIC_Stop(void)
{	
	IIC_SDA_OUT();
	IIC_SCL_H;
	
	IIC_SDA_L;
	Delay_us(4);
	IIC_SDA_H;
}

读取一个字节:通过传参的形式,设置第九个时钟周期是高电平(非应答)还是低电平(应答),将应答信号反馈给从设备
 

//IIC读取一个字节
uint8_t IIC_ReadByte(uint8_t ack) //ack 0应答 ,1非应答
{
	IIC_SDA_IN();
	
	uint8_t i , receive=0;
	for(i=0;i<8;i++)
	{
		IIC_SCL_L;
		Delay_us(1);
		IIC_SCL_H; //SDA数据有效
		
		receive	<<=1;
		if(READ_SDA)  
		{
			receive++;	//读多了高电平
		}
		Delay_us(1); //电平平稳	
	}
	if(ack)
		IIC_NACK();
	else
		IIC_ACK();
	
	return receive;
}

发送一个字节:STM32单片机向从设备发送一个字节的数据,发送一个字节之后要判断等待一下从设备的应答或非应答信号

//IIC发送一个字节
void IIC_SendByte(uint8_t data)
{
	IIC_SDA_OUT();
	IIC_SCL_L; //在SCL低电平时候,SDA可以进行数据切换的(0/1)
	
	uint8_t i=0;
	for(i=0;i<8;i++)
	{
		if(data&0x80)  //0x80 1000 0000
		{
			IIC_SDA_H;  //高电平,1
		}
		else
		{
			IIC_SDA_L;
		}
	
		IIC_SCL_H; //SCL拉高,数据有效
		Delay_us(1);//延时,将数据发出去
		
		IIC_SCL_L;  //SCL拉低,为下一次SDA变化做准备
		Delay_us(1); //低电平处于稳定的状态
		
		data<<=1; //左移	
	}	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值