I2C通信是如何工作的?Arduino和I2C教程

在本教程中,我们将学习I2C通信协议的工作原理,并使用Arduino板和使用该协议的传感器制作一个实际示例。你可以观看下面的视频或阅读下面的书面教程。

概述

I2C通信总线非常流行,并被许多电子设备广泛使用,因为它可以在许多需要在主设备和多个从设备甚至多个主设备之间进行通信的电子设计中轻松实现n在使用7位寻址时,最多128(112)个设备之间,在使用10位寻址时,最多1024(1008)个设备之间。

I2C-通信-概述1

I2C是如何工作的

这么多设备之间的通信怎么可能只用几根电线?每个设备都有一个预设的ID或一个唯一的设备地址,因此主机可以选择与哪些设备通信。

这两条线被称为串行时钟(SCL)和串行数据(SDA)。SCL线是同步I2C总线上设备之间的数据传输的时钟信号,它由主设备生成。另一条线是承载数据的SDA线。

这两条线路是“开漏”,这意味着需要将上拉电阻器连接到它们上,以便线路为高电平,因为I2C总线上的设备为低电平。电阻器的常用值从2K(高速时约为400Kbps)到10K(低速时约为100Kbps)。

I2C通信——工作原理

I2C协议

数据信号以8位序列传输。因此,在一个特殊的启动条件发生后,出现了前8位序列,这表明数据被发送到的奴隶的地址。在每个8位序列后面跟着一个称为确认的位。在大多数情况下,在第一个确认位之后是另一个寻址序列,但这次是用于从设备的内部寄存器。在寻址序列之后紧跟许多数据序列,直到数据完全发送并以一个特殊的停止条件结束。
I2C-Communcation-Protocol

让我们更仔细地看看这些事件。当数据线下降而时钟线仍然高时,启动条件发生。在此之后,时钟开始,每个数据位在每个时钟脉冲期间被传输。

设备寻址序列以最高有效位(MSB)开头,以最低有效位(LSB)结尾,实际上由7位组成,因为th位用于指示主服务器是写从服务器(逻辑低)还是读从服务器(逻辑高)。

I2C-Bits-Protocol

下一个位AKC/ NACK被从设备用来指示它是否已经成功地接收到前面的位序列。因此,此时主设备将SDA线的控制权交给从设备,如果从设备成功地接收到前一个序列,它将把SDA线拉到一个叫做“确认”的状态。如果奴隶没有拉下SDA线,条件被称为not Acknowledge,这意味着它没有成功地接收到前面的序列,这可能是由几个原因造成的。例如,从服务器可能很忙,可能不理解接收到的数据或命令,不能接收更多的数据,等等。在这种情况下,主设备决定它将如何进行。

I2C-Bits-Protocol_ADXL-X-Axis-Example

接下来是内部寄存器寻址。内部寄存器是在从存储器中包含各种信息或数据的位置。例如,ADX345加速度计有一个独特的设备地址和X, Y和Z轴的附加内部寄存器地址。所以如果我们想要读取x轴的数据,首先我们需要发送设备地址,然后是x轴的特定内部寄存器地址。这些地址可以从传感器数据表.

在寻址后,数据传输序列开始从主或从取决于选定的模式在R/W位。当数据完全发送后,传输将以停止条件结束,当SDA线从低到高而SCL线是高时发生。

实例

作为一个例子,我将使用由5个不同传感器组成的GY-80接线板和由3个不同传感器组成的GY-521接线板。所以我们可以从8个不同的传感器获取数据,只需要两根连接I2C总线的电线。

GY-80和GY-521地址

您可以从以下任何网站获得这些组件:

必威外围提钱披露:这些是附属链接。作为一名亚马逊员工,我通过符合条件的购买赚取收入。

下面是我们如何连接这些板。Arduino Board的Serial Clock引脚会连接到两个breakout Board的Serial Clock引脚,Serial Data引脚也是一样,我们会用Arduino Board的Gnd和5V引脚给Board供电。注意,这里我们不使用上拉电阻,因为接线板已经有了。

