IIC 总线详解


常用的串行扩展总线有: I2C (Inter IC BUS)总线、单总线(1-WIRE BUS)、SPI(Serial Peripheral Interface)总线及Microwire/PLUS等。

牵扯到知识:
多主从的串行总线
全双工(收发可同时进行)、半双工同步传输类型总线 (收发不能同时进行)、
双工(既可以发送数据又可以接收数据)

通信时序和逻辑电平的关系
SDA只有在SCL为低时数据才能变

两根线就能完成多机通信,一根SCL时钟线,一根SDA数据线(SDA是具有输出输入双向功能的)。两根线都得加上拉电阻(一般可以接4.7K或者10K)(开漏输出)

IIC简介

IIC(Inter-Integrated Circuit)是一个多主从的串行总线,又叫I2C,是由飞利浦公司发明的通讯总线,属于半双工同步传输类型总线。IIC总线是总线裁决和高低速器件同步功能的高性能串行总线。 仅仅使用两条线就能完成多机通讯,一条SCL时钟线,另外一条双向数据线SDA。

有的处理器硬件内部就直接包括了IIC接口,如果没有硬件IIC接口,可以通过软件模拟IO引脚。

软件模拟:方便移植,规避专利问题
硬件:效率高点。但是一个单片机移到另一个单片机,如果不同的话,又要费些时间来移植

在这里插入图片描述

具有IIC接口的设备都可以接到上面,都可以挂到两根线上

那么挂载这么多设备不会干扰吗
IIC总线规定了,每个从机设备具有唯一的地址,根据设备地址进行区分。
主机首先会发送设备地址,从机不是该地址就不要理

IIC总线要求每个设备SCL/SDA线都是漏极开路模式(OD模式),因此总线必须带有上拉电阻才能正常工作,如下图所示:
I2C总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。
在这里插入图片描述

IIC总线的数据传送

1、数据位的有效性规定

I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

在这里插入图片描述

2、IDLE状态

总线上没有数据传输,SCL和SDA都保持高电平。

3、 起始信号和终止信号

SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。

在这里插入图片描述

起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。连接到I2C总线上的器件,若具有I2C总线的硬件接口,则很容易检测到起始和终止信号。	接收器件收到一个完整的数据字节后,有可能需要完成一些其它工作,如处理内部中断服务等,可能无法立刻接收下一个字节,这时接收器件可以将SCL线拉成低电平,从而使主机处于等待状态。直到接收器件准备好接收下一个字节时,再释放SCL线使之为高电平,从而使数据传送可以继续进行。  

4、总线的寻址

I2C总线协议有明确的规定:采用7位的寻址字节(寻址字节是起始信号后的第一个字节)。
(1)寻址字节的位定义
在这里插入图片描述
D7~D1位组成从机的地址。D0位是数据传送方向位,为“0”时表示主机向从机写数据,为“1”时表示主机由从机读数据。

主机发送地址时,总线上的每个从机都将这7位地址码与自己的地址进行比较,如果相同,则认为自己正被主机寻址,根据R/T位将自己确定为发送器或接收器。
从机的地址由固定部分和可编程部分组成。在一个系统中可能希望接入多个相同的从机,从机地址中可编程部分决定了可接入总线该类器件的最大数目。如一个从机的7位寻址位有4位是固定位,3位是可编程位,这时仅能寻址8个同样的器件,即可以有8个同样的器件接入到该I2C总线系统中。

5、数据传送格式

(1)字节传送与应答
每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。

在这里插入图片描述
由于某种原因从机不对主机寻址信号应答时(如从机正在进行实时性的处理工作而无法接收总线上的数据),它必须将数据线置于高电平,而由主机产生一个终止信号以结束总线的数据传送。

如果从机对主机进行了应答,但在数据传送一段时间后无法继续接收更多的数据时,从机可以通过对无法接收的第一个数据字节的“非应答”通知主机,主机则应发出终止信号以结束数据的继续传送。

当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号。这个信号是由对从机的“非应答”来实现的。然后,从机释放SDA线,以允许主机产生终止信号。

