Adafruit TCA9548A 1-to-8 I2C 多路复用器:解决 I2C 设备地址冲突的利器

电子说

1.4w人已加入

描述

Adafruit TCA9548A 1-to-8 I2C 多路复用器:解决 I2C 设备地址冲突的利器

在电子设计中,当我们遇到需要连接多个具有相同 I2C 地址的设备时,常常会陷入困境。不过,Adafruit TCA9548A 1-to-8 I2C 多路复用器的出现,为我们提供了一个完美的解决方案。

文件下载:2717.pdf

一、概述

在使用 I2C 传感器时,我们可能会遇到这样的问题:某个 I2C 传感器芯片具有固定的 I2C 地址,而 I2C 协议不允许在同一 SDA/SCL 引脚上连接两个具有相同地址的设备。这时,TCA9548A 多路复用器就派上用场了。它就像一个门卫,能够根据我们的指令将命令传输到选定的 I2C 引脚组。

该多路复用器本身的 I2C 地址默认为 0x70,但可以在 0x70 到 0x77 之间进行调整。我们只需向该端口写入一个包含所需多路复用输出编号的单字节,后续的 I2C 数据包就会被发送到该端口。理论上,我们可以在 0x70 - 0x77 每个地址上使用 8 个这样的多路复用器,从而控制 64 个具有相同 I2C 地址的设备。

二、引脚说明

1. 电源引脚

  • Vin:电源引脚,传感器芯片使用 3 - 5 VDC 供电。为板子供电时,应提供与微控制器逻辑电平相同的电源,例如对于 5V 的 Arduino 微控制器,使用 5V 电源。
  • GND:电源和逻辑的公共接地端。

2. I2C 控制侧引脚

  • SCL:芯片本身的 I2C 时钟引脚,连接到微控制器的 I2C 时钟线。
  • SDA:芯片本身的 I2C 数据引脚,连接到微控制器的 I2C 数据线。
  • RST:复位引脚,用于复位多路复用器芯片。默认情况下拉高,连接到地即可复位。
  • A0、A1、A2:多路复用器的地址选择引脚。默认情况下,多路复用器的地址为 0x70,这三个引脚被拉低。将它们连接到 Vin 可以将地址设置为 0x71 - 0x77。其中,A0 是最低有效位(拉高时地址增加 1),A1 是次低有效位(拉高时地址增加 2),A2 是第三低有效位(拉高时地址增加 4)。

3. I2C 多路复用侧引脚

有 8 组 SDx 和 SCx 引脚,从 SD0/SC0 到 SD7/SC7。这些是多路复用引脚,每组都是一个完全独立的 I2C 总线集。因此,只要每个设备都连接到一个 I2C 总线上,我们就可以连接 8 个具有相同地址的 I2C 设备。需要注意的是,这些引脚没有安装上拉电阻,如果使用的芯片或扩展板没有 I2C 上拉电阻,一定要添加。而且,Vin 可以是 3.3V,而这些引脚可以上拉到 5V(即它们支持 5V)。

三、组装步骤

1. 准备排针

如果需要,将排针裁剪到合适的长度。将其插入面包板,长引脚朝下,这样更便于焊接。

2. 添加扩展板

将扩展板放在排针上,使短引脚穿过扩展板的焊盘。

3. 焊接

确保焊接所有引脚,以实现可靠的电气连接。如果需要焊接技巧,可以查看相关的焊接指南。

四、Arduino 接线与测试

1. 基本原理

TCA9548A 多路复用器有一个 I2C 地址(默认 0x70),我们可以向它发送命令,告诉它要与哪个 I2C 多路复用输出进行通信,然后就可以对目标板进行寻址。

2. 示例代码

#define TCAADDR 0x70
void tcaselect(uint8_t i) {
  if (i > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 < < i);
  Wire.endTransmission(); 
}

