Arduino 简明教程

Arduino - Inter Integrated Circuit

集成电路间总线 (I2C) 是一种新一代微控制器和专用集成电路之间进行串行数据交换的系统。当它们之间的距离较短(接收器和发送器通常位于同一块印刷电路板上)时,它会被使用。连接通过两条导线建立。一条用于数据传输,另一条用于同步(时钟信号)。

如图所示,一台设备始终作为主设备。在通信开始之前,它会对一个从设备进行寻址。通过这种方式,一个微控制器可以与 112 个不同的设备通信。波特率通常为 100 Kb/s(标准模式)或 10 Kb/s(低波特率模式)。最近出现了波特率为 3.4 Mb/s 的系统。通过 I2C 总线通信的设备之间的距离限制为几米。

i2c

Board I2C Pins

I2C 总线由两个信号组成 - SCL 和 SDA。SCL 是时钟信号,SDA 是数据信号。当前总线主设备始终生成时钟信号。某些从设备有时可能强制将时钟降至低电平,以延迟主设备发送更多数据(或在主设备尝试将其时钟化之前需要更多时间准备数据)。这称为“时钟拉伸”。

以下是不同 Arduino 板的引脚−

  1. Uno、Pro Mini A4 (SDA)、A5 (SCL)

  2. Mega、Due 20 (SDA)、21 (SCL)

  3. Leonardo、Yun 2 (SDA)、3 (SCL)

Arduino I2C

我们有两种模式 - 主设备代码和从设备代码 - 使用 I2C 连接两个 Arduino 板。它们是−

  1. 主设备发送器/从设备接收器

  2. 主设备接收器/从设备发送器

Master Transmitter / Slave Receiver

现在让我们看看什么是主设备发送器和从设备接收器。

Master Transmitter

以下函数用于初始化 Wire 库,并将作为主设备或从设备加入 I2C 总线。此操作通常只调用一次。

  1. Wire.begin(address) − 在我们的例子中,地址是 7 位从机地址,因为没有指定主机,它会作为主机加入总线。

  2. Wire.beginTransmission(address) − 使用给定的地址开始向 I2C 从机设备传输。

  3. Wire.write(value) − 将字节排队从主机传输到从机设备(介于 beginTransmission() 和 endTransmission() 调用之间)。

  4. Wire.endTransmission() − 结束由 beginTransmission() 开始的对从机设备的传输,并传输由 wire.write() 排队的字节。

Example

#include <Wire.h> //include wire library

void setup() //this will run only once {
   Wire.begin(); // join i2c bus as master
}

short age = 0;

void loop() {
   Wire.beginTransmission(2);
   // transmit to device #2
   Wire.write("age is = ");
   Wire.write(age); // sends one byte
   Wire.endTransmission(); // stop transmitting
   delay(1000);
}

Slave Receiver

使用以下函数 −

  1. Wire.begin(address) − 地址是 7 位从机地址。

  2. Wire.onReceive(received data handler) − 从机设备从主机接收数据时调用的函数。

  3. Wire.available() − 返回可通过 Wire.read() 检索的字节数。应该在 Wire.onReceive() 处理程序中调用此函数。

Example

#include <Wire.h> //include wire library

void setup() {  //this will run only once
   Wire.begin(2); // join i2c bus with address #2
   Wire.onReceive(receiveEvent); // call receiveEvent when the master send any thing
   Serial.begin(9600); // start serial for output to print what we receive
}

void loop() {
   delay(250);
}

//-----this function will execute whenever data is received from master-----//

void receiveEvent(int howMany) {
   while (Wire.available()>1) // loop through all but the last {
      char c = Wire.read(); // receive byte as a character
      Serial.print(c); // print the character
   }
}

Master Receiver / Slave Transmitter

现在让我们了解一下什么主机接收器和从机发送器。

Master Receiver

主机被编程为请求,然后读取从唯一寻址的从机 Arduino 发送的数据字节。

使用以下函数 −

Wire.requestFrom(address,number of bytes) − 主机用来从从机设备请求字节。然后可以用 wire.available() 和 wire.read() 函数检索字节。

Example

#include <Wire.h> //include wire library void setup() {
   Wire.begin(); // join i2c bus (address optional for master)
   Serial.begin(9600); // start serial for output
}

void loop() {
   Wire.requestFrom(2, 1); // request 1 bytes from slave device #2
   while (Wire.available()) // slave may send less than requested {
      char c = Wire.read(); // receive a byte as character
      Serial.print(c); // print the character
   }
   delay(500);
}

Slave Transmitter

使用以下函数。

Wire.onRequest(handler) − 当主机从该从机设备请求数据时,会调用一个函数。

Example

#include <Wire.h>

void setup() {
   Wire.begin(2); // join i2c bus with address #2
   Wire.onRequest(requestEvent); // register event
}

Byte x = 0;

void loop() {
   delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()

void requestEvent() {
   Wire.write(x); // respond with message of 1 bytes as expected by master
   x++;
}