You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用TCA9548A复用器连接4个ADXL345到Arduino UNO的故障排查

问题解决:TCA9548A多路复用器驱动ADXL345失败排查

核心问题分析

你当前代码存在几个致命问题,直接导致新传感器无法被读取:

  1. TCA9548A通道选择错误:TCA9548A通过单字节的对应位控制通道切换,比如通道2对应0x04(二进制00000100)、通道3是0x08、通道4是0x10、通道5是0x20,你代码里写的0x02、0x03等完全不符合通道选择规则,根本不会切换到目标通道。
  2. ADXL345地址认知错误:ADXL345的I2C地址只有4种可选值:0x53(ADDR接地)、0x1D(ADDR接VCC)、0x52(ADDR接SDA)、0x1C(ADDR接SCL),0x4A/0x4B并非ADXL345的合法地址,你大概率搞错了新传感器的ADDR引脚接线或地址配置。
  3. 数据拼接优先级错误:你写的(Wire.read() | Wire.read() << 8)缺少括号,由于位运算优先级,会导致数据拼接逻辑错误,正确写法是(Wire.read() | (Wire.read() << 8))。
  4. 无通信错误检测:代码里没有检查Wire.endTransmission()和Wire.requestFrom()的返回值,无法快速定位通信失败的具体环节。

修改后的代码

下面是修正所有问题后的代码,假设四个传感器的接线规则为:

  • 通道2:ADDR接地 → 地址0x53
  • 通道3:ADDR接VCC → 地址0x1D
  • 通道4:ADDR接地 → 地址0x53
  • 通道5:ADDR接VCC → 地址0x1D
#include <Wire.h>

// TCA9548A通道定义
#define TCA_CH2 0x04  // 通道2对应位2置1
#define TCA_CH3 0x08  // 通道3对应位3置1
#define TCA_CH4 0x10  // 通道4对应位4置1
#define TCA_CH5 0x20  // 通道5对应位5置1
#define TCA_ADDR 0x70 // TCA9548A默认地址

// ADXL345地址定义
#define ADXL_ADDR_GND 0x53 // ADDR接地
#define ADXL_ADDR_VCC 0x1D // ADDR接VCC

float Xls_out, Yls_out, Zls_out;
float Xrs_out, Yrs_out, Zrs_out;
float Xle_out, Yle_out, Zle_out;
float Xre_out, Yre_out, Zre_out;

// 切换TCA9548A通道
void selectTCAChannel(byte channel) {
  Wire.beginTransmission(TCA_ADDR);
  Wire.write(channel);
  byte result = Wire.endTransmission();
  if (result != 0) {
    Serial.print("TCA通道切换失败,错误码:");
    Serial.println(result);
  }
  delay(10); // 给通道切换留缓冲时间
}

// 初始化单个ADXL345
void initADXL(byte adxlAddr) {
  Wire.beginTransmission(adxlAddr);
  Wire.write(0x2D); // 电源控制寄存器
  Wire.write(8);    // 测量模式(0x08)
  byte result = Wire.endTransmission();
  if (result != 0) {
    Serial.print("ADXL初始化失败,地址:0x");
    Serial.print(adxlAddr, HEX);
    Serial.print(",错误码:");
    Serial.println(result);
  }
  delay(10);
}

// 读取ADXL345数据
void readADXL(byte adxlAddr, float &x, float &y, float &z) {
  Wire.beginTransmission(adxlAddr);
  Wire.write(0x32); // 数据起始寄存器
  byte result = Wire.endTransmission(false); // 保持总线开启
  if (result != 0) {
    Serial.print("ADXL读取指令发送失败,地址:0x");
    Serial.print(adxlAddr, HEX);
    Serial.print(",错误码:");
    Serial.println(result);
    x = y = z = 0;
    return;
  }

  byte bytesRead = Wire.requestFrom(adxlAddr, 6);
  if (bytesRead != 6) {
    Serial.print("ADXL数据读取不完整,仅读取:");
    Serial.println(bytesRead);
    x = y = z = 0;
    return;
  }

  // 正确拼接16位数据(低字节在前)
  int16_t xRaw = Wire.read() | (Wire.read() << 8);
  int16_t yRaw = Wire.read() | (Wire.read() << 8);
  int16_t zRaw = Wire.read() | (Wire.read() << 8);

  // 转换为g值(±2g量程下,分辨率10bit,LSB=4mg)
  x = xRaw / 256.0;
  y = yRaw / 256.0;
  z = zRaw / 256.0;
}

void setup() {
  Serial.begin(9600);
  Wire.begin();
  delay(100);

  // 初始化各个通道的ADXL345
  selectTCAChannel(TCA_CH2);
  initADXL(ADXL_ADDR_GND);

  selectTCAChannel(TCA_CH3);
  initADXL(ADXL_ADDR_VCC);

  selectTCAChannel(TCA_CH4);
  initADXL(ADXL_ADDR_GND);

  selectTCAChannel(TCA_CH5);
  initADXL(ADXL_ADDR_VCC);

  // 输出表头
  Serial.println("CH1,CH2,CH3,CH4,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12");
}

void loop() {
  // 读取通道2的ADXL345
  selectTCAChannel(TCA_CH2);
  readADXL(ADXL_ADDR_GND, Xls_out, Yls_out, Zls_out);
  Serial.print(Xls_out, 4);
  Serial.print(",");
  Serial.print(Yls_out, 4);
  Serial.print(",");
  Serial.print(Zls_out, 4);

  // 读取通道3的ADXL345
  selectTCAChannel(TCA_CH3);
  readADXL(ADXL_ADDR_VCC, Xrs_out, Yrs_out, Zrs_out);
  Serial.print(",");
  Serial.print(Xrs_out, 4);
  Serial.print(",");
  Serial.print(Yrs_out, 4);
  Serial.print(",");
  Serial.print(Zrs_out, 4);

  // 读取通道4的ADXL345
  selectTCAChannel(TCA_CH4);
  readADXL(ADXL_ADDR_GND, Xle_out, Yle_out, Zle_out);
  Serial.print(",");
  Serial.print(Xle_out, 4);
  Serial.print(",");
  Serial.print(Yle_out, 4);
  Serial.print(",");
  Serial.print(Zle_out, 4);

  // 读取通道5的ADXL345
  selectTCAChannel(TCA_CH5);
  readADXL(ADXL_ADDR_VCC, Xre_out, Yre_out, Zre_out);
  Serial.print(",");
  Serial.print(Xre_out, 4);
  Serial.print(",");
  Serial.print(Yre_out, 4);
  Serial.print(",");
  Serial.print(Zre_out, 4);
  
  Serial.println();
  delay(50); // 控制输出频率
}

额外排查步骤

  1. 用Arduino的I2C扫描工具确认TCA9548A的地址是否为0x70,以及切换每个通道后,对应通道的ADXL345地址是否能被扫描到。
  2. 检查新传感器的ADDR引脚接线,确保地址和代码里的定义一致。
  3. 检查所有传感器的VCC、GND、SDA、SCL接线是否牢固,TCA9548A的SDA/SCL要接Arduino UNO的A4/A5引脚。

内容的提问来源于stack exchange,提问作者Benjamin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:24:50