我们可以调用 tcaselect(0)tcaselect(7) 来设置多路复用器。如果碰巧有 I2C 地址为 0x70 的 I2C 设备,需要将 TCA9548 扩展板上的一个地址引脚短接到 Vin,以避免冲突。

3. 示例复用

假设我们要连接两个 HMC5883 扩展板,这些磁力计的固定地址为 0x1E,不能在一个 I2C 总线上连接两个。接线时,将 TCA9548 扩展板的 Vin 连接到 5V(对于 3V 逻辑的 Arduino/微控制器,使用 3.3V),GND 连接到地,SCL 连接到 I2C 时钟,SDA 连接到 I2C 数据。然后将每个传感器扩展板连接到 Vin、地,并使用其中一个 SCn/SDn 多路复用总线。

4. 扫描脚本

#include "Wire.h"
#define TCAADDR 0x70
void tcaselect(uint8_t i) {
  if (i > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 < < i);
  Wire.endTransmission(); 
}
void setup() {
  while (!Serial);
  delay(1000);
  Wire.begin();
  Serial.begin(115200);
  Serial.println("nTCAScanner ready!");
  for (uint8_t t = 0; t < 8; t++) {
    tcaselect(t);
    Serial.print("TCA Port #");
    Serial.println(t);
    for (uint8_t addr = 0; addr <= 127; addr++) {
      if (addr == TCAADDR) continue;
      Wire.beginTransmission(addr);
      if (!Wire.endTransmission()) {
        Serial.print("Found I2C 0x");
        Serial.println(addr, HEX);
      }
    }
    Serial.println("ndone");
  }
}
void loop() {}

运行这个脚本可以检测连接的设备。

5. 多传感器示例

#include < Wire.h >
#include < Adafruit_Sensor.h >
#include < Adafruit_HMC5883_U.h >
#define TCAADDR 0x70
Adafruit_HMC5883_Unified mag1 = Adafruit_HMC5883_Unified(1);
Adafruit_HMC5883_Unified mag2 = Adafruit_HMC5883_Unified(2);
void displaySensorDetails(Adafruit_HMC5883_Unified *mag) {
  sensor_t sensor;
  mag- >getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print("Sensor: ");
  Serial.println(sensor.name);
  Serial.print("Driver Ver: ");
  Serial.println(sensor.version);
  Serial.print("Unique ID: ");
  Serial.println(sensor.sensor_id);
  Serial.print("Max Value: ");
  Serial.print(sensor.max_value);
  Serial.println(" uT");
  Serial.print("Min Value: ");
  Serial.print(sensor.min_value);
  Serial.println(" uT");
  Serial.print("Resolution: ");
  Serial.print(sensor.resolution);
  Serial.println(" uT");
  Serial.println("------------------------------------");
  delay(500);
}
void tcaselect(uint8_t i) {
  if (i > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 < < i);
  Wire.endTransmission(); 
}
void setup(void) {
  Serial.begin(9600);
  Serial.println("HMC5883 Magnetometer Test");
  Serial.println("");
  tcaselect(2);
  if (!mag1.begin()) {
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while (1);
  }
  tcaselect(6);
  if (!mag2.begin()) {
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while (1);
  }
  tcaselect(2);
  displaySensorDetails(&mag1);
  tcaselect(6);
  displaySensorDetails(&mag2);
}
void loop(void) {
  sensors_event_t event;
  tcaselect(2);
  mag1.getEvent(&event);
  Serial.print("Sensor #1 - ");
  Serial.print("X: ");
  Serial.print(event.magnetic.x);
  Serial.print(" ");
  Serial.print("Y: ");
  Serial.print(event.magnetic.y);
  Serial.print(" ");
  Serial.print("Z: ");
  Serial.print(event.magnetic.z);
  Serial.println(" uT");
  tcaselect(6);
  mag2.getEvent(&event);
  Serial.print("Sensor #2 - ");
  Serial.print("X: ");
  Serial.print(event.magnetic.x);
  Serial.print(" ");
  Serial.print("Y: ");
  Serial.print(event.magnetic.y);
  Serial.print(" ");
  Serial.print("Z: ");
  Serial.print(event.magnetic.z);
  Serial.println(" uT");
  delay(500);
}

