zoukankan      html  css  js  c++  java
  • 【转】三种方法让你在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); //改变参数可以改变读取频率 }
  • 相关阅读:
    Java基础——链表的添加、移除、反转
    Java基础——数组队列的原理和实现
    Java基础——String、StringBuiler、StringBuffer的用法和区别
    Java基础——解决JFrame.setBackground设置无效,mac系统IDEA编译器
    Java基础——文件查找创建删除
    Java基础——Java异常机制
    线性表的操作
    Linux目录及文件系统操作
    Linux用户及文件权限管理
    Linux日志系统
  • 原文地址:https://www.cnblogs.com/schips/p/10795711.html
Copyright © 2011-2022 走看看