This Design Idea explores level-shifting an I2C bus from 5V/ground (positive domain) to ground/–5V (negative domain). In multisupply systems, you sometimes face a situation in which digital information stored in logic circuits running from 5V to ground needs conversion to analog signals referenced to a negative supply. Converting from digital to analog in the positive domain and then level-shifting to reference the negative rail introduces errors and results in a large component count. A better approach is to level-shift the digital data lines and convert with negative-referenced A/D converters. I2C is a bidirectional system employing a two-wire bus: one clock line and one data line. Pullup resistors and open-collector outputs establish dominant-low signaling. Figure 1 shows a typical setup, in which the microcontroller is the master, and all the peripherals are slaves. Each device has a unique I2C address. The master always generates the clock, but, depending on the desired direction of data flow, either the master or the slave could be the transmitter on the data line.
To understand the level-shifting procedure, consider the simple circuit in Figure 2. The circuit level-shifts the clock line unidirectionally. Q1 comes with a pnp, an npn, and four bias resistors, all in one small SOT-363 package. R1 provides the necessary pullup function in the positive domain, and R2 does the same in the negative domain. The operation of the circuit is straightforward. When VIN is set to VDD, Q1 remains off, so VOUT=0V (logic high). When VIN is set to 0V, Q1 is on, so VOUT=VEE (logic low). This unidirectional circuit does not allow the master to detect when the slave holds the clock low. Therefore, if you desire I2C clock-extension (wait-stating), you would need a bidirectional level-shifting circuit.
The data line needs a bidirectional circuit. Even when the master is transmitting, the master needs to detect when the negative-domain slave pulls the data line low on every ninth bit to acknowledge the transmitted byte. Also, when instructed, the slave may need to transmit data back to the master. In the slave-transmitter mode, the slave would have to detect when the master pulls the data line low on every ninth bit to acknowledge the transmitted byte. Despite this added complexity, you can still accomplish the task with just five SOT-363-size packages and five discrete resistors (Figure 3). To see that the circuit in Figure 3 is topologically the same as the one inFigure 2, assume transmission gates IC1 and IC2 are on and ignore the lower half of the circuit for the moment. With SDA_POS set to VDD, Q2 is off, R3 and R4 pull up to 0V, resulting in SDA_NEG=0V (logic high). With SDA_POS set to 0V, Q2 is on, so SDA_NEG~VEE (logic low).
Now, trace the return path from slave to master. With SDA_NEG set to 0V (logic high), Q3 is off, and R1 pulls SDA_POS up to VDD. With SDA_NEG set to VEE (logic low), Q3 is on, and R1||R2 forms a voltage divider with R5 to yield SDA_POS~0V. You select R1, R2, and R5 to yield VDD=5V and VEE=–5.2V. If desired, you could use additional transistors to construct the return path so that it doesn‘t depend on resistors to set logic levels. Transmission gates IC1 and IC2 and Schottky diodes D1A and D1B break the positive feedback path that would otherwise result when either master or slave pulls SDA to a logic low. Note that, without these components, Q2 and Q3 would form a latch. The circuit in Figure 3 easily meets I2C timing requirements at a 50-kHz clock rate. For 100-kHz operation, it is best to use an MUN5311, which has 10-kΩ internal resistors instead of 22 kΩ. You can use the same bidirectional circuit in Figure 3 for the clock signal, to cover all the I2C modes of operation.