通过添加 tcaselect() 函数,我们可以与两个传感器进行通信。

6. 多个多路复用器

由于 TCA9548 是可寻址的,我们可以在总线上使用多个多路复用器。有 8 个可能的地址,这意味着我们可以控制多达 64 个独立的 I2C 总线。为了避免不同多路复用器上具有相同地址的设备之间发生冲突,可以使用以下代码禁用多路复用器上的所有通道:

Wire.beginTransmission(TCAADDR1);
Wire.write(0); // no channel selected
Wire.endTransmission();

五、CircuitPython 与 Python

1. 安装 TCA9548A 库

需要安装 Adafruit_Blinka 库,该库为 Python 提供 CircuitPython 支持。这可能还需要在平台上启用 I2C 并验证是否运行 Python 3。由于每个平台略有不同,并且 Linux 经常变化,请访问 CircuitPython on Linux 指南来准备好计算机。安装完成后,从命令行运行以下命令:

sudo pip3 install adafruit-circuitpython-tca9548a

如果默认 Python 是版本 3,可能需要运行 pip 而不是 pip3。请确保不要在 Python 2.x 上使用 CircuitPython,因为它不支持。

2. CircuitPython 用法

使用 CircuitPython 时,需要先将 TCA9548A 库及其依赖项安装到 CIRCUITPY 驱动器的 lib 文件夹中,然后用示例脚本更新 code.py。可以点击下载项目捆绑包按钮,下载必要的库和 code.py 文件的压缩包,解压后将整个 lib 文件夹和 code.py 文件复制到 CIRCUITPY 驱动器。

3. Python 用法

在计算机上使用 pip3 安装库后,将示例代码复制或下载到计算机上,运行以下命令:

python3 code.py

4. 简单测试示例代码

import board
import adafruit_tca9548a
i2c = board.I2C()
tca = adafruit_tca9548a.TCA9548A(i2c)
for channel in range(8):
    if tca[channel].try_lock():
        print("Channel {}:".format(channel), end="")
        addresses = tca[channel].scan()
        print([hex(address) for address in addresses if address != 0x70])
        tca[channel].unlock()

这个简单的测试会对 TCA9548A 的所有八个端口进行 I2C 扫描,如果有设备连接,会将 I2C 地址打印到 REPL 中。

5. 多传感器示例代码

import time
import board
import adafruit_tsl2591
import adafruit_tca9548a
i2c = board.I2C()
tca = adafruit_tca9548a.TCA9548A(i2c)
tsl1 = adafruit_tsl2591.TSL2591(tca[0])
tsl2 = adafruit_tsl2591.TSL2591(tca[1])
while True:
    print(tsl1.lux, tsl2.lux)
    time.sleep(0.1)

在这个多传感器示例中,TCA9548A 作为 I2C 多路复用器与两个 TSL2591 光传感器一起使用。循环中,每 0.1 秒将两个光传感器的读数打印到 REPL 中。

六、下载资源

可以下载 TCA9548A 的数据手册、Adafruit Fritzing 库中的 Fritzing 对象以及 GitHub 上的 EagleCAD PCB 文件,还能查看原理图和制造图纸。

总之,Adafruit TCA9548A 1-to-8 I2C 多路复用器为解决 I2C 设备地址冲突问题提供了一个简单而有效的解决方案。无论是使用 Arduino 还是 CircuitPython/Python,都能轻松实现多个相同地址 I2C 设备的连接和通信。大家在实际应用中有没有遇到过类似的地址冲突问题呢?又是如何解决的呢?欢迎在评论区分享交流。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 相关推荐
  • 热点推荐

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分