(一)I2C总线简介

        I2C总线是Philips公司在八十年代初推出的一种同步串行、半双工的总线,主要用于近距离、低速的芯片之间的通信。

        I2C总线有两根双向的信号线,一根数据线SDA用于收发数据,一根时钟线SCL用于通信双方时钟的同步。

        I2C总线是一种多主机总线,连接在I2C总线上的器件分为主机和从机。主机有权发起和结束一次通信,从机只能被动呼叫。

        标准模式下,基本的I2C总线规范的规定的数据传输速率为100kb/s

        快速模式下,数据传输速率为400Kb/s

        高速模式下,数据传输速率为3.4Mb/s        

        当总线上有多个主机同时启用总线时,I2C也具备冲突检测和仲裁的功能来防止错误产生;每个连接到I2C总线上的器件都有一个唯一的地址(7bit),且每个器件都可以作为主机也可以作为从机(但同一时刻只能有一个主机),总线上的器件增加和删除不影响其他器件正常工作;I2C总线在通信时总线上发送数据的器件为发送器,接收数据的器件为接收器。

I2C协议仅需要一个SDA和SCL引脚。SDA是串行数据线的缩写,而SCL是串行时钟线的缩写。

但这两条数据线需要接上拉电阻,一般接2KΩ或4.7KΩ。这是因为I²C总线(SDASCL)内部都使用漏极开路驱动器(开漏驱动),因此SDASCL 可以被拉低为低电平,但是不能被驱动为高电平,所以每条线上都要使用一个上拉电阻,默认情况下将其保持在高电平;

(二)I2C总线的寻址

每个连接在I2C总线的器件,都具有一个唯一确定的地址。在任何时刻,I2C总线上只能有一个主机对总线实行控制权,分时地实现点对点的数据传送。
器件(从机)的地址由7位组成,它与1位方向位构成了I2C总线数据传输时起始状态Start之后第1个字节。

当主机发送了第1个字节后,系统中的每个从机(器件)都在起始状态Start之后把高7位与本机的地址比较,如果与本机地址一样,则该从机被主机选中,是接收数据还是发送数据由R/W确定

从机器件地址由固定位和可编程位组成。固定位由器件出厂时给定,用户不能自行设置,它是器件的标识码。

当系统中使用了多个相同器件时,从机地址中的可编程位,可使这些器件具有不同的地址;这些可编程位也规定了I2C总线上同类芯片的最大个数。如一个从机的7位寻址位有4位是固定位,3位是可编程位,这时仅能寻址8个同样的器件即可以有8个同样的器件接入到该I2C总线系统中。
 

(三)I2C总线通信协议使用方法

I2C总线上主设备和从设备进行数据传输时遵循以下协议格式。数据通过一条SDA数据线在主设备和从设备之间传输01的串行数据。

只有在总线空闲时才允许启动数据传送

在数据传送过程中当时钟线为高电平时数据线必须保持稳定状态不允许有跳变,时钟线为高电平时数据线的任何电平变化将被看作总线的起始或停止信号。

 整个I2C串行通信过程可以分为:起始信号,地址位,读写位,应答位,数据位,停止条件,具体如下所示: 1、起始信号

 

起始(START)状态:I2C总线传输过程中,当时钟线SCL为高电平时,数据线SDA出现高电平到低电平跳变时,标志着I2C总线传输数据开始。

