SSD1306 128x64 SPI OLED Display

From Embedded Workshop
Jump to navigation Jump to search

Hardware

These displays use the SSD1306 controller: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf

The following is from the SSD1306.pfd document:

8.1.3 MCU Serial Interface (4-wire SPI)
The 4-wire serial interface consists of serial clock: SCLK, serial data: SDIN (MOSI), D/C#, CS#.
In 4-wire SPI mode, D0 is used for SCLK signal, D1 is used for MOSI. For the unused data pins, D2 should be left open.
The pins from D3 to D7, E and R/W# (WR#)# can be connected to an external ground.

Table 8-4 : Control pins of 4-wire Serial interface
Function        E(RD#)	  R/W#(WR#)   CS#    D/C#   D0
Write command  Tie LOW   Tie LOW      L      L      ↑
Write data     Tie LOW	  Tie LOW      L      H      ↑
Note
(1) H stands for HIGH signal
(2) L stands for LOW signal

RES#   This pin is reset signal input. When the pin is pulled LOW, initialization of the chip is executed.
       Keep this pin HIGH (i.e. connect to VDD) during normal operation.
D/C#   This is Data/Command control pin. When LOW, it indicates a command to be sent to the command register. 
       When HIGH, it indicates data.
       In I2C mode, this pin acts as SA0 for slave address selection.
       When 3-wire serial interface is selected, this pin must be tied low (connected to VSS).
CS#  This pin is the chip select input. (active LOW).

NOTE: This device uses SPI mode 0.
Note the diagram on the back of the SSD1306 module.  It documents resistor population for different
processor interfaces.  This one came configured perfectly for "4SPI" connection.

For this exercise, I used the SPI (4 wire) Hardware interface, with reset (RES#) added. (I don't believe MISO is used.)
According to the datasheet, the maximum SPI clock frequency is 10MHz.

Connections

Board	       MOSI    MISO	SCK	RES#	CS#	D/C#
Arduino UNO	11	12	13	8	7	6

Arduino Uno - Hardware SPI - Screen Captures

Before each frame, the Arduino sends six command bytes before sending the frame data


Capture showing the time it takes to send a complete frame - 2.79ms


With a single byte SPI buffer (no FIFO), and not using DMA, it takes time to load each byte for transfer.
If DMA were available and implemented, the frame time could be reduced considerably.
The sending of a single byte takes 1.0us using an 8MHz SPI clock.
We see the Arduino is sending bytes about every 2.69us.


This capture shows we are using an 8MHz clock. The maximum clock for this part is 10MHz, so this is about as fast as the Arduino UNO can send SPI data.

Software

For Arduino, the Adafruit SSD1306 library, version 2.4.2, works very well.
For testing, I used libraries\Adafruit_SSD1306\examples\ssd1306_128x64_spi.ino example.
For hardware SPI, need to follow the directions at the top of the file, commenting out the software SPI defines
and constructor (default case), and uncomment the hardware SPI defines and constructor.

It should look something like the following:

/*
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
*/

/* Comment out above, uncomment this block to use hardware SPI */
#define OLED_DC     6
#define OLED_CS     7
#define OLED_RESET  8
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  &SPI, OLED_DC, OLED_RESET, OLED_CS);

Additional Resources

https://learn.adafruit.com/monochrome-oled-breakouts/wiring-128x32-spi-oled-display