Skip to content
Doprava zdarma nad 690 Kč Doručení do 24 hodin od sklizně +420 222 741 880

How does an SPI OLED display work with microcontrollers?

Napsal(a) Z farmy ke stolu · Zelené Potraviny

An SPI OLED display works by using a serial peripheral interface (SPI) to communicate between a microcontroller and the display's driver chip, typically something like the SSD1306 or SH1107. The microcontroller sends pixel data, commands, and clock signals over a four-wire bus (or sometimes three-wire, depending on the configuration), and the OLED driver chip translates that into precise voltage levels across a grid of organic light-emitting diodes. If you’re building a project with a Raspberry Pi Pico, ESP32, or an Arduino Uno, you’re essentially offloading the heavy lifting of pixel management to the driver, while the SPI bus handles the data transfer at speeds that can hit 10 MHz or more. For a deeper dive into specific module specs, check out an SPI OLED display from a reliable supplier.

The core of the operation is the SPI protocol itself. Unlike I2C, which uses a shared bus with addressing, SPI is a full-duplex, master-slave architecture. The microcontroller acts as the master, and the OLED driver is the slave. You’ve got four lines: SCK (serial clock), MOSI (master out, slave in), MISO (master in, slave out), and CS (chip select). But in many OLED displays, the MISO line is often omitted because the display doesn’t need to send data back to the microcontroller at high speed—it’s a one-way street for pixel data. So you’re usually looking at a 3-wire SPI setup: SCK, MOSI, and CS, plus a DC (data/command) pin and a RESET pin. The DC pin tells the driver whether the incoming byte is a command or data, which is critical for initializing the display and drawing pixels.

Let’s break down the initialization sequence. When you power up the display, the microcontroller first toggles the RESET pin low for at least 3 microseconds, then high. This clears the driver’s internal state. Then, you send a series of commands over SPI. For example, with the SSD1306, you’d set the display off (command 0xAE), set the multiplex ratio (0xA8 followed by a value like 0x3F for 64 rows), set the display offset (0xD3 with 0x00), set the start line (0x40), and configure the charge pump (0x8D with 0x14 to enable it). The charge pump is a big deal—it generates the 7-8V needed to drive the OLED pixels from the microcontroller’s 3.3V or 5V logic. Without it, the display won’t light up. The entire init sequence for a 128x64 monochrome OLED takes about 30-40 bytes of data, and with SPI running at 4 MHz, that’s under 100 microseconds.

Once initialized, the display enters a “data mode” where every byte you send over SPI maps to a column of pixels. The SSD1306 organizes its frame buffer into 8 pages, each page being 8 pixels tall. A 128x64 display has 128 columns and 8 pages. To draw a pixel at column 50, page 3, you set the column address range (commands 0x21, 0x00, 0x7F) and the page address (0x22, 0x00, 0x07), then send the pixel data. Each bit in the byte corresponds to a pixel row within that page. Bit 0 is the bottom row, bit 7 is the top. So if you want to light up the top pixel of column 50, page 3, you send 0x80. This bit-level control is why SPI OLEDs are so fast—you can update the entire display in about 2 milliseconds at 4 MHz, versus 10-20 ms for an I2C OLED at 400 kHz.

Now, let’s talk about the physical layer. The OLED panel itself is a matrix of organic compounds sandwiched between two electrodes. Each pixel is a tiny LED that emits light when current passes through it. The driver chip uses a constant-current source to control brightness. The SSD1306, for instance, has a built-in DC-DC converter that generates the high voltage from the logic supply. The current per segment (pixel) is typically around 100-200 microamps, and the total current draw for a full-white 128x64 display is about 20-30 mA at 3.3V. That’s efficient compared to an LCD with a backlight, which can pull 100 mA or more. But the trade-off is lifespan—OLED pixels degrade over time, especially blue ones, and the typical half-life is around 10,000-20,000 hours of continuous use at full brightness.

