Skip to content
Jackdough

What is an SPI PMOLED display and how does it work for embedded systems?

· · Jackdough

An SPI PMOLED display is a type of passive-matrix organic light-emitting diode screen that uses a Serial Peripheral Interface (SPI) for communication with microcontrollers or embedded processors. In simple terms, it’s a small, self-emissive display where each pixel generates its own light—no backlight needed—and the control signals are sent over a four-wire serial bus. For embedded systems, this means you get bright, high-contrast visuals with low pin count and moderate power draw, making it a practical choice for battery-powered devices like wearables, medical monitors, or industrial control panels. The SPI protocol handles data transfer efficiently, using a master-slave architecture where the embedded system (master) sends commands and pixel data to the display driver chip (slave) via three lines: MOSI (Master Out Slave In), SCK (Serial Clock), and a chip select (CS) line, plus an optional data/command (DC) pin. Unlike parallel interfaces, SPI reduces wiring complexity, which is critical for compact PCB layouts. The PMOLED part refers to the passive matrix structure: rows and columns of electrodes drive the organic layers, and each row is scanned sequentially. This contrasts with active-matrix OLEDs (AMOLEDs), which use a thin-film transistor backplane for each pixel. PMOLEDs are simpler to manufacture but have limitations in resolution and size—typically under 3 inches diagonally, with resolutions around 128x64 or 128x128 pixels. For example, common modules like the 0.96-inch 128x64 SPI PMOLED display draw about 20 mA at full brightness, compared to 50-100 mA for an equivalent TFT LCD with backlight. The trade-off is that PMOLEDs have a shorter lifespan for blue subpixels (around 10,000-15,000 hours) versus 50,000+ hours for red and green, but for many embedded applications, this is acceptable. The SPI interface also supports clock speeds up to 10 MHz, enabling fast refresh rates—typically 60-100 Hz—which is sufficient for static or slowly updating data like sensor readouts or menu systems. The display controller, often a chip like the SSD1306 or SH1106, handles the multiplexing and current regulation internally. The SSD1306, for instance, has a 128x64-bit SRAM buffer that maps directly to pixels, and you can write data via SPI in pages or columns. This architecture makes it easy to integrate with low-power microcontrollers like the STM32L0 series or ESP32, where you can use hardware SPI peripherals to offload CPU cycles. Power consumption scales with the number of illuminated pixels—a fully white screen might draw 30-40 mA, while a mostly black screen with just text uses 5-10 mA. This is because PMOLEDs only power the active rows and columns, so darker content reduces current draw. In contrast, LCDs always need backlight power regardless of content. For embedded systems, this means you can optimize battery life by designing UI themes with dark backgrounds. Another key detail: SPI PMOLED displays often operate at 3.3V logic levels, but many modules include onboard voltage converters to generate the 7-10V needed for the OLED panel itself. This is handled by a charge pump circuit inside the driver IC, so you don’t need external boost converters. The physical interface typically uses a 7-pin header: VCC, GND, SCK, MOSI, CS, DC, and RESET. The RESET pin is optional if you handle initialization via software, but it’s recommended for reliable startup. Some modules also include a separate pin for data/command selection, which is essential for distinguishing between control instructions and pixel data. The command set for the SSD1306 includes over 30 instructions for settings like contrast, display on/off, addressing mode, and scrolling. For example, you can set contrast from 0x00 to 0xFF, which adjusts the current drive to the OLED pixels—lower values reduce brightness and power consumption. The addressing modes (page, horizontal, vertical) determine how pixel data is mapped to the buffer. In page addressing mode, you write 8-bit columns sequentially within a 8-pixel tall page, which is common for text rendering. The SPI bus itself is full-duplex, but for display communication, it’s typically used in half-duplex mode—the master sends data, and the slave sends back status or no data. This is fine because display updates are one-way. The clock polarity and phase (CPOL and CPHA) are usually set to mode 0 or 3, depending on the driver IC. For the SSD1306, mode 0 (CPOL=0, CPHA=0) is standard, meaning data is sampled on the rising edge of SCK. The maximum SPI clock speed for the SSD1306 is 10 MHz, but with long wires or high capacitance, you might need to reduce it to 4-5 MHz for reliable operation. One practical consideration: the SPI bus is susceptible to noise in electrically noisy environments, like near motors or switching power supplies. Adding a 100 nF decoupling capacitor near the display module’s VCC pin helps. Also, the CS line must be held low during the entire transaction—some microcontrollers have hardware CS control, but if you use a GPIO, ensure it toggles cleanly. The DC pin is critical: when DC is low, the next byte is interpreted as a command; when high, it’s data. This is a common source of bugs if you forget to set it correctly. For example, to initialize the display, you send a sequence of commands like 0xAE (display off), 0x20 (set memory addressing mode), 0x00 (horizontal mode), 0x21 (set column address range), 0x22 (set page address range), 0x8D (charge pump setting), 0x14 (enable charge pump), 0xA4 (display on resume), 0xA6 (normal display), and 0xAF (display on). Each command requires DC low, then the byte is sent via SPI. After that, you can send pixel data with DC high. The buffer size for a 128x64 display is 1024 bytes (128 columns * 64 rows / 8 bits per byte). This fits easily in most microcontrollers’ RAM. For embedded systems, the real advantage of SPI PMOLED displays is the combination of low pin count, fast update, and self-emissive technology. They are ideal for applications where size and weight matter—like a 0.96-inch module weighing just 3 grams. They also have a wide viewing angle (over 160 degrees) and high contrast ratio (10,000:1), which makes them readable in direct sunlight, though the absolute brightness is lower than LCDs with high-power backlights. Typical brightness is around 100-150 cd/m², compared to 300-500 cd/m² for a good TFT LCD. But in dim environments, they are more visible because of the deep blacks. The temperature range is also wider: -40°C to +85°C for storage and -20°C to +70°C for operation, which suits industrial applications. One downside: PMOLEDs have a shorter lifetime for blue pixels, which can cause color shift over time. For monochrome displays (white, yellow, or blue), this is less of an issue. If you need color, you’d look at an RGB PMOLED, but those are rare and more expensive. The SPI interface also supports daisy-chaining multiple displays, but this is uncommon in practice because each display needs its own CS line. The driver ICs like SSD1306 have a built-in oscillator that generates the necessary timing for the OLED panel, so you don’t need external clock sources. The frame rate is typically 60 Hz, but you can adjust it via commands. For graphics, you can use libraries like Adafruit_SSD1306 or U8g2, which abstract the SPI commands and provide functions for drawing text, lines, and bitmaps. These libraries handle the buffer management and command sequences, so you don’t need to manually set DC and CS every time. For example, in Arduino, you can initialize the display with display.begin(SSD1306_SWITCHCAPVCC, 0x3C) for I2C, but for SPI, you use display.begin(SSD1306_SWITCHCAPVCC, 0x3C, &SPI, DC, CS, RST). The library takes care of the rest. The SPI bus can also be shared with other peripherals, like SD cards or sensors, as long as each has a unique CS line. This reduces wiring further. However, you must ensure that the display’s SPI settings (clock speed, mode) are compatible with other devices. For instance, an SD card might need mode 0 or 3, but the SSD1306 uses mode 0. If you share the bus, you need to reconfigure the SPI registers between transactions, which adds overhead. Many embedded designers use a dedicated SPI bus for the display to avoid this. The power consumption of the SPI bus itself is negligible—about 1-2 mW at 10 MHz—compared to the display’s power draw. The real power savings come from the PMOLED technology. For a battery-powered system, you can also put the display in sleep mode via command 0xAE, which cuts power to the OLED panel but keeps the driver IC active. The current draw in sleep mode is typically 1-5 µA, which is excellent for low-power designs. Some displays also have a built-in DC-DC converter that can be disabled in sleep mode. Another feature: the display can be configured to invert colors, which is useful for highlighting. The contrast adjustment is linear, so you can fine-tune brightness. For embedded systems with limited processing power, like an 8-bit microcontroller, the SPI interface is fast enough to update the entire display in under 10 ms at 10 MHz. This is important for animations or fast-changing data. The driver IC also supports hardware scrolling, which can shift the display content without rewriting the buffer. This is useful for text tickers or status bars. The scrolling commands include horizontal, vertical, and diagonal scrolling, with configurable speed and step size. For example, you can scroll the entire display left at 2 frames per second using command 0x26. This offloads the microcontroller from having to update the buffer repeatedly. The display’s glass substrate is typically 0.7-1.1 mm thick, and the module includes a flexible PCB with a connector. The connector pitch is usually 0.1 inch (2.54 mm) for breadboard compatibility, or 0.05 inch (1.27 mm) for compact designs. The pinout is standardized for most 0.96-inch modules: pin 1 is GND, pin 2 is VCC (3.3V), pin 3 is SCK, pin 4 is MOSI, pin 5 is CS, pin 6 is DC, pin 7 is RESET. Some modules have a 8th pin for NC (not connected) or a second CS. Always check the datasheet because pin order can vary. For 3.3V systems, you can connect VCC directly. For 5V systems, you need a level shifter on the SPI lines, though some modules have built-in 5V tolerance. The SSD1306 datasheet specifies absolute maximum VCC of 3.6V, so 5V will damage it. The logic pins are also 3.3V, but they are 5V tolerant on some versions. To be safe, use a level shifter or a voltage divider. The display’s contrast is also temperature-dependent: the OLED efficiency drops at low temperatures, so you might need to increase contrast in cold environments. The driver IC has a temperature compensation feature that can adjust the contrast automatically if you enable it via command. This is configured by setting the temperature coefficient register. For embedded systems, this is a nice-to-have but not critical. The SPI PMOLED display is also susceptible to image retention if you display static content for long periods. This is a characteristic of OLED technology. To mitigate this, you can implement a screen saver that shifts the content slightly every few minutes, or turn off the display when not in use. The driver IC supports a display-on/off command that can be used for this. The lifetime of the display is typically rated at 10,000 hours for 50% brightness reduction, but this varies by manufacturer. For a 0.96-inch 128x64 module, the cost is around $5-10 in single quantities, making it affordable for prototyping. The SPI interface is also compatible with Raspberry Pi, BeagleBone, and other single-board computers. For Linux, you can use the spidev driver to send commands via ioctl calls. The driver IC’s initialization sequence is the same regardless of the host. One common mistake is not waiting for the display to power up after reset. The datasheet specifies a delay of 100 ms after power-on before sending commands. Also, the RESET pin must be held low for at least 10 µs. If you use the same reset line as the microcontroller, ensure the microcontroller’s reset doesn’t glitch the display. The SPI bus can also be used to read back the display’s status, but this is rarely needed. The SSD1306 has a readback command for the status register, but it’s not commonly implemented in libraries. For debugging, you can use a logic analyzer to check the SPI signals. The expected waveform: CS goes low, then SCK toggles while MOSI carries data. The DC pin should be set before the first SCK pulse. The data is MSB-first. The SPI mode 0 means SCK is low when idle, and data is sampled on the rising edge. If you use mode 3 (SCK high idle), the display won’t work. The maximum cable length for SPI is about 1 meter at 10 MHz, but for embedded systems, the cable is usually short. For longer distances, use lower clock speeds or differential signaling. The display’s driver IC also has a built-in charge pump that generates the negative voltage for the OLED cathode. This can cause audible noise if the switching frequency is in the audible range (20-20 kHz). The SSD1306’s charge pump operates at 8 MHz, so it’s inaudible. But some cheaper clones might use lower frequencies. The display’s response time is under 10 µs, which is much faster than LCDs. This makes it suitable for high-speed data visualization. The viewing angle is almost 180 degrees, so it’s readable from any angle. The display’s weight is about 3 grams for a 0.96-inch module, which is important for drone or wearable applications. The SPI interface also allows for partial updates: you can update only a portion of the display by setting the column and page address range. This reduces SPI traffic and power consumption. For example, if you only need to update a 16x16 pixel icon, you can set the column range to 32-47 and page range to 2-3, then send 32 bytes of data. This is more efficient than rewriting the entire buffer. The driver IC supports this via the 0x21 and 0x22 commands. The address range is inclusive, so you specify start and end addresses. For a 128x64 display, columns are 0-127, and pages are 0-7. Each page is 8 pixels tall. So if you want to update the top-left 8x8 pixel area, you set column start=0, column end=7, page start=0, page end=0, then send 8 bytes. The data is sent in column-major order within each page. This is efficient for text rendering because you can update individual characters. The SPI bus also supports DMA (Direct Memory Access) on many microcontrollers, which can transfer data to the display without CPU intervention. This frees up the CPU for other tasks. For example, on an STM32, you can configure the SPI DMA to send a buffer of 1024 bytes to the display, and the CPU can go to sleep or process other data. The DMA transfer is triggered by the SPI TX request. The speed is limited by the SPI clock, but you can achieve 10 MB/s with DMA. This is useful for video-like animations, though the PMOLED’s refresh rate limits it to 60 Hz. The display’s driver IC also has a built-in RAM that can be accessed via SPI. The RAM is 128x64 bits, organized as 8 pages of 128 bytes. You can write to it in any order, but the addressing mode determines how the data is mapped. In page addressing mode, the column address increments automatically after each byte, and wraps to the next page after column 127. In horizontal addressing mode, the column increments, then the page increments after column 127. In vertical addressing mode, the page increments, then the column increments after page 7. These modes are useful for different graphics algorithms. For example, if you are drawing a bitmap that is stored in row-major order, horizontal addressing mode is efficient. If you are drawing a font that is stored in column-major order, vertical addressing mode is better. The default mode is page addressing, which is simple but not optimal for all cases. The driver IC also supports a “charge pump” setting that can be adjusted for different OLED panel voltages. The default is 0x14 for 7.5V, but you can set it to 0x10 for 6.5V or 0x18 for 8.5V. This is useful if you want to reduce power consumption at the cost of brightness. The contrast setting is separate from the charge pump. The contrast range is 0-255, and the default is 0x7F (127). The contrast affects the current drive to the OLED pixels. The relationship is linear: doubling the contrast value doubles the current, but the brightness increase is sublinear due to OLED efficiency. The power consumption also scales with contrast. For a typical 0.96-inch display, the power consumption at full contrast is about 30-40 mA for a white screen. At half contrast, it’s about 15-20 mA. This is a good way to save power. The display also has a “display start line” register that can be used to shift the display vertically. This is useful for scrolling without rewriting the buffer. The start line register is set via command 0x40. For example, if you set it to 32, the display will show rows 32-63 and then wrap to rows 0-31. This is a hardware scrolling feature. The driver IC also supports a “segment remap” command that can flip the display horizontally. This is useful if you mount the display upside down. The command is 0xA0 for normal mapping and 0xA1 for remapped. Similarly, the COM output scan direction can be reversed via command 0xC0 or 0xC8. This allows you to adjust the display orientation without changing the physical mounting.

Ready when you are

Turn weekend loaves into a legal, paying home bakery.

Join 11,400+ home bakers who got the business blueprint — cottage food laws, costing templates, recipes that scale — delivered free to your inbox over five short lessons.

Get My Free Profit Roadmap

No credit card required · 11,400+ bakers enrolled · Unsubscribe in one click