I am attempting to connect an 8051-compatible microcontroller to an accelerometer using the I2C bus. Both devices operate at the same voltage, 3.3v. However, I am failing to understand something: won't a direct short be created when the microcontroller asserts a logic HIGH on either SCL or SDA and the slave device attempts to hold the line at logic LOW? I don't understand how to avoid this...

How can I make the MCU float the lines instead of placing a logic HIGH on them? I realize I can change the state of the lines to "input" instead of output, but is that safe to avoid a short circuit?

As I see it, the following scenario could happen:

If the MCU switched from 'input' mode to 'output' mode, couldn't the pin be in the HIGH state, even if you set the pin to LOW, then set input mode to 'output'? Won't the input voltage change the state back to HIGH due to the pin being in 'input' mode, before it has a chance to switch to output mode? Then for a few uS you would be outputting a logic high, before the MCU executed the next instruction to turn the pin to LOW.


2 Answers 2


Switching to input in order to float the line is completely acceptable. Microchip's PIC MCU's have done it this way for years. Only recently have they introduced devices that can be configured as open-drain.

Your MCU should have a separate control for input/output, and for the value of the output bit. The customary way to operate this is to set the output data to zero, and switch the direction bit (the one that determines input or output) instead. That is, make it an output to assert a zero, and make it an input to assert (suggest, really) a 1. Setting the bit to input also allows reading it; this and the "high" state are interchangeable.

  • \$\begingroup\$ That makes sense. But in this example, it seems like there would be a short circuit for a very short time: 1) the pin is in INPUT mode. 2) A logic HIGH is detected due to the pullup resistors. 3) Set the value to LOW in code. 4) Switch to OUTPUT mode. Won't it simply re-detect the logic high value between steps 3 and 4, and re-assert the pin HIGH, causing a short? \$\endgroup\$ Apr 23, 2014 at 3:31
  • \$\begingroup\$ No. Having the input pin reading a high signal does not cause anything in the output driver circuit to assume a high state. When the pin is changed to output, it does so without driving any current out to the pin. In fact, it sinks current, which is how it goes low. \$\endgroup\$
    – gbarry
    Apr 23, 2014 at 6:55

The last sentence in the O.P. should be:

Then for a few uS you would set the MCU output to high-Z be outputting a logic high, before the MCU executed the next instruction to turn the pin to LOW.

I2C is an open drain bus with pull up resistors. Master and slaves can only pull the lines low. Neither master nor slave drive the I2C lines (SDA and SCL) up. In other words, master and slave can only sink current from the I2C lines, but they can's source current. Master and slaves can only put outputs to high-Z state, and the resistors can pull the lines up.

The values of pull-up resistors are somewhere between 1.5 kΩ and 10 kΩ depending on the logic voltage levels, bus speed, bus capacitance. When the bus is driven low, the resistors limit the current, so there is no hard short.

enter image description here(source)

This is detailed in the I2C specification (UM10204). Anyone working with the I2C bus should at least skim through it.

  • \$\begingroup\$ I understand, but this MCU does not seem to have any way to set TRISTATE mode. There is no register called TRIS as in PIC controllers. All I have is a P0 (port 0) register and P0DIR (port direction). Ideas? \$\endgroup\$ Apr 23, 2014 at 3:35
  • \$\begingroup\$ @RyanGriggs Make the I/O pin an input, connect a pull-up resisror to it, see what happens. \$\endgroup\$ Apr 23, 2014 at 3:38
  • \$\begingroup\$ Nick Alexeev already pointed this out: Using your PoDIR register you can set a pin as "input" which basically makes it tristate. If you're sending on SDA, you will make your pin an output and drive it high or low; if you're expecting data, you will set the pin as input (which will make the line float and be pulled up by the external pull-ups). Now the external device (I2C slave) is able to drive the line and you are able to read the value on your pin \$\endgroup\$
    – Tom L.
    Apr 23, 2014 at 5:33
  • 1
    \$\begingroup\$ If you were to investigate how a PIC changes a pin to input, you would find that it uses the TRIS register. What this means for you is that in the case of the PIC, there's no difference between "tri-stating" and switching to "input". So, switching your MCU pin to input is perfectly fine. \$\endgroup\$
    – gbarry
    Apr 23, 2014 at 7:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.