I2C总线特征
1、只要求两条总线线路:一条串行数据线SDA,一条串行时钟线SCL;
2、每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机关系软件设定地址,主机可以作为主机发送器或主机接收器;
3、它是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏;
4、串行的8 位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s;
5、连接到相同总线的IC 数量只受到总线的最大电容400pF 限制。
发送器:发送数据到总线的器件;
接收器:从总线接收数据的器件;
主机:初始化发送产生时钟信号和终止发送的器件;
从机:被主机寻址的器件;
多主机:同时有多于一个主机尝试控制总线但不破坏传输;
仲裁:是一个在有多个主机同时尝试控制总线但只允许其中一个控制总线并使传输不被破坏
的过程;
同步:两个或多个器件同步时钟信号的过程 。
由于连接到I2C 总线的器件有不同种类的工艺,逻辑0(低)和逻辑1(高)的电平不是固定的,它由电源VCC的相关电平决定,每传输一个数据位就产生一个时钟脉冲。
SDA 线上的数据必须在时钟的高电平周期保持稳定。数据线的高或低电平状态只
有在SCL 线的时钟信号是低电平时才能改变 。
图1 I2C位传输数据有效性
SCL 线是高电平时,SDA 线从高电平向低电平切换,这个情况表示起始条件;
SCL 线是高电平时,SDA 线由低电平向高电平切换,这个情况表示停止条件。
起始和停止条件一般由主机产生,总线在起始条件后被认为处于忙的状态,在停止条件的某段时间后总线被认为再次处于空闲状态。
如果产生重复起始条件而不产生停止条件,总线会一直处于忙的状态,此时的起始条件(S)和重复起始条件(Sr) 在功能上是一样的。
图2 起始和停止条件
伪代码:
void i2c_start()
{
SDA=1;
SCL=1;
SDA=0;
SCL=0;
}
Void i2c_stop()
{
SDA=0;
SCL=1;
SDA=1;
SCL=0;
}
发送到SDA 线上的每个字节必须为8 位,每次传输可以发送的字节数量不受限制。每个字节后必须跟一个响应位。首先传输的是数据的最高位(MSB),如果从机要完成一些其他功能后(例如一个内部中断服务程序)才能接收或发送下一个完整的数据字节,可以使时钟线SCL 保持低电平,迫使主机进入等待状态,当从机准备好接收下一个数据字节并释放时钟线SCL 后数据传输继续。
数据传输必须带响应,相关的响应时钟脉冲由主机产生。在响应的时钟脉冲期间发送器释放SDA 线(高)。
在响应的时钟脉冲期间,接收器必须将SDA 线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平。
通常被寻址的接收器在接收到的每个字节后,除了用CBUS 地址开头的数据,必须产生一个响应。当从机不能响应从机地址时(例如它正在执行一些实时函数不能接收或发送),从机必须使数据线保持高电平,主机然后产生一个停止条件终止传输或者产生重复起始条件开始新的传输。
图3 I2C总线数据传输和应答
如果从机接收器响应了从机地址,但是在传输了一段时间后不能接收更多数据字节,主机必须再一次终止传输。这个情况用从机在第一个字节后没有产生响应来表示。从机使数据线保持高电平,主机产生一个停止或重复起始条件。
如果传输中有主机接收器,它必须通过在从机不产生时钟的最后一个字节不产生一个响应,向从机发送器通知数据结束。从机发送器必须释放数据线,允许主机产生一个停止或重复起始条件。
伪代码:
void send_0()
{
SDA=0;
SCL=1;
SCL=0;
}
Void send_1()
{
SDA=1;
SCL=1;
SCL=0;
}
bit Check_Acknowledge()
{
Unsigned char receive_bit;
SDA=1;
SCL=1;
receive_bit =SDA;
SCL=0;
if(receive_bit = =1)
{
return FALSE;
}
return TRUE;
}
void write_byte(unsigned char u8byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
if((u8byte<<i)&0x80)
send_1();
else
send_0();
}
}
void write_n_byte(unsigned char *buffer , unsigned char num)
{
unsigned char i;
i2c_start();
write_byte(address|0x01);
for(i=0;i<num;i++)
{
Write_byte(*(buffer+i))
if(!Check_Acknowledge())
{
i2c_stop();
return (i==num);
}
i2c_stop();
return TRUE;
}
}
unsigned char read_byte()
{
unsigned char b=0,i;receive_data;
for(i=0;i<8;i++)
{
SDA=1; //释放总线
SCL=1; //接受数据
receive_data =SDA;
SCL=0;
if(receive_data ==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
return b;
}
bit read_n_bytes(unsigned char num , unsigned char *buffer)
{
ungsigned char i;
I2c_start();
Write_byte(address&0xfe);
if(!Check_Acknowledge()) //等待接收器应答信号
return FALSE;
for(i=0;i<num;i++)
{
*(buffer+i)=reead_byte();
if(i!=num)
SEND_0(); //发送应答
else
SEND_1(); //发送非应答
}
i2c_Stop();
return TRUE;
}
第一个字节的头7 位组成了从机地址,最低位(LSB)是第8 位,它决定了传输的方向。第一个字节的最低位是“0”,表示主机会写信息到被选中的从机;“1”表示主机会向从机读信息,当发送了一个地址后,系统中的每个器件都在起始条件后将头7 位与它自己的地址比较,如果一样,器件会判定它被主机寻址,至于是从机接收器还是从机发送器,都由R/W 位决定。
图 4 普通的和带重复开始条件的7位地址格式
伪代码:
Void send_7bit_address(unsigned char address)
{
Write_byte(address); //地址含R/W信号
if(!Check_Acknowledge()) //等待接收器应答信号
return FALSE;
else
return TRUE;
}
10位寻址和7 位寻址兼容,而且可以结合使用。
10位寻址采用了保留的1111XXX 作为起始条件(S),或重复起始条件(Sr )的后第一个字节的头7 位。
10 位寻址不会影响已有的7 位寻址,有7 位和10 位地址的器件可以连接到相同的I2C 总线。它们都能用于标准模式(F/S)和高速模式(Hs)系统。
保留地址位1111XXX 有8 个组合,但是只有4 个组合11110XX 用于10 位寻址,剩下的4个组合11111XX 保留给后续增强的I2C 总线。
10 位从机地址是由在起始条件(S) 或重复起始条件(Sr )后的头两个字节组成。
第一个字节的头7 位是11110XX 的组合,其中最后两位(XX) 是10 位地址的两个最高位(MSB)。
第一个字节的第8 位是R/W 位,决定了传输的方向,第一个字节的最低位是“0”表示主机将写信息到选中的从机,“1 ”表示主机将向从机读信息。
如果R/W 位是“0 ”,则第二个字节是10 位从机地址剩下的8 位;如果R/W 位是“1” 则下一个字节是从机发送给主机的数据。
图5 I2C总线10位地址格式
伪代码:
bit send_10bit_address(unsigned int address)
{
Write_byte(unsigned char (address>>8)); //地址含R/W信号
if(!Check_Acknowledge()) //等待接收器应答信号
return FALSE;
write_byte(unsigned char address);
if(!Check_Acknowledge()) //等待接收器应答信号
return FALSE;
return TRUE;
}
文章评论(0条评论)
登录后参与讨论