当主设备决定开始通讯时,需要发送开始信号,需要执行以下动作;

  • 先将SDA线从高压电平切换到低压电平;
  • 然后将SCL从高电平切换到低电平;
  • 在主设备发送开始条件信号之后,所有从机即使处于睡眠模式也将变为活动状态,并等待接收地址位

    /*******************************************
    函数:I2C_Start()
    功能:I2C总线通信起始信号
    参数:无
    返回值:无
    *******************************************/
    void I2C_Start()
    {
    	I2C_SDA = 1;
    	I2C_SCL = 1;	//总线空闲时SDA SCK都为高电平
    	//时钟线保持高电平4us之后 数据线电平从高到低的跳变 作为I2C总线的起始信号
    	I2CDelay();		//12MHz 延时4us
    	I2C_SDA = 0;
    	I2CDelay();		//12MHz 延时4us
    	I2C_SCL = 0;
    }

    2、数据传输

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

    I2C总线上主机与从机之间一次传送的数据成为一帧,由启动信号、若干个数据字节、应答位和停止信号组成,数据传输的基本单元位一位数据。

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

    I2C总线数据传送时每成功地传送一个字节数据后,接收器都必须产生一个应答信号,应答的器件在第9个时钟周期时将SDA 线拉低表示其已收到一个8 位数据,必须要跟一个应答信号,否则主机和从机都不知道数据是否传输完毕。

    每写8位数据之后要读取一次ACK应答信号。应答位是从机将SDA电平拉低,应答信号为0说明有应答

    /*******************************************
    函数:I2C_WriteByte(unsigned char dat)
    功能:I2C总线通信写入数据
    参数:unsigned char dat---一个字节 8位数据
    返回值:无
    *******************************************/
    void I2C_WriteByte(unsigned char dat)
    {
    	unsigned char temp;
    	for(temp = 0x80; temp != 0; temp >>= 1)
    	{
    		if(temp & dat)
    		{
    			I2C_SDA = 1;	
    		}
    		else 
    		{
    			I2C_SDA = 0;	
    		}
    		I2CDelay();		//12MHz 延时4us 维持SCK低,写入数据
    		I2C_SCL = 1;	//拉高器件读数据位
    		I2CDelay();		//12MHz 延时4us	 维持SCK高,器件读取数据
    		I2C_SCL = 0;	//SCK拉低,为下次数据位变化做准备
    	}	
    }
    /*******************************************
    函数:I2C_RecvAck()
    功能:I2C总线通信读取应答位
    参数:无
    返回值:bit---0 器件有应答 1 器件无应答 
    *******************************************/
    bit I2C_RecvAck()
    {
    	bit ack;
    	I2C_SDA = 1;//主机主动释放数据总线,为读ack做准备 器件存在是拉低电平
    	I2CDelay();	//维持SCL低 4us
    	I2C_SCL = 1;//拉高时钟线,主机读取ACK,若ACK存在,从机会将SDA拉低
    	ack = I2C_SDA; 
    	I2CDelay();	//维持SCL高 4us
    	I2C_SCL = 0;
    	
    	return ack;		
    }

    I2C总线上传输的数据信号是广义的,既包括地址信号,有包括真正的数据信号。

    在起始信号Start之后,必须首先传送的第一个字节必须是是从机的器件地址数据,只有器件地址传送完成之后,才能进行后续操作。

     I2C总线的一次数据传输过程可以有几种数据传输的组合方式:

    (1)主机向从机发送数据,数据的整个传送方向在整个传送过程中保持不变。

     (2)在第一个字节后,主机立刻从从机读取数据

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

    3、停止信号

     停止(STOP)状态:I2C总线传输过程中,当时钟线SCL为高电平时,数据线SDA出现低电平到高电平跳变时,标志着IPC总线传输数据结束。

    当主设备决定结束通讯时,需要发送开始信号,需要执行以下动作;

  • 先将SDA线从低电压电平切换到高电压电平;
  • 再将SCL线从高电平拉到低电平;
  • /*******************************************
    函数:I2C_Stop()
    功能:I2C总线通信结束信号
    参数:无
    返回值:无
    *******************************************/
    void I2C_Stop()
    {
    	I2C_SDA = 0;
    	I2C_SCL = 0;//初始都给低电平	
    	//时钟线保持高电平4us之后 数据线电平从低到高的跳变 作为I2C总线的结束信号
    	I2CDelay();		//SCL维持4us低
    	I2C_SCL = 1;
    	I2CDelay();		//SCL维持4us高
    	I2C_SDA = 1;	//拉高SDA
    	I2CDelay();
    }

    (四)I2C总线完整工作过程

    1、主机发送启动信号

    2、主机发送从设备器件地址

            主设备向每个从机发送要与之通信的从机的7位或10位地址,以及相应的读/写位。

    3、主机接收应答

            每个从设备将主设备发送的地址与其自己的地址进行比较。如果地址匹配,则从设备通过将SDA线拉低一位以表示返回一个ACK位

            如果来自主设备的地址与从机自身的地址不匹配,则从设备将SDA线拉高,表示返回一个NACK位

    4、传输数据

            主设备发送或接收数据到从设备;

    5、接收应答

            在传输完每个数据帧后,接收设备将另一个ACK位返回给发送方,以确认已成功接收到该帧:

    6、结束信号

            为了停止数据传输,主设备将SCL切换为高电平,然后再将SDA切换为高电平,从而向从机发送停止条件;

    物联沃分享整理
    物联沃-IOTWORD物联网 » 深入解析I2C通信协议

    发表评论