【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总线的底层驱动代码,但是对于具体设备的操作还需要结合数据手册来进一步实现。
【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总线的底层驱动代码,但是对于具体设备的操作还需要结合数据手册来进一步实现。
举报