From a microcontroller perspective, you need to manage the SPI peripheral’s registers. On an STM32, you’d configure the SPI1 or SPI2 block with a baud rate prescaler, set the data frame to 8 bits, and enable software slave management. The code typically looks like this: set the CS pin low, send a command byte by pulling the DC pin low, then write the byte to the SPI data register. Wait for the transmit complete flag, then repeat for data bytes with DC high. On an Arduino, the SPI.transfer() function handles this, but you still need to manually control the CS and DC pins. The maximum SPI clock speed for the SSD1306 is 10 MHz, but many microcontrollers can’t hit that due to timing constraints. In practice, 4 MHz is a sweet spot—fast enough for smooth animations, slow enough to avoid signal integrity issues on breadboards.

One common pitfall is the voltage level mismatch. Most OLED displays are 3.3V devices, but many microcontrollers, like the Arduino Uno, run at 5V logic. If you connect 5V to the SPI pins, you risk damaging the driver chip. You need a level shifter or a voltage divider on the MOSI, SCK, and CS lines. The DC and RESET pins also need level shifting. Alternatively, use a 3.3V microcontroller like the ESP32 or a Raspberry Pi Pico. The Pico’s RP2040 has two SPI peripherals, each with dedicated pins, and you can run them at up to 25 MHz with the right clock divider. But the OLED’s internal timing limits you to 10 MHz, so you’re bottlenecked by the display, not the MCU.

Data throughput is where SPI shines. For a 128x64 monochrome display, the frame buffer is 1024 bytes (128 columns * 8 pages). At 4 MHz, transferring 1024 bytes takes about 2 milliseconds. But you also need to send the column and page address commands, which adds another 10-20 bytes. So a full frame update is around 2.1 ms. That’s 476 frames per second, theoretically. In practice, you’re limited by the microcontroller’s processing time and the display’s internal refresh rate, which is typically 60-100 Hz for the SSD1306. So you can easily do 60 fps with SPI, which is smooth for animations, scrolling text, or even simple games. Compare that to I2C, where the same 1024 bytes at 400 kHz takes about 25 ms, giving you only 40 fps max.

But there’s a catch: SPI uses more pins. A 4-wire SPI setup needs 4 pins (SCK, MOSI, CS, DC) plus RESET, for a total of 5. That’s still fewer than a parallel interface, which can use 8-16 data lines plus control lines. On a microcontroller with limited GPIO, like the ATtiny85, you might be forced to use I2C or a software SPI implementation. Software SPI bit-bangs the protocol on any pins, but it’s slower and less reliable. For example, bit-banging SPI on an Arduino at 16 MHz gets you about 500 kHz effective clock speed, which is fine for static displays but chokes on animations. Hardware SPI is always preferred.

Now, let’s get into the nitty-gritty of the driver chip’s internal architecture. The SSD1306 has a 128x64-bit SRAM frame buffer. That’s 1024 bytes of RAM, which is a lot for a small driver chip. The buffer is organized as a 2D array: 128 columns by 8 pages. Each page is 8 bits tall. When you write data, you’re filling this buffer. The driver then continuously scans the buffer and outputs the pixel states to the OLED panel. The scan is done row-by-row, using a technique called “pulse width modulation” (PWM) to control brightness. The SSD1306 has a “segment current” register that sets the current for each column, and a “contrast” register that adjusts the overall brightness. You can control these via SPI commands, giving you dimming control without changing the pixel data.

The SH1107 is another common driver, used in 128x64 and 128x128 displays. It’s similar to the SSD1306 but with a different memory map. The SH1107 has a 132x64-bit buffer, but only 128 columns are visible. The extra columns are for offset. The initialization sequence is slightly different, but the SPI protocol is the same. The key difference is that the SH1107 supports higher contrast and a wider operating voltage range (1.65V to 3.5V). Some displays use the SH1107 for better longevity, but the SSD1306 is more popular in hobbyist projects due to its extensive library support.

From a software perspective, you’re not writing raw SPI commands for every project. Libraries like Adafruit_SSD1306 or u8g2 handle the low-level SPI communication. The Adafruit library, for example, uses the SPI class in Arduino to send data. It initializes the display with a predefined sequence, then provides functions like display.drawPixel() and display.display(). The display() function is the bottleneck—it transfers the entire frame buffer over SPI. If you’re only updating a small portion of the screen, you can optimize by sending only the changed bytes. But the library doesn’t do that by default. You’d need to implement a dirty-rectangle algorithm, which is complex but can cut update times by 50% or more.

