I built an I2C multiplexer shield using an Arduino prototyping shield from SchmartBoard a couple of weeks ago. The shield uses a PCA9548A I2C multiplexer and switch chip from Texas Instruments.

One of the issues with testing I2C using Arduino is that different ICs have different Vcc requirements. While ATMega328P can be powered by either 3.3V or 5V, most Arduino boards are designed to handle only a single supply voltage. So when the supply voltage of the IC is different than that of the Arduino, a voltage level translator such as PCA9517 must be added (you can see an example here).

This is where PCA9548 comes in handy. PCA9548 has 5V tolerate IO ports and when powered with a 3.3V Vcc, it can communicate with either 3.3V or 5V powered I2C devices. And it is also very easy to use. Basically, you first select the channels you want to communicate with and then you can communicate with the I2C device as you would with it directly.

The following code example illustrates this. Here a DS1077 oscillator is connected to the first I2C channel of the PCA9548A (in this example, PCA9548A’s I2C address is set as A2 A1 A0 = 1 0 0).

#define PCA9548ADDR 0x74 //1110100
#define DS1077ADDR 0x58 //1011000

#include <Wire.h>

void setup()
{
  Wire.begin();
  
  //select the first I2C Channel  
  selectI2CChannels(0x1);
  
  //output a 16.67 Mhz clock on output 0
  writeDS1077Reg(0x2, 0x1E, 0x0);  //write mux register CLK/8
}

void loop()
{

}

void selectI2CChannels(int channels) 
{
  Wire.beginTransmission(PCA9548ADDR);
  Wire.write(channels);
  Wire.endTransmission();  
}

void writeDS1077Reg(int cmd, int msb, int lsb) 
{
    Wire.beginTransmission(DS1077ADDR);
    Wire.write(cmd);
    Wire.write(msb);
    Wire.write(lsb);
    Wire.endTransmission();
}

Function writeDS1077Reg sets the output frequency of the DS1077 oscillator to CLK/8 (16.67 Mhz). This is the only line of code needed when the device is attached to Arduino directly.

When attached to PCA9548A, the only difference in code is the selection of the channel on which DS1077 is connected to prior to calling writeDS1077Reg. This is handled via selectI2CChannels function call. This function takes in a single byte that controls which I2C channels are selected. The eight I2C channels of PCA9548A can be addressed using this command byte, with each bit representing a channel.

Multiple I2C channels can be enabled at once. For instance, if both channel 2 and channel 4 are selected the channel command byte would be B00001010, or 0xA. Once the selected channels are activated, they will remain active in subsequent I2C calls until selectI2CChannels is called again to deactivate the channel (i.e. with a 0 in the corresponding bit) or until a power reset.

Besides interfacing I2C devices requiring different supply voltages, PCA9548A is also useful when dealing with multiple I2C devices with the same device address. In this case, we can use PCA9548A to multiplex these devices by ensuring only one channel is active at any given time.

Be Sociable, Share!