【1】IIC总线概述

      IIC总线全称:Inter-Integrated Circuit,是由飞利浦公司开发出来的一种串行总线协议,它是一种多主机的总线,当发生主机竞争时,有总线仲裁机制

      IIC总线只有2根信号线,一根是数据线SDA,一根是时钟线SCL。SDA和SCL均为双向信号线,通过上拉电阻接正电源。当总线空闲时,两根线都是高电平。连接到总线上的任一器件,输出低电平,都将使总线的信号变低。
      连接总线的器件输出级必须是集电极或漏极开路,以形成线“与”功能
      每个具有IIC接口的设备都有一个唯一的地址,也叫做设备地址

【2】数据位的有效性定义

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

【3】IIC总线数据传输规范

      在数据的传输过程中,必须确认数据传送的开始和结束。在IIC总线规范中,规定了起始信号和停止信号。

      起始信号:当时钟线SCL为高电平时,数据线SDA由高变低。
      停止信号:当时钟线SCL为高电平时,数据线SDA由低变高。
      在起始信号以后,IIC总线就被认为是处于忙状态,直到停止信号以后的几个时钟周期,IIC总线才被认为重新处于空闲状态

      在起始信号之后,必须是器件的控制字节,也即是设备地址,其中高4位是器件的类型识别符(EEPROM的识别符为1010),接着3位是片选信号,最后1位是读写控制位,读操作为1,写操作为0。

      对于EEPROM器件来说,如果片选信号为000,则:
      读操作的设备地址为:0xA1
      写操作的设备地址为:0xA0

      IIC总线每次传送的数据字节不限,每一个字节必须是8位。数据传送时,必须先送最高位(MSB),每个数据字节后面都有一个确认位,也就是应答(ACK)。

      IIC总线协议规定,每传送一个字节数据后,都要有一个应答信号,以确定数据传送是否被对方收到。应答信号由接收方在数据开始后的第9个时钟周期发送,在SCL为高电平期间,接收方将SDA拉为低电平产生应答,用来结束一个字节的传输。也就是说,一帧完整的数据共有9位。
      注意:当主机接收数据(也就是在读数据状态)时,它收到最后一个字节后,必须向从机发出一个结束传送的信号。这个信号是通过对从机的“非应答信号”来实现的,在SCL为高电平期间,SDA为高电平,即从机释放SDA线,允许主机产生一个停止信号。

【4】IIC总线数据帧的传输方式

      在总线的一次数据传送中,可以有以下几种组合方式:
      ●主机向从机发送数据,数据传送方向在整个传送过程中不变:

      

      ●主机在第一个字节后,立即从从机读数据。

      

       ●在读数据的过程中,一定要注意,当读完最后一个字节数据的时候,主机不能产生“应答”信号,而应该产生一个“非应答”信号。在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读写方向位正好反相。

      

       注:阴影部分表示数据从主机向从机传送,无阴影部分表示数据由从机向主机传送。

【5】IIC总线驱动程序设计

     在没有硬件IIC外设的微处理器中,需要根据总线时序设计IIC接口的驱动程序。包括:起始信号停止信号产生应答等待应答发送数据接收数据6个函数。下面以51单片机为例,阐述IIC总线驱动程序的设计。

延时函数

void Delay_IIC(unsigned char time)
{
	while(time--);
}

起始信号

void IIC_Start(void)
{
	SDA = 1;
	SCL = 1;
	Delay_IIC(5);
	SDA = 0;        //在SCL高电平期间,SDA由高变低
	Delay_IIC(5);
	SCL = 0;	
}

停止信号

void IIC_Stop(void)
{
	SDA = 0;
	SCL = 1;
	Delay_IIC(5);
	SDA = 1;	//在SCL高电平期间,SDA由高变低
	Delay_IIC(5);
}

产生应答

void IIC_Ack(unsigned char ackbit)
{
	if(ackbit) 	
		SDA = 0;	//产生应答信号
	else 
		SDA = 1;	//产生非应答信号
	Delay_IIC(5);
	SCL = 1;
	Delay_IIC(5);	        //第9个时钟周期
        SCL = 0;
	SDA = 1; 		//释放SDA线
	Delay_IIC(5);
}

等待应答

bit IIC_WaitAck(void)
{
	SDA = 1;
	Delay_IIC(5);
	SCL = 1;
	Delay_IIC(5);	

	if(SDA)    		//在SCL高电平期间,SDA为高电平,从机非应答。
	{   
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else 			//在SCL高电平期间,SDA为低电平,从机有应答。
	{ 
		SCL = 0;
		return 1;
	}	
}

发送数据

void IIC_SendByte(unsigned char byt)
{
	unsigned char i;
	for(i=0;i<8;i++)		//循环发送8位数据
	{   
		if(byt & 0x80) 		//数据位是高电平
		{	
			SDA = 1;
		}
		else 			//数据位是低电平
		{
			SDA = 0;
		}

		Delay_IIC(5);
		SCL = 1;		//SCL高电平期间,SDA的数据要保持稳定
		byt <<= 1;		//发送的数据左移,准备发送下一位
		Delay_IIC(5);		//等待SDA的数据被读取
		SCL = 0;
	}
}

接收数据

unsigned char IIC_RecByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++)
	{   
		SCL = 1;
		Delay_IIC(5);		//在SCL高电平期间,读取SDA的数据
		da <<= 1;
		if(SDA) 
			da |= 0x01;
		SCL = 0;
		Delay_IIC(5);
	}
	return da;
}

【6】IIC总线驱动程序的应用

    一般情况下,所提供的IIC总线底层驱动代码有“ **.c ”和“ **.h ”两个文件,你需要懂得它们,至少需要了解“ **.h” 头文件,才能正确应用。虽然不再需要编写IIC总线的底层驱动代码,但是对于具体设备的操作还需要结合数据手册来进一步实现。关于IIC总线设备的具体应用在《PCF8591的基本原理与AD转换应用》《24C02存储器的基本原理与应用》两个笔记中有详细的阐述,欢迎参阅。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