在本教程中,我们将学习如何将 TCA9548A I2C 多路复用器与 Arduino 结合使用。我们将讨论如何通过整合硬件解决方案来使用多个具有相同地址的 Arduino 的 I2C 设备。通过使用 TCA9548A I2C 多路复用器,我们将能够增加 Arduino 的 I2C 地址范围,并能够连接 8 个具有相同地址的 I2C 设备。
TCA9548A 是一款 1 至 8 I2C 多路复用器。通过将设备连接到多路复用器并选择要通过多路复用器进行通信的设备,您可以在单个微控制器上使用最多 8 个具有相同地址的 I2C 从设备。
Arduino I2C 通信引脚
对于 I2C 通信,不同的 Arduino 板有不同的引脚专用为 SDA 和 SCL 引脚。下面的列表显示了各种板上的这些引脚号。
- 在 Arduino UNO 中,引脚 A4 = SDA,引脚 A5 = SCL
- 对于 Arduino Mega2560,引脚 20 = SDA,引脚 21 = SCL
- 在 Arduino Leonardo 中,引脚 2 = SDA,引脚 3 = SCL
- 对于 Arduino Due,引脚 20 = SDA,引脚 21 = SCL、SDA1、SCL。
在 Arduino 中使用多个不同地址从属 I2C 设备
在本节中,我们将首先使用默认的 I2C 引脚将三个不同的 I2C 设备(OLED、SHT32(温度传感器)和 BME280(温度传感器))与 Arduino 连接。然后我们将对我们的板进行编程以运行 I2C 扫描仪。
所需组件
- Arduino
- SSD1306 OLED显示屏
- BME280传感器
- SHT31传感器
- 面包板
- 连接线
Arduino 与 OLED、BME280 和 SHT31 的接口
让我们看看如何将 Arduino 与 OLED、BME280 模块和 SHT31 模块连接在一起。我们将使用一条公共 I2C 线来连接所有设备。Arduino 将充当主机,BME280 传感器、SHT31 传感器和 OLED 将充当从机。
我们使用的四个设备之间的连接如下表所示。
Arduino | SSD1306 OLED显示屏 | BME280 | SHT31 |
3.3V | VCC | VCC | VCC |
A4 | SDA | SDA | SDA |
A5 | SCL | SCL | SCL |
接地 | GND | GND | GND |
我们使用了上表中指定的相同连接。
Arduino I2C 扫描仪 Arduino 草图
每个 I2C 设备都有一个与其关联的地址。Arduino 使用该地址通过 I2C 协议与从机进行通信。
现在复制此代码并将其上传到您的开发板以及已连接的所有 I2C 设备。
此代码将扫描与 Arduino 连接的任何 I2C 设备,并指定串行终端中具有地址的设备数量。
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(115200);
Serial.println("\nI2C Scanner");
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++ ) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.println(address,HEX);
nDevices++;
}
else if (error==4) {
Serial.print("Unknown error at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.println(address,HEX);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found\n");
}
else {
Serial.println("done\n");
}
delay(5000);
Serial.print("i2c devices found:");
Serial.println(nDevices);
}
void loop() {
}
I2C 扫描器识别出 3 个连接到 I2C 接口的设备。OLED显示屏的I2C地址是0x3C,SHT31是0x44,BME280是0x76。
由于这三个 I2C 设备都有不同的地址,因此可以共享相同的 I2C 总线。
Arduino 在 OLED 上显示 BME280 和 SHT31 温度读数
从 I2C 扫描仪中可以看出,BME280、SHT31 和 OLED 具有不同的 I2C 地址,因此可以共享相同的 I2C 总线。让我们向您展示一个 Arduino 草图,它可以访问这两个传感器的温度读数并将其显示在 OLED 上。
我们将使用 Arduino IDE 对 Arduino 开发板进行编程。因此,您应该拥有最新版本的 Arduino IDE。
在 Arduino IDE 中安装 SSD1306 OLED 库
要在我们的项目中使用 OLED 显示屏,我们必须在 Arduino IDE 中安装 Adafruit SSD 1306 库。按照以下步骤即可成功安装。
打开 Arduino IDE 并单击 Sketch > Library > Manage Libraries。将打开以下窗口。
在搜索选项卡中输入“SSD1306”并安装 Adafruit SSD1306 OLED 库。
安装 BME280 Arduino 库
当我们将 BME280 传感器与 Arduino 连接时。因此,我们必须将 BME280 库安装到我们的模块中。该项目需要两个库:
- Adafruit_BME280 库
- Adafruit_传感器库
我们将使用 Arduino IDE 中的库管理器来安装最新版本的库。打开 Arduino IDE 并转到 Sketch > Include Libraries > Manage Libraries。 在搜索栏中输入 Adafruit BME280 库名称并安装它们。
打开 Arduino IDE 并转到 Sketch > Include Libraries > Manage Libraries。 在搜索栏中输入 Adafruit 统一传感器库名称并安装。
安装SHT31 Arduino库
由于我们将 SHT31 传感器模块与 Arduino 连接,因此我们必须安装库来访问传感器数据。该项目需要两个库:
- 阿达水果 SHT31
- Adafruit 总线IO
我们将使用 Arduino IDE 中的库管理器来安装最新版本的库。打开 Arduino IDE 并转到 Sketch > Include Libraries > Manage Libraries。 在搜索栏中输入 Adafruit SHT31 并安装最新版本。
在搜索栏中输入 Adafruit BusIO 并安装它。
Arduino 在 OLED 代码上显示 BME280 和 SHT31 温度读数
代码如何运作?
现在,让我们了解代码的每个部分是如何工作的。
代码首先包含代码正常功能所需的所有必要库。Wire.h 将允许我们通过 I2C 协议进行通信。其余的库是我们刚刚安装的用于 BME280 传感器、SHT31 传感器和 OLED 功能的库。
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_SHT31.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
然后,我们通过将其设置在默认 I2C GPIO 引脚上来定义名为“bme”的 Adafruit_BME280 对象,并创建名为“sht31”的 Adafruit_SHT31 对象。
Adafruit_BME280 bme;
Adafruit_SHT31 sht31 = Adafruit_SHT31();
现在,我们创建另一个名为 display 的对象,它将处理 OLED 显示。此外,通过将参数传递给 Adafruit_SSD1306() 函数来定义 OLED 显示屏的尺寸。
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);
setup()
打开串口通讯,波特率为115200。
Serial.begin(115200);
通过调用显示对象的 begin() 方法来初始化 OLED 显示。
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
接下来,我们将通过调用clearDisplay()函数来清除OLED屏幕。此外,我们使用 setTextColor() 函数设置文本的颜色并传递 WHITE 作为参数。如果我们有深色背景,我们将以白色显示文本,如果我们有明亮背景,那么我们将以黑色显示文本。另外,我们使用 setTextSize() 设置字体大小。
display.clearDisplay();
display.display();
display.setTextSize(1);
display.setTextColor(WHITE);
然后,BME280 传感器使用进行初始化,如果发生故障,串行监视器上会打印一条错误消息。同样,SHT31 传感器也被初始化。如果传感器初始化不成功,串行监视器上将打印相关消息。
bool status;
status = bme.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
if (! sht31.begin(0x44)) {
Serial.println("Check circuit. SHT31 not found!");
while (1) delay(1);
}
loop()
在loop()函数中,我们分别使用bme.readTemperature()和sht31.readTemperature获取BME280和SHT31温度读数。这些信息每秒都会显示在 Arduino 串行监视器和 OLED 上。
void loop() {
display.setCursor(0,0);
Serial.print("Temperature BME280 = "); Serial.print(bme.readTemperature()); Serial.println(" °C");
display.print("Temperature: "); display.print(bme.readTemperature()); display.println(" C");
display.setCursor(0,20);
Serial.print("Temperature SHT31 = "); Serial.print(sht31.readTemperature()); Serial.println(" °C");
display.print("Temperature: "); display.print(sht31.readTemperature()); display.println(" C");
Serial.println();
display.display();
display.clearDisplay();
delay(1000);
}
示范
要查看上述代码的演示,请将代码上传到 Arduino。但是,在上传代码之前,请确保从 Tools > Board 选择 Arduino 板,并从Tools > Port选择 Arduino 板连接的正确 COM 端口 。
一旦代码成功上传到开发板,OLED 将开始显示两个传感器的温度读数,如下所示:
此外,您还可以在Arduino串口终端中查看温度读数。记得将波特率设置为115200。
串行监视器
TCA9548A 与 Arduino 具有相同地址的多个 I2C 设备
在上一节中,我们能够在 Arduino 的相同 I2C 引脚上连接三个不同的 I2C 设备。这是因为 Arduino 能够通过其唯一的地址来识别它们。但是,当我们想用Arduino连接多个设备进行I2C通信,但它们的地址相同时,会发生什么情况呢?例如,两个BME280传感器与Arduino连接或两个OLED与Arduino连接。
要在 Arduino 上使用相同的 I2C 设备,我们要么必须更改设备的 I2C 地址,要么使用 I2C 多路复用器。然而,更改设备的地址并不是那么简单,并且它只允许在同一 I2C 总线上使用有限的设备。因此我们可以使用多路复用器,例如。TCA9548A 允许最多 8 个具有相同地址的设备连接到同一 I2C 总线。因此,它的工作电压范围为 3-5.5 伏,因此可以方便地与具有 3.3/5V 逻辑引脚的微控制器一起使用。
下图显示了 TCA9548A 多路复用器,我们将其与具有相同地址的 I2C 设备一起使用,以便与 Arduino 进行通信。
TCA9548A 多路复用器
它是一种电子开关设备,使用户能够将多个 I2C 总线与其自身连接。所有具有相同地址的从站需要连接到不同的总线。为了与从机通信,连接到从机的总线由用户切换,然后寻址。
TCA9548A 多路复用器引脚分配
下图显示了用作 I2C 扩展器的 TCA9548A 多路复用器的引脚排列。
- Vin:这是为模块提供电源的引脚。将Arduino的3.3V或5V引脚与此引脚连接。
- GND:这是提供公共接地的引脚。
- SDA:这是与主设备连接的I2C串行数据引脚。
- SCL:这是与主设备连接的I2C串行时钟引脚。
- RST:该引脚负责复位多路复用器。
- A0、A1、A2:这三个引脚用于更改多路复用器的 I2C 地址。默认情况下,当这些引脚未连接时,其地址为 0x70。借助该模块,单个 I2C 地址最多可扩展为 8 个 I2C 地址。
- SDx、SCx:这些是外部 I2C 通道通道 0 至通道 7。对于具有相同地址的每个 I2C 设备,将 SDA 引脚与 SDx 连接,将 SCL 引脚与 SCx 连接。
Arduino 使用 TCA9548A 多路复用器在 OLED 上显示文本
让我们向您展示如何使用 TCA9548A 多路复用器通过 Arduino 连接和编程具有相同地址 0x3C 的两个 OLED。我们需要以下组件:
所需组件
- Arduino
- 两个 SSD1306 OLED
- TCA9548A 多路复用器
- 四个 10k 欧姆上拉电阻
- 面包板
- 连接线
Arduino 与带有 OLED 的 TCA9548A 多路复用器的接口
让我们向您展示如何将 TCA9548A 多路复用器与 Arduino 和 OLED 连接。Arduino 将充当主机,OLED 将充当从机。
按照下面的示意图连接所有设备。
下表显示了 TCA9548A 与 Arduino 和两个 OLED 连接的引脚。
TCA9548A | 与其余设备的连接 |
vin | Arduino 的 3.3V,两个 OLED 的 VCC |
GND | Arduino 的 GND、两个 OLED 的 GND |
SDA | Arduino的A4 |
SCL | Arduino的A5 |
SD0 | OLED1 的 SDA 带 10k 欧姆上拉电阻 |
SC0 | OLED1 的 SCL 带 10k 欧姆上拉电阻 |
SD1 | OLED2 的 SDA 带 10k 欧姆上拉电阻 |
SC1 | OLED2 的 SCL 带 10k 欧姆上拉电阻 |
Arduino 使用 TCA9548A 多路复用器代码在 OLED 上显示文本
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire, -1);
void TCA9548A(uint8_t bus) //activate particular channel
{
Wire.beginTransmission(0x70); // TCA9548A address is 0x70
Wire.write(1 << bus); // send byte to select bus
Wire.endTransmission();
}
void setup()
{
Serial.begin(115200);
Wire.begin();
delay(100);
TCA9548A(0);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(20, 10);
display.setTextColor(WHITE);
display.println("OLED #1");
display.display();
TCA9548A(1);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(20, 10);
display.setTextColor(WHITE);
display.println("OLED #2");
display.display();
}
void loop() {
}
该代码如何运作?
现在,让我们了解代码的每个部分是如何工作的。
代码首先包含正确代码功能所需的所有必要库。Wire.h 将允许我们通过 I2C 协议进行通信,Adafruit_GFX.h 和 Adafruit_SSD1306.h 是 OLED 库。
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
现在,我们创建一个名为 display 的对象,它将处理 OLED 显示。此外,通过将参数传递给 Adafruit_SSD1306() 函数来定义 OLED 显示屏的尺寸。
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire, -1);
接下来,我们为 TCA9548A() 定义一个函数,它接受一个参数,即 I2C 总线通道。每当我们想要激活特定的 I2C 通道时就会调用此函数。
void TCA9548A(uint8_t bus)
{
Wire.beginTransmission(0x70); // TCA9548A address is 0x70
Wire.write(1 << bus); // send byte to select bus
Wire.endTransmission();
}
设置()
打开串口通信,波特率115200,发起I2C通信。
Serial.begin(115200);
Wire.begin();
接下来,我们通过调用 TCA9548A() 函数来激活 I2C 通道 0,并将 0 作为其中的参数传递。我们的第一个 OLED 与 I2C 通道 0 连接。之后我们初始化 OLED 显示、清屏、设置文本颜色、设置字体大小和光标位置。然后我们在显示屏上打印文本“OLED #1”。
TCA9548A(0);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(20, 10);
display.setTextColor(WHITE);
display.println("OLED #1");
display.display();
接下来,我们通过调用 TCA9548A() 函数作为传递 1 作为其中的参数来激活 I2C 通道 1。我们的第二个OLED与I2C通道1连接。之后我们初始化OLED显示屏,清除屏幕,设置文本颜色,设置字体大小和光标位置。然后我们在显示屏上打印文本“OLED #2”。
TCA9548A(1);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(20, 10);
display.setTextColor(WHITE);
display.println("OLED #2");
display.display();
示范
要查看上述代码的演示,请将代码上传到 Arduino。但是,在上传代码之前,请确保从 Tools > Board 选择 Arduino 板,并从Tools > Port选择 Arduino 板连接的正确 COM 端口 。
一旦代码成功上传到开发板,两个 OLED 将开始显示各自的文本,如下所示: