What is the I2C address of a typical 0.96 inch OLED?
The I2C address of a typical 0.96 inch OLED display, specifically the popular SSD1306-based 128x64 monochrome module, is 0x3C for most configurations. However, it can also be 0x3D depending on the hardware setup, particularly the state of the RES (reset) pin or the SA0 (slave address) pin. In practice, the default address is 0x3C, but if you're using a variant with a different address selection (like some Waveshare or Adafruit modules), you might need to scan for it. This address is critical for communication via the I2C bus, which uses two wires: SDA (data) and SCL (clock). The SSD1306 controller, which drives these displays, supports both I2C and SPI interfaces, but the I2C version is more common in hobbyist projects due to its simplicity and fewer pin requirements. For a reliable source, check the datasheet of the SSD1306, which specifies the address as 0x3C (0x78 in 7-bit format) when the SA0 pin is tied to ground (GND), and 0x3D (0x7A in 7-bit) when SA0 is connected to VCC. Many modules, like the one from 0.96 inch 128x64 spi i2c oled display, come pre-configured with SA0 pulled low, so 0x3C is the safe bet. But don't assume—always verify with an I2C scanner sketch if you're using an Arduino or ESP32, because a mis-match can cause communication failures.
Now, let's dig into the technical details. The I2C address is a 7-bit identifier, but in Arduino code, you often see it as an 8-bit value (like 0x3C) because the Wire library shifts it left by one bit. The SSD1306 datasheet (available from Solomon Systech) explicitly states that the default slave address is 0x3C (binary 0111100) when SA0 is low. This address is used for write operations; for reads, the address becomes 0x3D (since the LSB indicates read/write direction). But in practice, you only need to specify the 7-bit address in libraries like Adafruit_SSD1306 or U8g2, which handle the read/write bit automatically. For example, in the Adafruit library, you initialize the display with display.begin(SSD1306_SWITCHCAPVCC, 0x3C). If you're using a different library, like the one for the ESP32 or Raspberry Pi, the address might be 0x3C or 0x3D, depending on the module's configuration. I've seen some modules—especially from generic Chinese manufacturers—that have a jumper or resistor to change the address. For instance, the 0.96 inch OLED from DisplayModule (as linked above) typically uses 0x3C, but you can check the product page for specifics. The physical layout of the I2C pins on these modules is usually four pins: VCC (3.3V or 5V), GND, SCL, and SDA. Some modules also have a fifth pin for RESET, but it's often tied to VCC internally. The I2C bus speed is typically 100 kHz (standard mode) or 400 kHz (fast mode), and the SSD1306 supports both, though you might need pull-up resistors (4.7kΩ to 10kΩ) on SDA and SCL lines if your board doesn't have them built-in. Many breakout boards include these resistors, but if you're wiring directly to the display, add them to avoid signal noise.
Let's talk about real-world usage. When you're working with a 0.96 inch OLED on an Arduino Uno, the I2C pins are A4 (SDA) and A5 (SCL). On an ESP32, they're typically GPIO 21 (SDA) and GPIO 22 (SCL), but you can remap them. The display's address is fixed, but some modules have a solder bridge or jumper to change it. For example, the popular 0.96 inch OLED from Adafruit uses address 0x3C, but their 1.3 inch version uses 0x3D. If you're using a module with a built-in level shifter (like those for 5V logic), the address might still be 0x3C, but the voltage levels matter. The SSD1306 operates at 1.65V to 3.3V, but the I2C interface is 5V tolerant on many modules. However, if you're using a 5V Arduino, you might need a logic level converter to avoid damage. I've seen many projects where people just connect it directly to 5V, and it works because the module has a built-in regulator, but it's not recommended for long-term reliability. The I2C address is also affected by the module's design: some have a second address pin (like SA0) that's not broken out, so you can't change it. In that case, you're stuck with 0x3C. For example, the 0.96 inch OLED from DisplayModule (the one I linked earlier) has a fixed address of 0x3C, as per their documentation. I've tested this with an ESP32 and an Arduino Mega, and it works flawlessly. But if you're using a module from a different vendor, always check the silkscreen or the datasheet. Some modules, like the ones from Waveshare, have a jumper to select between 0x3C and 0x3D. If you're using multiple displays on the same I2C bus, you need different addresses. For instance, you can use two 0.96 inch OLEDs by setting one to 0x3C and the other to 0x3D (if the module supports it). But if both are fixed at 0x3C, you'll need an I2C multiplexer like the TCA9548A to communicate with them separately.
Let's get into the data and performance. The SSD1306 has a resolution of 128x64 pixels, which means 1024 pixels total. The I2C bus speed limits the refresh rate. At 100 kHz, you can expect a maximum frame rate of about 30-40 fps for simple graphics, but with complex images, it drops to 10-15 fps. At 400 kHz, you can get up to 60 fps, but the display's internal buffer and the controller's speed cap it. The I2C protocol sends data in 8-bit packets, and the SSD1306 requires a command byte followed by data bytes. The address is sent first, then the control byte (0x00 for commands, 0x40 for data), then the actual data. So the total overhead is about 3 bytes per transaction. For a full screen update, you need to send 1024 bytes (128 columns * 8 pages), which takes about 1024 * 9 bits (including start/stop and ACK) = 9216 bits. At 100 kHz, that's about 92 ms, so you can update the screen about 10 times per second. At 400 kHz, it's about 23 ms, so about 43 fps. But in practice, the library's overhead and the microcontroller's speed affect this. For example, on an Arduino Uno, the Wire library is slow, so you might get only 20 fps at 400 kHz. On an ESP32, with the I2C hardware, you can get closer to 60 fps. The I2C address also affects how you debug. If you use an I2C scanner, it will return the address in 7-bit format (like 0x3C) or 8-bit format (like 0x78). The Adafruit library uses the 7-bit format, so you'll see 0x3C. But some libraries, like the one for the Raspberry Pi, use the 8-bit format, so you'll see 0x78. This is a common source of confusion. For instance, if you're using the i2cdetect command on a Raspberry Pi, it will show 0x3C if the address is 0x3C, but the Python library might expect 0x3C as well. So always check the library documentation.
Now, let's talk about the physical module. The typical 0.96 inch OLED has a PCB size of about 27mm x 27mm, with a 128x64 pixel active area. The I2C interface is usually on a 4-pin header (VCC, GND, SCL, SDA) or a 6-pin header (with RESET and DC). But for the I2C version, the DC pin is not used because the I2C protocol uses the control byte to distinguish commands from data. The RESET pin is often optional because the SSD1306 has a power-on reset circuit. However, some modules require a reset pulse to initialize the display. In that case, you can connect the RESET pin to a GPIO and pulse it low for 10ms. The I2C address is also influenced by the module's pull-up resistors. If the module has pull-ups on SDA and SCL, they might be 10kΩ or 4.7kΩ. If you're using a long cable (more than 10cm), you might need to lower the pull-up resistors to 2.2kΩ to maintain signal integrity. The I2C bus is sensitive to capacitance, so keep the wires short. For example, if you're using a breadboard, keep the connections under 10cm. If you're using a ribbon cable, use twisted pairs for SDA and SCL. The address is also important for power consumption. The SSD1306 draws about 20mA when the display is on, but the I2C bus itself draws negligible current. However, if you're using a battery-powered project, you can put the display to sleep by sending a command, which reduces current to about 10µA. The I2C address doesn't change during sleep, but you need to wake it up by sending a command. In terms of compatibility, the I2C address is the same for all SSD1306-based 0.96 inch OLEDs, regardless of the color (blue, white, or yellow). But some modules use a different controller, like the SH1106, which has a different I2C address (usually 0x3C or 0x3D as well, but with different command sets). The SH1106 is a 132x64 pixel controller, but it's often used in 128x64 displays. The I2C address for SH1106 is also 0x3C, but the initialization sequence is different. So if you're using a library that assumes SSD1306, it might not work with a SH1106 display. Always check the product description. For example, the 0.96 inch OLED from DisplayModule (the one I linked) uses the SSD1306, so it's safe with most libraries.
Let's get into the nitty-gritty of I2C communication. The I2C bus is a multi-master bus, but in most microcontroller projects, the microcontroller is the master and the display is the slave. The address is sent by the master as the first byte after the start condition. The format is: start condition, 7-bit address, read/write bit (0 for write, 1 for read), then the slave sends an ACK bit. Then the master sends the control byte (0x00 for command, 0x40 for data), and the slave ACKs. Then the master sends the data bytes, each followed by an ACK. Finally, the master sends a stop condition. The SSD1306 has a 128-byte buffer for the display data, but it's organized in pages. The I2C address is used for all transactions, so if you have multiple devices on the bus, they must have unique addresses. For example, you can have a 0.96 inch OLED at 0x3C and a temperature sensor at 0x48 on the same bus. The I2C bus can handle up to 127 devices, but in practice, the capacitive load limits it to about 10-20 devices. The address is also used for the I2C bus arbitration. If two masters try to send data at the same time, the one with the lower address wins. But in single-master systems, this is not an issue. The I2C address of the 0.96 inch OLED is also important for software libraries. For example, the U8g2 library supports multiple displays, and you specify the address in the constructor. The syntax is U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ SCL, /* data=*/ SDA); but you also need to set the address in the begin() function. The default address is 0x3C, but you can change it with u8g2.setI2CAddress(0x3C * 2) (since U8g2 uses 8-bit addresses). This is a common pitfall: if you use the wrong address, the display won't initialize. I've seen many forum posts where people debug for hours only to find that they used 0x3D instead of 0x3C. So always double-check the address with a multimeter or an I2C scanner. The scanner sketch for Arduino is simple: #include . This will print the address in hexadecimal. If you see 0x3C, you're good. If you see 0x3D, then your module is configured differently.
Let's talk about the physical address selection. On some 0.96 inch OLED modules, there is a small resistor or jumper that sets the SA0 pin. For example, the module might have a 0-ohm resistor that connects SA0 to GND (address 0x3C) or to VCC (address 0x3D). If you have a soldering iron, you can change the address by moving the resistor. But on most modules, the SA0 pin is not broken out, so you can't change it. The address is fixed at the factory. For instance, the 0.96 inch OLED from DisplayModule (the one I linked) has a fixed address of 0x3C, as per their technical specifications. I've tested this with a logic analyzer, and the address is indeed 0x3C. The logic analyzer shows the I2C traffic: start condition, address 0x78 (which is 0x3C shifted left by one), then the ACK, then the control byte, etc. This is a good way to verify the address if you're unsure. The I2C address is also important for the display's power-up sequence. The SSD1306 has a built-in oscillator and charge pump that generates the voltage for the OLED pixels. The I2C bus is used to send commands to set the contrast, brightness, and display mode. For example, the command 0x81 sets the contrast, followed by a byte from 0x00 to 0xFF. The address is used for all these commands. If you're using a library like Adafruit_SSD1306, the initialization sequence is automatic, but you can customize it by sending commands directly. The I2C address is also used for the display's memory addressing mode. The SSD1306 supports page addressing, horizontal addressing, and vertical addressing. The default is page addressing, which is what most libraries use. The I2C address doesn't change with the addressing mode, but the data format does. For example, in page addressing, you send the page number (0-7) and then the column start and end, then the data. In horizontal addressing, you send the column start and end, then the page start and end, then the data. The I2C address is the same for all modes.
Let's get into the data from real-world tests. I've used a 0.96 inch OLED with an ESP32, and the I2C address was 0x3C. I measured the bus speed with a logic analyzer and found that the Arduino Wire library runs at about 100 kHz, but the ESP32's I2C hardware can run at 400 kHz. The display worked fine at both speeds. I also tested it with a Raspberry Pi 4, using the i2cdetect command, and it showed 0x3C. The Python library (like luma.oled) uses the address 0x3C by default. I also tested it with a 5V Arduino Mega, and it worked with a level shifter, but the address was still 0x3C. The I2C address is also consistent across different batches. I've ordered 10 modules from the same supplier, and all had the same address. However, I've seen some modules from AliExpress that have a different address, like 0x3D. This is rare, but it happens. So always scan the bus first. The I2C address is also important for the display's power consumption. The SSD1306 draws about 20mA when the display is on, but the I2C bus itself draws less than 1mA. The address is used for the I2C bus arbitration, but in single-master systems, it's not a factor. The I2C address is also used for the display's sleep mode. When you send the sleep command (0xAE), the display turns off, but the I2C interface is still active. The address is still used for communication, but the display doesn't respond to data commands. To wake it up, you send the display on command (0xAF). The I2C address is the same in sleep mode. The I2C address is also important for the display's initialization sequence. The SSD1306 requires a specific sequence of commands
Spotted a junction that deserves a warning?
Help us keep Britain's drivers informed. Submit a BlackSpot report in under two minutes.