原理图:
图 I2C接口的RTC芯片
图 单片机I2C部分引脚图
软件
启动I2C
启动Wire库并作为主机或者从机加入总线,这个函数调用一次即可,参数为7位从机地址,不带参数就以主机的形式加入总线。
Wire.begin();
Wire.begin(address);
主设备从从设备请求字节
由主设备向从设备请求字节,之后用available()和read()函数读取字节,第三个参数位为stop,在请求后会发送停止消息,释放I2C总线,否则总线就不会被释放。
Wire.requestFrom(address, quantity);
Wire.requestFrom(address, quantity, stop);
给指定地址的从设备传输数据
给指定地址的从设备传输数据,之后调用write()函数排队传输字节,要通过endTransmission()
结束传输。
Wire.beginTransmission(address)
endTransmission()
有以下几个返回结果:
-
0:成功
-
1:数据太长,无法放入发送缓冲区
-
2:在发送地址时收到 NACK
-
3:在发送数据时收到 NACK
-
4:其他错误
写数据
向从设备写入数据,在调用 beginTransmission()
和 endTransmission()
之间。
Wire.write(value)
Wire.write(string)
Wire.write(data, length)
举个例子
#include <Wire.h>
byte val = 0;
void setup()
{
Wire.begin(); // join i2c bus
}
void loop()
{
Wire.beginTransmission(44); // transmit to device #44 (0x2c)
// device address is specified in datasheet
Wire.write(val); // sends value byte
Wire.endTransmission(); // stop transmitting
val++; // increment value
if(val == 64) // if reached 64th position (max)
{
val = 0; // start over from lowest value
}
delay(500);
}
读数据
调用requestFrom()后从从设备读取数据。
Wire.read()
举个例子
#include <Wire.h>
void setup(){
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop(){
Wire.requestFrom(2, 6); // request 6 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);
}
还有其它一些函数,例如修改时钟频率等等,大家用到的时候自行了解一下。
完整程序
这里我们用一个例子来演示一下,I2C启动之后,我们开始扫描总线上存在的设备,并通过串口打印结果出来,我在I2C下面接了一个OLED的设备。
#include "Wire.h"
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println("Scanning for I2C Devices ...");
Serial.print("\r\n");
int I2CDevices = 0;
byte address;
Wire.begin();
for (address = 1; address < 127; address++)
{
Wire.beginTransmission(address);
if (Wire.endTransmission() == 0) //发送成功
{
Serial.print("Found I2C Device: ");
Serial.print(" (0x");
if (address < 16)
{
Serial.print("0");
}
Serial.print(address, HEX);
Serial.println(")");
I2CDevices++;
}
}
if (I2CDevices == 0)
{
Serial.println("没有发现I2C设备!\n");
}
else
{
Serial.print("发现了");
Serial.print(I2CDevices);
Serial.println("个I2C设备!\n");
}
}
void loop()
{
}
Wire.endTransmission()
返回0,代表这个地址通信成功,我们就认为总线上存在这个地址的设备。
标签:begin,Wire,项目,esp32,address,Serial,I2C,设备 From: https://www.cnblogs.com/FBsharl/p/18241678