原理
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);
}