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


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM