ref:http://tieba.baidu.com/p/3769008030
对于不同地址的模块就不用多说了,直接分别对其地址进行通信即可。那么若拿到相同地址的模块,或者直接是相同的多个模块怎么办呢?
经过楼主对adxl345的苦苦摸索,这里给大家分享三种方法。
方法一:(内置了两种地址的模块)
对于内置了两种地址的模块,可以通过对某个引脚置高或置低来选择其中一个地址,现假设置高为A,置低为B。
假设你有三个模块要同时通信,首先将模块1置高,模块2、模块3的地址选择口置低,这样仅有模块1在地址A,然后对地址A进行通信即可防止其他模块干扰。接下来将模块1置低,模块2置高,即可对模块2通信。循环下去即可实现同时对三个模块通信。
方法二:(具有使能端的模块)
若你手中的模块某个引脚必须拉低或拉高才能正常使用,那么仿照方法一,对其中一个使能,其他均处于非使能状态,如此便可以仅对其中一个模块通信咯。
如果以上都不行,那就只能方法三了。
万能方法三:(什么都没有,仅有一种地址的模块)
原本买来六个ADXL345来读取不同地方的加速度信息,datasheet里说可以通过对某个引脚置高置低来选择其中一个地址。然而发现并不能改变地址!于是只好想出这样一个邪恶的方法。
用到的工具是模拟开关,楼主以CD4053为例,这货非常便宜,几元钱可以买一大把。
简单来说模拟开关相当于多个单刀双掷开关,可以通过IO口输出高低电平控制某两路连通。
我们知道I2C通信有 SCL和SDA两根线,我们通过调整模拟开关使仅有一个模块完整接入I2C BUS即可实现只对其中一个通信。
具体实施方式:
假设有模块1 2 3
CD4053的 ay by cy悬空 ax bx cx并接到单片机的SCL
将模块1的SCL口接CD4053的a口
将模块2的SCL口接CD4053的b口
将模块3的SCL口接CD4053的c口
这样只需将A置高,B、C置低,即可与模块1通信
故同理,将B置高,A、C置低,即可与模块2通信
故同理,将C置高,A、B置低,即可与模块3通信
亲测有效,读数稳定,
不过注意一定要将CD4053 VEE和VSS都接地,不然读数抖动不稳定,楼主在这里卡死了很久。
上代码 以ADXL345为例:
boolean x=true; //是否调试输出 //CD4053的接入方式 //INH口接地 aY->SCL1 bY->SCL2 cY->SCL3 a.b.c->SCL_Arduino #define CD4053_C 10 #define CD4053_B 9 #define CD4053_A 8 //----------1 //CBA 000 不接通 //CBA 100 C接通 //CBA 010 B接通 //CBA 001 A接通 //----------2 //PIN #define PIN_SDA 20 #define PIN_SCL 21 //I2C (sparkfun breakout) #define Register_ID 0 #define Register_2D 0x2D #define Register_X0 0x32 #define Register_X1 0x33 #define Register_Y0 0x34 #define Register_Y1 0x35 #define Register_Z0 0x36 #define Register_Z1 0x37 #include <Wire.h> int ADXAddress = 0x53; // the default 7-bit slave address int reading = 0; int val=0; int X0,X1,X_out; int Y0,Y1,Y_out; int Z1,Z0,Z_out; double Xg,Yg,Zg; int flag=1; //标志变量 void Wire_Start(){ Wire.beginTransmission(ADXAddress); Wire.write(Register_2D); Wire.write(8); //measuring enable Wire.endTransmission(); // stop transmitting } void Wire_Get()
{ //--------------X Wire.beginTransmission(ADXAddress); // transmit to device Wire.write(Register_X0); Wire.write(Register_X1); Wire.endTransmission(); Wire.requestFrom(ADXAddress,2); if(Wire.available()<=2) { X0 = Wire.read(); X1 = Wire.read(); X1=X1<<8; X_out=X0+X1; } //------------------Y Wire.beginTransmission(ADXAddress); // transmit to device Wire.write(Register_Y0); Wire.write(Register_Y1); Wire.endTransmission(); Wire.requestFrom(ADXAddress,2); if(Wire.available()<=2) { Y0 = Wire.read(); Y1 = Wire.read(); Y1=Y1<<8; Y_out=Y0+Y1; } //------------------Z Wire.beginTransmission(ADXAddress); // transmit to device Wire.write(Register_Z0); Wire.write(Register_Z1); Wire.endTransmission(); Wire.requestFrom(ADXAddress,2); if(Wire.available()<=2) { Z0 = Wire.read(); Z1 = Wire.read(); Z1=Z1<<8; Z_out=Z0+Z1; } //---------------- Xg=X_out/256.0; Yg=Y_out/256.0; Zg=Z_out/256.0; } void setup() { Wire.begin(); if(x) Serial.begin(9600); delay(100); pinMode(CD4053_A,OUTPUT); pinMode(CD4053_B,OUTPUT); pinMode(CD4053_C,OUTPUT); // enable to measute g data digitalWrite(CD4053_A,HIGH); digitalWrite(CD4053_B,LOW); digitalWrite(CD4053_C,LOW); delay(10); Wire_Start(); //初始化模块1 digitalWrite(CD4053_A,LOW); digitalWrite(CD4053_B,HIGH); delay(10); Wire_Start(); //初始化模块2 digitalWrite(CD4053_B,LOW); digitalWrite(CD4053_C,HIGH); delay(10); Wire_Start(); //初始化模块3 } void loop() { if(x){ Serial.print("----"); Serial.print((flag+0)); Serial.println("----");} switch(flag){ case 1: { digitalWrite(CD4053_A,HIGH); digitalWrite(CD4053_C,LOW); Wire_Get(); //读取模块1 flag=2; break; } case 2:{ digitalWrite(CD4053_B,HIGH); digitalWrite(CD4053_A,LOW); Wire_Get(); //读取模块2 flag=3; break; } case 3:{ digitalWrite(CD4053_C,HIGH); digitalWrite(CD4053_B,LOW); Wire_Get(); //读取模块3 flag=1; break; } } if(x)
{ Serial.print("X= "); Serial.print(Xg); Serial.print(" "); Serial.print("Y= "); Serial.print(Yg); Serial.print(" "); Serial.print("Z= "); Serial.println(Zg); } delay(33); //改变参数可以改变读取频率 }