Power consumption is another angle. The OLED’s efficiency is tied to the number of lit pixels. A full-white screen draws about 20 mA, while a mostly black screen with a few pixels lit draws under 5 mA. The microcontroller’s SPI peripheral also consumes power—typically 1-2 mA for the SPI block at 4 MHz. So the total system draw for a simple clock display is around 10-15 mA. That’s low enough for battery-powered projects, like a wearable or a remote sensor display. But if you’re running animations, the constant SPI transfers keep the MCU awake, which drains more power. Using sleep modes and waking only to update the display can extend battery life significantly.

Signal integrity is critical for reliable SPI communication. Long wires, breadboard jumpers, or high-speed clocks can cause reflections and data corruption. The SPI lines should be kept under 10 cm if possible, and you should add a 100 nF capacitor between VCC and GND on the display module. The CS line is especially important—it must be pulled high when not in use, or the display might misinterpret data. Most OLED modules have a built-in pull-up resistor on CS, but you should verify with a multimeter. If you’re using a 3.3V display with a 5V MCU, the level shifter introduces propagation delay, which can limit the SPI clock speed to 2 MHz or less. In that case, drop the clock to 1 MHz to avoid errors.

Temperature affects OLED performance. The organic compounds have a temperature coefficient, and the brightness drops as the temperature rises. At 25°C, the typical brightness is 100 cd/m². At 60°C, it drops to about 80 cd/m². The driver chip’s charge pump also becomes less efficient at high temperatures, increasing power consumption. If you’re using the display outdoors in direct sunlight, you’ll need a higher contrast setting, which consumes more current. Some displays have a temperature compensation feature, but it’s not common in the SSD1306. You’d need to adjust the contrast register manually based on a temperature sensor reading.

Now, let’s talk about refresh rates and persistence of vision. The SSD1306’s internal frame rate is set by the “display clock divide ratio” and “oscillator frequency” registers. The default is a divide ratio of 0x80, which gives a frame rate of about 60 Hz. You can increase it to 100 Hz by setting the ratio to 0x00, but that increases power consumption. The human eye can’t perceive flicker above 60 Hz, so 60 Hz is fine for most applications. But if you’re using the display for a camera viewfinder or a video stream, you’ll want 100 Hz to reduce motion blur. The SPI bus can handle the data rate, but the microcontroller might struggle to generate frames at 100 fps if it’s doing other tasks.

One practical tip: when you’re debugging SPI communication, use a logic analyzer. The Saleae Logic 8 or a cheap clone can capture the SCK, MOSI, and CS lines. You’ll see the command bytes and data bytes in real time. Look for the CS line going low, followed by the SCK pulses. If the data is garbled, check the clock polarity and phase. The SSD1306 expects SPI mode 0 (CPOL=0, CPHA=0), which means the clock idles low and data is sampled on the rising edge. If your microcontroller defaults to mode 3, the display won’t respond. You can set the mode in the SPI configuration registers.

Finally, consider the physical mounting. SPI OLED displays come in various sizes: 0.96-inch (128x64), 1.3-inch (128x64), and 2.42-inch (128x64). The 0.96-inch is the most common, with a pixel pitch of about 0.15 mm. The viewing angle is 160 degrees, which is typical for OLEDs. The module usually has a 4-pin or 7-pin header. The 7-pin version includes the MISO line, which is rarely used but can be handy for reading the display’s status register. If you’re soldering the module, use a low-temperature iron (300°C) to avoid damaging the flex cable. The glass substrate is fragile, so handle it by the edges.

In summary, the SPI OLED display works by leveraging the high-speed SPI bus to transfer pixel data to a dedicated driver chip, which then manages the OLED panel’s voltage and current. The microcontroller’s role is to initialize the driver, send commands, and stream frame buffer data. The combination of hardware SPI, efficient driver chips, and low-power OLED technology makes this a go-to choice for embedded displays. The key parameters—clock speed, frame buffer size, and power consumption—are all optimized for real-time performance. If you’re choosing between SPI and I2C, go with SPI for speed, but be prepared for more pins and careful signal routing.