esklar81 wrote:@MichaelN:
I'm a bit confused (Yeah, I know, there's a shocker. ) by: "I'm not familiar with Arduino, but if it is really I2C you should have no problem. Put pullup resistors on the SDA and SCL lines to 3.3V; the voltage levels will be valid for both 3.3V and 5V devices. Just make sure you don't set those pins on the Arduino as outputs and drive them high, as this could indeed damage the devices powered by 3.3V."
I can see how your approach would work if all one wanted to do with the Arduino is read from the I2C, as 3.3 V should be read as a 1 by a digital input (including an analog input port being operated as a digital input) of the Arduino. What I don't see is how you could write to the I2C (or output clock pulses, for that matter) without setting the Arduino pins to HIGH and, thereby, putting 5 V on them if one is using a 5 V Arduino. Care to enlighten me or point me at an explanation somewhere?
I2C is an open-drain bus, which means the devices don't actually drive the lines high (that is achieved with a pull-up resistor). Devices on the bus actively pull the lines low, but not high. As stated, pulling up the lines to 3.3V with a pull-up resistor will still be read as a valid logic “1” by devices powered with 5V.
Usually you will use an inbuilt I2C module in the microcontroller, which takes most of the hassle out of bit-bashing it. If you do need to bit-bash, you need to be very careful what you do with the registers controlling the pins. You first need to write a logic “0” to the pins used for I2C, and then DO NOT CHANGE IT. To write a logic “1” to a pin, you change the
Data Direction Register for that pin to make it an INPUT – the pull-up resistor will then pull the line high. To write a logic “0” to the pin, you change the Data Direction Register for that pin to make it an OUTPUT.
Hopefully that’s not too confusing…