(2)数据帧格式
I2C总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。
在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/T),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)。每次数据传送总是由主机产生的终止信号结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。

在总线的一次数据传送过程中,可以有以下几种组合方式:
a、主机向从机发送数据,数据传送方向在整个传送过程中不变:
在这里插入图片描述
注:有阴影部分表示数据由主机向从机传送,无阴影部分则表示数据由从机向主机传送。
A表示应答, A非表示非应答(高电平)。S表示起始信号,P表示终止信号。。

b、主机在第一个字节后,立即从从机读数据
在这里插入图片描述

c、在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好反相。

在这里插入图片描述

6、ACK和NACK信号

发送方发送完成8bit数据(一个字节)后,紧随的下一个时钟周期,发送方释放SDA线,接收方发送一个ACK/NACK信号,用于应答发送方接收状态。

ACK:SCL高电平时,SDA为低电平,表示数据被正确接收,发送方可以继续发送,如下图所示:
在这里插入图片描述
NACK:SCL高电平时,SDA为高电平
在这里插入图片描述
通讯过程中出现以下情况,总线上会出现NACK信号:

1)接收方忙于其他事情,不能接收数据

2)接收方不能理解收到的数据或者没有空间存储数据

3)主机读取数据完成,返回NACK告知从机读取完成。

5、数据传输

1)主机向从机寄存器中写数据

主机首先发送START信号占用总线,然后发送7Bit从机地址,一般情况下从机地址是通过外部上下拉电阻分配的,7Bit从机地址之后是读写位,如果主机想要写数据此位为0,读数据此位为1,之后紧随从机ACK,然后主机发送寄存器地址,即数据写在从机哪个地址上,从机再次返回ACK,主机继续发送数据,所有数据发完之后,主机发送STOP后释放总线。

在这里插入图片描述

80C51单片机I2C串行总线器件的接口

总线数据传送的模拟

主机可以采用不带I2C总线接口的单片机,如80C51、AT89C2051等单片机,利用软件实现I2C总线的数据传送,即软件与硬件结合的信号模拟。

一、典型信号模拟
为了保证数据传送的可靠性,标准的I2C总线的数据传送有严格的时序要求。I2C总线的起始信号、终止信号、发送“0”及发送“1”的模拟时序 :
在这里插入图片描述

I2C总线器件的扩展
扩展电路
在这里插入图片描述

串行E2PROM的扩展
(1)串行E2PROM典型产品
ATMEL公司的AT24C系列:
AT24C01:128字节(128×8位);
AT24C02:256字节(256×8位);
AT24C04:512字节(512×8位);
AT24C08:1K字节(1K×8位);
AT24C16:2K字节(2K×8位);

(2)写入过程
AT24C系列E2PROM芯片地址的固定部分为1010,A2、A1、A0引脚接高、低电平后得到确定的3位编码。形成的7位编码即为该器件的地址码。
单片机进行写操作时,首先发送该器件的7位地址码和写方向位“0”(共8位,即一个字节),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为相应,单片机收到应答后就可以传送数据了。

传送数据时,单片机首先发送一个字节的被写入器件的存储区的首地址,收到存储器器件的应答后,单片机就逐个发送各数据字节,但每发送一个字节后都要等待应答。

AT24C系列器件片内地址在接收到每一个数据字节地址后自动加1,在芯片的“一次装载字节数”(不同芯片字节数不同)限度内,只需输入首地址。装载字节数超过芯片的“一次装载字节数”时,数据地址将“上卷”,前面的数据将被覆盖。

当要写入的数据传送完后,单片机应发出终止信号以结束写入操作。写入n个字节的数据格式 :
在这里插入图片描述

(3)读出过程
单片机先发送该器件的7位地址码和写方向位“0”(“伪写”),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为回应。
然后,再发一个字节的要读出器件的存储区的首地址,收到应答后,单片机要重复一次起始信号并发出器件地址和读方向位(“1”),收到器件应答后就可以读出数据字节,每读出一个字节,单片机都要回复应答信号。当最后一个字节数据读完后,单片机应返回以“非应答”(高电平),并发出终止信号以结束读出操作。 注意,此处有一个STOP,两个START,也就是说START和STOP有可能不是成对出现。
在这里插入图片描述

