本帖最后由 forgot 于 2023-2-15 11:38 编辑
前面说到了三线制的SPI和四线制的SPI,今天说一下I2C总线,I2C总线由SDA(串行数据线)和SCL(串行时钟线)两条线构成,是典型的半双工,而不是全双工,同一时间只可以单向通信。而I2C的总从通讯主要由判断I2C总线上的每个设备的唯一的地址,来确保不同设备之间访问的准确性,也就是说挂在总线上的每个I2C设备,都由一个属于自己的固定地址,并且I2C总线规范规定,标准模式I2C,从机地址为7位长,其次是1个读/写位。该地址可由软件设定,也可以通过一些外部的配置进行改变,如一些液晶模块,可以通过电阻来选择不同的地址,比较灵活。但是在一主多从的设计中,只能允许有一个主机。
由于总线结构的限制,I2C的通讯速率没有SPI高,标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下最高可达3.4 Mbit/s,具体要根据器件本身的通讯性能还有设计线路的可靠性进行速率匹配。
I2C的通讯过程由起始、应答、结束三部分构成。 I2C开始条件:在SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据; I2C应答信号:接收数据的乙方在接收到数据之后,向发送数据的一方发出特定的低电平脉冲,表示已经收到数据。主机向从机发出一个信号之后,等待从机发出应答信号,在主机接收到应答信号之后,根据实际情况进行数据传输。 I2C结束条件:在SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据;
实际开发过程中,往往可以不检测应答信号,也是可以进行通讯的。现在的很多单片机都内置了I2C外设,在使用上只需要配置好对应的管脚、模式、速率以及地址等参数就可以进行通讯,但是由于硬件I2C设计的固定,对于应答等方面有了固定的要求,并不便于调整,还有很多单片机本身就没有I2C,所以现在很多设计都喜欢采用IO口模拟时序的方式来实现。实现过程如下:
首先先选择好对应SDA和SCL的管脚进行GPIO口的配置,然后通过GPIO的操作函数可实现管脚的置高于置低控制。 再根据前面提到的起始、应答、结束编写对应的功能函数: 开始信号,停止信号,等待应答信号、发送应答信号等 void IIC_Start()
{
OLED_SCLK_Set();
OLED_SDIN_Set();
MY_Delay(1);
OLED_SDIN_Clr();
MY_Delay(1);
}
void IIC_Stop()
{
OLED_SCLK_Set();
MY_Delay(1);
OLED_SDIN_Clr();
MY_Delay(1);
OLED_SDIN_Set();
MY_Delay(1);
}
最后根据实际需要编写读写函数: 发送一个字节,读取一个字节等,以SSD1306为例:
void Write_IIC_Command(unsigned char IIC_Command)
{
IIC_Start();
Write_IIC_Byte(0x78);//Slave address,SA0=0
IIC_Wait_Ack();
Write_IIC_Byte(0x00);//write command
IIC_Wait_Ack();
Write_IIC_Byte(IIC_Command);
IIC_Wait_Ack();
IIC_Stop();
}
void Write_IIC_Data(unsigned char IIC_Data)
{
IIC_Start();
Write_IIC_Byte(0x78);//D/C#=0; R/W#=0
IIC_Wait_Ack();
Write_IIC_Byte(0x40);//write data
IIC_Wait_Ack();
Write_IIC_Byte(IIC_Data);
IIC_Wait_Ack();
IIC_Stop();
}
最后总结一下,I2C由于是两条总线构成,给开发节省了管脚和走线,简化了PCB的布局布线,降低了系统开发成本,对于速率要求不是特别高的地方,已经成为很多设计首选总线类型之一。
|