Bi-directional level shifter.
When you have to connect a 5V device with a 3.3V device over a SPI interface you have to guarantee the right levels to both sides. Take as an example the Arduino UNO (5V device) and a Lora Ra-02 SX1278 Semtech device (3.3V device).
A level shifter can be used to do a voltage shift of the bi-directional signals of the I2C-bus (SDA and SCL).
This creates two groups on the I2C-bus, one group with the 5V and one group with a lower voltage. Once the level shifter is implemented, any combination of 3.3V and 5V components can be made and all within the I2C specifications.
Below is a list of possibilities:
Use two MOSFETs.
This is the approach most often used.
The Philips Applications Note AN97055 explains it.
The MOSFETs must be types that activate with a very low gate voltage, for example BSS138or TN2501.
The resistors are not part of the level shifter; they are the pull-up resistors required by the I2C bus. In this case they have to be on both sides of the level shifter.
Each MOSFET conducts if the signal rail on either side is pulled low. If the source side is pulled low, the gate becomes positive with respect to the source; if the drain side is pulled low, the body diode conducts, bringing the source voltage down until the gate-source voltage is high enough to make the transistor conductive. The gate is always connected to the lower of the two supply voltages.
A device that pulls a line down has to handle the current through both resistors (on the 3.3V side and on the 5V side). That’s why a higher value for the pull-up resistors is chosen, usually 10k.