I2C-and-Arduino-Circuit-Schematics

为了与这些芯片或传感器通信我们需要知道它们的唯一地址。我们可以从传感器的数据表中找到它们。对于GY-80分线板,我们有以下4个地址:3轴加速度计传感器的十六进制0x53, 3轴陀螺仪的十六进制0x69, 3轴磁强计的十六进制0x1E和气压计和温度计传感器的十六进制0x77。

对于GY-521接线板,我们只有一个地址,这是一个十六进制的0x68。我们也可以通过Arduino官网的Arduino I2C Scanner草图来获取或查询地址。在这里,如果我们上传并运行这个草图,我们将得到I2C总线上连接的设备的地址。


传感器部件编号I2C地址

3轴加速度计模拟设备ADXL345 0x53数据表

三轴回旋微电子L3G4200D 0x6必威lol9数据表

霍尼韦尔MC5883L 0x1E三轴磁强计数据表

气压计+温度计Bosch BMP085 0x77数据表


在我们找到设备的地址之后,我们还需要找到它们的内部寄存器的地址,以便从中读取数据。例如,如果我们想从GY-80分接板的3轴加速计传感器读取X轴数据,我们需要找到存储X轴数据的内部寄存器地址。从传感器的数据表中,我们可以看到X轴的数据实际上存储在两个寄存器中,即具有十六进制地址0x32的DATAX0和具有十六进制地址0x33的DATAX1。

Arduino I2C代码

现在让我们编写获取X轴数据的代码。我们将使用Arduino Wire Library,它必须包含在草图中。首先,我们必须定义传感器地址和之前找到的两个内部寄存器地址。这个Wire.begin ()函数将启动Wire library,我们还需要启动串行通信,因为我们将使用串行监视器显示来自传感器的数据。

循环()我们将从Wire.beginTransmission ()该功能将开始传输到特定传感器,在我们的情况下为3轴加速计。然后用Wire.write()函数时,我们将从X轴的两个寄存器请求特定的数据。这个Wire.endTransmission ()将结束传输并从寄存器传输数据。现在Wire.requestFrom ()函数,我们将从两个寄存器请求传输的数据或两个字节。

这个Wire.available()函数将返回可供检索的字节数,如果该数与请求的字节数匹配,则使用Wire.read()函数我们将从X轴的两个寄存器读取字节。最后,我们将把数据打印到串行监视器中。这是数据,但请记住,这是原始数据,需要进行一些数学运算才能获得正确的X轴值。你可以在我的下一个教程中找到更多关于在Arduino板上使用加速度计的详细信息,因为我不想让本教程负担过重,因为它的主要目的是解释Arduino I2C通信是如何工作的。

/**I2C通信协议的工作原理-Dejan提供的Arduino I2C教程**,www.HowToMechatronics.com**/#包括int-bet188官方网站ADXLAddress=0x53;//设备地址,其中还包括用于选择模式的第8位,在本例中读取#为DATAX0内部寄存器定义X轴寄存器DATAX0 0x32//十六进制地址#为DATAX1内部寄存器定义X轴寄存器DATAX1 0x33//十六进制地址#定义电源寄存器0x2D//电源控制寄存器int X0、X1、X_out;void setup(){Wire.begin();//启动线库序列。begin(9600);delay(100);//启用测量线。beginTransmission(ADXLAddress);Wire.write(Power_寄存器);//位D3高用于测量启用(0000 1000)线。write(8);Wire.endTransmission();}void循环(){Wire.beginTransmission(ADXLAddress);//开始传输到传感器//询问特定寄存器的数据线。write(X_轴_寄存器_数据x0);Wire.write(X_轴_寄存器_数据x1);Wire.endTransmission();//结束传输并从两个寄存器线传输数据。requestFrom(ADXLAddress,2);//如果(Wire.available()<=2){//X0=Wire.read();//从寄存器X1=Wire.read();}Serial.print(“X0=”);Serial.print(X0);Serial.print(“X1=”);Serial.println(X1);}