有关于通信的协议的有很多,通信协议顾名思义就是两个不同的设备相互交流的一种方式,类似于人们之间的交流。有汉语,英语,俄语,法语,等等。但是两个设备交流也是一样,需要大家都有同一样的协议,才能一起通信,就好像大家都能懂汉语。所以才能的交流。
设备之间的通信协议有很多种,例如I2C,SPI,USART,CAN,以及国际联盟推出的MIPI接口协议这个接口包括DSI、DBI、DPI等等。
下面就来了解一下I2C协它有哪些特点,以及他是怎么通信的,包括他的代码是如何实现的。下面讲得都是极简的方式,是给我自己看的。
首先了解I2C的通信速度
标准模式100Kbps、、快速模式400Kbps、、高速模式3.4Mbps。
I2C总线
支持多个从设备的总线,其中数据线SDA和时钟线SCL。
I2C传输
半双工:同一时间内只能发送或者接受。
I2C协议和时序
必须是起始信号为开始条件,结束信号为传输的停止条件。在这两个条件的中间做发送或者接收字节。
先看一张完整的时序图。
其中时序图可以看到它的一个完整时序,包括开始时序、发送地址8位地址、发送应答、接收数据地址8位、接收应答、停止时序。
其中看到第一发送时序,是SCL高电平期间,SDA数据线是由高电平到低电平的一个变化,最后需要释放SCL的数据总线。
代码可以这样写
void I2C_start(void)
{ //根据时序图来写出开始的条件 如果我们使用得ARM芯片反应很快就需要加延迟延迟可以自行查看I2C实现的延迟最大最小值
I2C_SDA=1;
I2C_SCL=1;
I2C_SDA=0;
I2C_SCL=0;
}
接下来到了发送8位字节。
发送8位字节,看时序图可以知道,在SCL低电平期间,SDA数据线两个设备以及交流也就是发送地址。发送完之后就拉高SCL,这样就完成一个字节发送,而且在SCL高电平期间SDA数据线是不允许有变化的。所以代码可以这样写。
void I2C_SandByte(unsigned char Byte)
{ unsigned char i;
for(i=0;i<8;i++)
{ I2C_SDA=Byte&(0x80>>i); //这里是表示寻址从第一个开始最高位
I2C_SCL=1;
I2C_SCL=0;
}
}
接下来就是发送应答,发送应答就是一方发送完数据,就要告诉另一方,我已经发送完了,你查收一下。
发送应答就是,SDA 数据线,写入一个0或者1告诉我这个是应答信号,然后SCL由高到低电平的一个变化。代码可以这样写。
void I2C_SandAck(unsigned char ACKBit)
{
I2C_SDA=ACKBit;
I2C_SCL=1;
I2C_SCL=0;
}
接下来就是接收字节了,接收字节也是跟发送一样,毕竟你发多少我就要接收多少,首先要把之前的数据线给释放,然后接收字节在SCL低电平期间,主机就会把数据在SDA发送过来,然后再把SCL拉高读取数据。所以读取数据的时候数据是不允许由变化的。也就是SDA不允许变化。这样就可以依次把SDA数据读出来。也就是在SCL高电平的期间读取数据。
代码这样写
unsigned char I2C_ResdByte(void)
{ unsigned char Byte;
unsigned char i;
I2C_SDA=1;
for(i=0;i<8;i++)
{ I2C_SCL=1;
if(I2C_SDA)
Byte|=(0x80>>i);
I2C_SCL=0;
return Byte;
}
接下来就是接收应答,接收应答就是在SCL高电平期间是读取数据的也就是那个时候可以知道有没有应答,但是应答的前提是要释放SDA总线数据。然后再读取SDA的应答信号。然后收完应答就可以把SCL拉低电平了。
unsigned char I2C_ResdACK(void)
{
unsigned char ACKBit;
I2C_SDA=1;
I2C_SCL=1;
ACKBit=I2C_SDA; //0就是应答。1是非应答
I2C_SCL=0;
return ACKBit;
}
最后就是停止时序了,整个信号的最后就是停止。可以看到时序图的SCL高电平期间,SD由低电平到到高电平的一个变化。
void I2C_Stop(void)
{
I2C_SDA=0;
I2C_SCL=1;
I2C_SDA=1;
}
整个时序就在这样的一个过程。