1. 程式人生 > >【轉】三種方法讓你在I2C通信中同時和多個從機通信

【轉】三種方法讓你在I2C通信中同時和多個從機通信

efi 抖動 萬能 stop ans ole println tran 正常

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); //改變參數可以改變讀取頻率 }

【轉】三種方法讓你在I2C通信中同時和多個從機通信