每个接到I2C总线上的器件都有唯一的地址。主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。
在多主机系统中,可能同时有几个主机企图启动总线传送数据。为了避免混乱, I2C总线要通过总线仲裁,以决定由哪一台主机控制总线。

在80C51单片机应用系统的串行总线扩展中,我们经常遇到的是以80C51单片机为主机,其它接口器件为从机的单主机情况。

以下是IIC的驱动代码,可以进行参考(移植时请注意修改SDA和SCL对应PIN脚、设置IO口的输入输出模式)

代码

#ifndef _IIC_H_
#define _IIC_H_

#include "sys.h"

sbit SDA=P2^6;	//iic两根线更换要修改对用的pin
sbit SCL=P2^7;

#define	SDA_IN()	P2MDOUT&=0x7F	//设置SDA引脚为输入
#define SDA_OUT()	P2MDOUT|=0x80	//设置SDA引脚为输出
#define SCL_OUT()	P2MDOUT|=0x40	//设置SCL引脚为输出

#define IIC_DELAY()	delay_us(5)

void iic_init();
void iic_start();
void iic_stop();
void iic_ack();
void iic_nack();
u8 iic_wait_ack();
void iic_send_byte(u8 byte);
u8 iic_read_byte(u8 ack);

#endif 
#include "iic.h"

void iic_init(){
	SDA_OUT();
	SCL_OUT():
	SCL=1;	//拉高scl
	IIC_DELAY();
	SDA=1;	//如果之前SDA=0,那么在SCL为高时拉高SDA,  就是一个stop信号
	IIC_DELAY():
}

void iic_start(){
	SDA_OUT();
	SDA=1;	//确保SDA为高
	SCL=1;	//确保SCL为高
	IIC_DELAY();	//保持一段时间,空闲
	SDA=0;	//起始信号
	IIC_DELAY():
	SCL=0;	//拉低SCL,准备发送和接收数据
}

void iic_stop(){
	SDA_OUT():
	SCL=0;
	SDA=0;
	IIC_DELAY():
	SCL=1;
	IIC_DELAY();
	SDA=1;	//产生stop信号
	IIC_DELAY();
}

void iic_ack(){
	SDA_OUT();
	SCL=0;	//先拉低SCL,使得SDA的数据可变
	SDA=0IIC_DELAY();
	SCL=1;
	IIC_DELAY():
	SCL=0;
	SDA=1;	//应答之后记得拉高
}

void iic_nack(){
	SDA_OUT();
	SCL=0;
	SDA=1;
	IIC_DELAY();
	SCL=1;
	IIC_DELAY():
	SCL=0;
}

u8 iic_wait_ack(){
	u8 wait_time=0;
	SDA_IN();
	SDA=1;	IIC_DELAY();	//释放SDA,使slave能够应答
	SCL=1IIC_DELAY();	//SCL为高时,主机读取SDA
	while(SDA){
	wait_time++;
	if(wait_time>250){
		iic_stop();
		return 1;
		}
	}
	SCL=0;	//第9个时钟周期结束,告诉从机可以释放SDA了
	return 0;
}

void iic_send_byte(u8 byte){
	u8 i=0;
	SDA_OUT();
	SCL=0;
	IIC_DELAY();
	for(i=0;i<8;i++){
		SDA=((byte&0x80)!=0)
		byte=byte<<1;
		SCL=1;
		IIC_DELAY();
		SCL=0;
		IIC_DELAY();	//最后这个SCL变为0拉低后,slave会抓住这个短时间作出应答
	}
	iic_wait_ack();
} 

u8 iic_read_byte(u8 ack){
	u8 i=0;
	u8 byte=0;
	SDA_IN();
	for(i=0;i<8;i++){
		SCL=0;
		IIC_DELAY();
		SCL=1;
		byte=byte<<1;
		if(SDA)
			byte++;
		IIC_DELAY();
	}	
	if(ack)
		iic_ack();
	else
		iic_nack();
	return byte;
}

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值