Arduino 之间进行 I2C 通讯

原理

I2C 分为两种模式共四个可能性,分别为

  • Master Transmitter:主动发起 START,并向指定地址的 slave 传送数据,接受来自 slave 的 ACK,传输结束后主动发起 STOP
  • Master Receiver:主动发起 START,并向指定地址的 slave 请求数据,向 slave 发送 ACK 并发起 STOP
  • Slave Transmitter:接受来自 master 向本机地址发起的 START,向 master 传送数据,接受来自 master 的 ACK,并检测是否 STOP
  • Slave Receiver:接受来自 master 向本机地址发起的 START,接受来自 master 的数据,向 master 发送 ACK,并检测是否 STOP

它们这样对应:
Master Transmitter <-> Slave Receiver
Master Receiver <-> Slave Transmitter

接线

两个 Arduino 之间进行 I2C 通信,接线如下

Device SDA SCL
Arduino A4 A5
Arduino A4 A5

注意,因为 I2C 协议需要线与,所以要添加上拉电阻
这里选择 A4 和 A5 各 10k 上拉,如果需要更快的 I2C 通讯速度,可以降低电阻值

接线

加上 Probe

接线

代码

/** I2C_Master_Transmitter.ino
 * 
 * | Arduino | A4 | ---- SDA
 *           | A5 | ---- SCL
 */

#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin();       // join I2C bus as master (no address provided).
}

byte x = 0;

void loop() {
  uint8_t slave_addr = 0x02;
  Serial.println("Finish transmission");
  Wire.beginTransmission(slave_addr); // transmit to device
  Wire.write("x is ");        // sends five bytes
  Wire.write(x);              // sends one byte  
  Wire.endTransmission();    // stop transmitting

  x += 1;
  delay(100);
}

/** I2C_Master_Receiver.ino
 * 
 * | Arduino | A4 | ---- SDA
 *           | A5 | ---- SCL
 */

#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin();       // join I2C bus as master (no address provided).
}

void loop() {
  uint8_t slave_addr = 0x2;
  uint8_t n_bytes = 1;
  Wire.requestFrom(slave_addr, n_bytes);    // request data from slave device

  while (Wire.available() > 0) {  // slave may send less than requested
    char c = Wire.read();         // receive a byte as character
    Serial.print(c);
  }

  delay(100);
}

/** I2C_Slave_Transmitter.ino
 * 
 * | Arduino | A4 | ---- SDA
 *           | A5 | ---- SCL
 */

#include <Wire.h>

void setup() {
  uint8_t device_addr = 0x02;
  Serial.begin(115200);
  Wire.begin(device_addr);            // join I2C bus as slave (address provided)
  Wire.onRequest(requestEvent);       // register event
}

void loop() {
  delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  Serial.println("replied");
  
  Wire.write("hello "); // respond with message of 6 bytes
  // as expected by master
}

/** I2C_Slave_Receiver.ino
 * 
 * | Arduino | A4 | ---- SDA
 *           | A5 | ---- SCL
 */

#include <Wire.h>

void setup() {
  uint8_t device_addr = 0x02;
  Serial.begin(115200);
  Wire.begin(device_addr);            // join I2C bus as slave (address provided)
  Wire.onReceive(receiveEvent);       // register event
}

void loop() {
  delay(100);
}

void receiveEvent(int howMany) {
  while(1 < Wire.available()) {
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);
}

示波器图形

6bc783c308e84c2a6e83d854ef0e784.jpg
325e082278601b3ad2910b15fc88c30.jpg
3061bebce0d25f8dd4f23230e578adb.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在使用单片机的过程中,I2C 通信可以说是最被广泛使用和采纳的协议之一,采用 I2C 协议可以占用更少的资源,链接...
    noparkinghere阅读 2,292评论 0 8
  • I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间...
    WB莫遥燚阅读 5,245评论 0 1
  • 1. I2C接口 ——概述:I2C是一个两线接口,一条数据线、一条时钟线,采用边沿触发方式。使用方式为cpu<——...
    郑行_aover阅读 1,438评论 0 0
  • 1.目的: 写一个关于nrf52832的用硬件I2C驱动一个传感器的流程文档 2.分析: 现在用IIC和BMI16...
    Mo_辉仔阅读 2,406评论 0 0
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,581评论 16 22