简介
TCA9458是TI德州仪器的一款iic数据选择器,具有8个iic扩展接口,TCA9548A本身也是一个iic元器件,可以在8个iic地址之间切换。
需求
场景1
现在有一个需求,需要通过iic接口,链接8个LCD1602显示屏,显示不同的内容。但是LCD1602显示屏设备的iic地址相同,均为0x27(常见),现在需要通过TCA9458进行iic地址扩展,使这些显示屏显示不冲突。
场景2
通过io接口模拟的iic地址设备内部定时器不足,需要扩展较多的,具有类似地址特征的iic设备,需要通过TCA9458进行iic地址扩展,使这些设备不冲突。、
使用方式
arduino设备 <=> tca9548 <=> iic设备
iic地址问题
tca9548自身的地址
tca9548也是一个iic器件,本身有iic地址。tca9548自身的地址和它A0,A1,A2口的电平状态有关,组合出8个iic地址。默认地址为0x70(A0,A1,A2全部接地),最大地址为0x77(A0,A1,A2全部上拉)
#define TCAADDR 0x70
tca9548连接器件地址
tca9548的连接接口没有自身固定地址,地址取决于所链接的设备。通过arduino的iic接口,对tca9548发送选址信息,建立和它的不同接口的通信,结合程序说明
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.begin();//开启iic设备总线,mpu6050类必须先开启总线,对于LCD显示屏这行代码可有可无
Wire.beginTransmission(TCAADDR);//向tca9548建立通信
Wire.write(1 << i);//向iic总线写入tca9548选择连通的地址(0~7接口)
Wire.endTransmission(); //关闭通信
}
查询设备链接
查询和tca9548链接的iic设备的有效地址,以下代码直接可以用来在串口输出对应的接口对应的地址
extern "C" {
#include "utility/twi.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(9600);
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;
uint8_t data;
if (! twi_writeTo(addr, &data, 0, 1, 1)) {
Serial.print("Found I2C 0x"); Serial.println(addr,HEX);
}
}
}
Serial.println("\ndone");
}
void loop(){}
两个LCD显示屏例程
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd1(0x27, 16, 2);
LiquidCrystal_I2C lcd2(0x27, 16, 2);
#define TCAADDR 0x70
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
void setup()
{
tcaselect(1); lcd1.init();lcd1.backlight();
lcd1.print("Hello, world! 1");lcd1.setCursor(4,0);
delay(100);
tcaselect(2); lcd2.init(); lcd2.backlight();
lcd2.print("Hello, world! 2");lcd2.setCursor(4,1);
delay(100);
}
void loop()
{
int x=random(0,65535);
tcaselect(1);
lcd1.setCursor(4,1);
lcd1.print(x);
delay(500);
tcaselect(2);
lcd1.setCursor(4,1);
lcd1.print(x);
delay(1000);
}
LCD显示屏显示两个MPU6050 x轴角速度例程,亲测有效可用
#include "LiquidCrystal_I2C.h"
#include "MPU6050_6Axis_MotionApps20.h"//MPU6050库文件
LiquidCrystal_I2C lcd(0x27, 16, 2);
MPU6050 Mpu6050;
#define TCAADDR 0x70
int16_t ax, ay, az, gx, gy, gz; //MPU6050的三轴加速度和三轴陀螺仪数据
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.begin();
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
void setup()
{
Serial.begin(9600);
tcaselect(0);delay(400);
Mpu6050.initialize(); //初始化MPU6050
delay(100);
tcaselect(1);delay(400);
Mpu6050.initialize(); //初始化MPU6050
delay(100);
tcaselect(2);
lcd.init();delay(100);
lcd.setCursor(0,0);
lcd.print("mpu6050");
}
void loop()
{
tcaselect(0);
Mpu6050.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
int gx1 = gx;
tcaselect(1);
Mpu6050.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
int gx2 = gx;
tcaselect(2);
lcd.backlight();
lcd.setCursor(0,1);
lcd.print(gx1);
lcd.setCursor(8,1);
lcd.print(gx2);
delay(200);
lcd.setCursor(0,1);
lcd.print(" ");
}
···