一、I2C 总线
每个连接到总线的设备都有一个独立的地址(一般可以通过硬件设置,可通过查芯片数据手册得知),主机可以利用这个地址进行不同设备之间的访问。 总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。数据线(SDA)用来传输数据,时钟线(SCL)用于数据收发同步。
上拉电阻可以是1.5K,2.2K,4.7K, 电阻越小,上升时间越短,当总线过长或者从机过多可以选择小的上拉电阻,增加信号强度,否则选择较大电阻减小功耗,当然首先是参考各个芯片的数据手册!
二、三种信号
开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
停止信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//发送I2C总线结束信号
delay_us(4);
}
响应信号:主机产生时钟,在第 9 个时钟时,数据发送端会释放 SDA 的控制权,由数据接收端控制 SDA,若 SDA 为高电平,表示非应答信号(NACK),低电平表示应答信号(ACK)。当数据接受端接收完一个字节数据或者地址,就要返回应答或非应答信号来表示继续或者停止接受数据,若发送方收到非应答信号就会返回结束信号结束通信,否则继续下一个字节数据传输。
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置为输入
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA) //READ_SDA为读取SDA的电平函数的宏定义
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
三、通信过程
1、选择从机
首先由主机产生起始信号,这时连接到 I2C 总线上的所有从机都会接收到这个信号。接下来所有从机开始等待主机紧接下来广播的从机地址信号,传输时,SCL 为高电平的时候 SDA 表示的数据有效,SCL 为低电平时SDA切换电平,准备下一次SCL 高电平时要传输的数据,当主机广播的地址与某个设备地址相同时,这个设备就被选中了,没被选中的设备将会忽略之后的数据信号。根据 I2C 协议,这个从机地址可以是 7 位或 10 位。在地址位之后,是传输方向的选择位,该位为 0表示主机向从机写数据。该位为 1表示主机由从机读数据。从机接收到匹配的地址后,会返回一个应答(ACK)或非应答(NACK)信号,只有接收到应答信号后,主机才能继续发送或接收数据。
2、主机发数据
广播完地址,接收到应答信号后,主机开始正式向从机传输数据,数据包的大小为 8 位,主机每发送完一个字节数据,都要等待从机的应答信号(ACK),重复这个过程,可以向从机传输 N 个数据,这个 N 没有大小限制。当数据传输结束时,主机向从机发送一个停止传输信号§,表示不再传输数据。
3、主机读数据
广播完地址,接收到应答信号后,从机开始向主机返回数据,数据包大小也为 8 位,从机每发送完一个数据,都会等待主机的应答信号(ACK),重复这个过程,可以返回 N 个数据,这个 N 也没有大小限制。当主机希望停止接收数据时,就向从机返回一个非应答信号(NACK),则从机自动停止数据传输。
4、复合格式
除了基本的读写,I2C 通讯更常用的是复合格式,该传输过程有两次起始信号。一般在第一次传输中,主机通过从机地址寻找到从设备后,发送一段从机设备内部的寄存器或存储器地址,在第二次的传输中,对该地址的内容进行读或写。也就是说,第一次通讯是告诉从机读写地址,第二次则是读写的实际内容。
例如一个EEPROM的连续读过程为:
发起I2C总线启动信号
发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读
等待ACK
发送字节地址
等待ACK
再次发起I2C总线启动信号
发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读
发送ACK
在循环里接收数据