SSD1306 via Hardware SPI

I have my SSD1306 running fine via Software SPI initializing it like this:

#define OLED_MOSI   D0
#define OLED_CLK    D1
#define OLED_DC     D2
#define OLED_CS     D3
#define OLED_RESET  D4

But I am struggling to figure out how to wire up the display to hardware SPI and then initialize it.

The docs say about hardware SPI pins:

A2: SS (Slave Select)
A3: SCK (Serial Clock)
A4: MISO (Master In Slave Out)
A5: MOSI (Master Out Slave In)

The example I have for initializing the display as hardware SPI suggests this:

// use hardware SPI
#define OLED_DC     D3
#define OLED_CS     D4
#define OLED_RESET  D5
Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);

Does any of you guys know how to set it up?

I took a look and it should probably be:

SSD1306 --> Core
CS     ---> SS (A2)
CLK    ---> SCK (A3)
MOSI    --> MOSI (A5)
DC      --> Any pin you defined (eg. D3)
CS     ---> A2 (can be changed but we use the default chip select pin)
Reset  ---> Any pin you defined (eg. D5)

Let us know how it goes :wink:


Thx Kenneth!

I’ll give it a go. :smiley:

Just to make things even clearer than @kennethlimcp has already done:

The DC or D/C pin is needed by some devices to distinguish between commands or data for the controler.
Since SPI only pushes out anonymous bitsreams the user code has to “tell” the controler if this will be a command (e.g. D/C LOW) or a data (e.g. D/C HIGH) bitstream. And so D/C is not actually an SPI pin, but this gives you freedom which Core pin to choose.

Similarly the Reset pin can be chosen freely or even pulled high or left open if it’s pulled high on the board already, if you don’t need to reset the device via user code.

The CS pin is a kind of hybrid here. While SPI brings its own version of it (SS) you might want to use any other free digital pin if you’d like to attach multiple SPI devices, selecting each individual one via its own designated chip select pin.
For each SPI stream only one CS should be active to ensure that only the meant device listens to it.
And since only user code “knows” who is meant at a given time you have to decide which Core pin to use as CS for which device.


Ok. I just tried it without any luck.
I initialize like this:

#define OLED_DC     A1
#define OLED_CS     A2
#define OLED_RESET  A4
Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);

I have connected it like this:

SSD1306 --> Core
DC     ---> A1
CS     ---> A2
CLK   ---> A3
Reset ---> A4
MOSI ---> A5

I going to look more into it in a few days to figure it out.

I think A4 might not work as it’s a SPI oin on the core. Try maybe a Digital pin :wink:

1 Like

The reason why A4 won’t do is that this is already a dedicated SPI pin (MISO) - as @kennethlimcp already stated :wink:
Look here


Heureka! — it’s alive. :smiley:

Moved Reset to D0 as initialized accordingly and it worked.
I have a question more though. The Adafruit_1306 lib has the frequency for HW SPI set at 9mhz:

SPI.setClockDivider(SPI_CLOCK_DIV8);	// 72MHz / 8 = 9Mhz

What is the reason of this limit? Is the SSD1306 not able to run at a higher frequency?

That might be possible but checking the data sheet will give us the best answer. :wink:

Or maybe the arduino they interfaced to cannot handle too high a freq and 72Mhz seems like a stm32f103 thing on the core and divided to get the same freq used in the original library.

You can try bumping it up and see how it goes :wink:

Tried it, but makes not difference.

I tried measuring the FPS, and it doesn’t seem like its the SPI that limits a good FPS.

If I draw 1 frame per loop then before wifi is connected I get a good 210FPS. After WIFI connects I get 100FPS. If I draw 4 frames per loop it jumps to 170FPS after WIFI connects.

And all I need really is 60FPS. Im gonna measure I2C now. If that gives me 60FPS I might as well use that to have more pins available. :smiley: