SSD1306 (6 pin/SPI) with STM32F103C8T6

Hello, all!

I have a question about wiring the SSD1306 (6 pin/SPI) display to STM32F103C8T6 (the blue pill). Can you share with me some kind of wiring diagram (where all the nets are connected, which are the coresponding pins?), because I didn't find any information about the connection between these two devices. I've tried to run some basic graphics examples using the Arduino Uno board and it works perfect, but now I want to run the same display with STM32F103C8T6. What about the code? Can I use the same libraries with small modification or I need another one? (I'm talking about Adafruit_SSD1306 and Adafruit-GFX-Library). I have installed the blue pill properly and also able to run a simple sketch like - blink.

STM32F103C8T6:

SSD1306 Display:

Thank you in advance, guys!

Regards!

It is a complete mystery how any SPI device can operate (reliably) without a /CS pin.

If you can show it working on a Uno, then I will show you how to work it on a BluePill.

Are you using the STM32 MapleCore (from Roger Clark) or the ST Core from STMicrolectronics ?

David.

In fact it's working perfect with the Arduino Uno, I'll show you the code which I get from Adafruit_SSD1306 library

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// If using software SPI (the 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(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

/* Uncomment this block to use hardware SPI
#define OLED_DC     6
#define OLED_CS     7
#define OLED_RESET  8
Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);
*/

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16 
#define LOGO16_GLCD_WIDTH  16 
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()   {                
  Serial.begin(9600);

  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC);
  // init done
  
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(2000);

  // Clear the buffer.
  display.clearDisplay();

  // draw a single pixel
  display.drawPixel(10, 10, WHITE);
  // Show the display buffer on the hardware.
  // NOTE: You _must_ call display after making any drawing commands
  // to make them visible on the display hardware!
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw many lines
  testdrawline();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw rectangles
  testdrawrect();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw multiple rectangles
  testfillrect();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw mulitple circles
  testdrawcircle();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw a white circle, 10 pixel radius
  display.fillCircle(display.width()/2, display.height()/2, 10, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  testdrawroundrect();
  delay(2000);
  display.clearDisplay();

  testfillroundrect();
  delay(2000);
  display.clearDisplay();

  testdrawtriangle();
  delay(2000);
  display.clearDisplay();
   
  testfilltriangle();
  delay(2000);
  display.clearDisplay();

  // draw the first ~12 characters in the font
  testdrawchar();
  display.display();
  delay(2000);
  display.clearDisplay();

  // draw scrolling text
  testscrolltext();
  delay(2000);
  display.clearDisplay();

  // text display tests
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Hello, world!");
  display.setTextColor(BLACK, WHITE); // 'inverted' text
  display.println(3.141592);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.print("0x"); display.println(0xDEADBEEF, HEX);
  display.display();
  delay(2000);
  display.clearDisplay();

  // miniature bitmap display
  display.drawBitmap(30, 16,  logo16_glcd_bmp, 16, 16, 1);
  display.display();

  // invert the display
  display.invertDisplay(true);
  delay(1000); 
  display.invertDisplay(false);
  delay(1000); 
  display.clearDisplay();

  // draw a bitmap icon and 'animate' movement
  testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
}


void loop() {
  
}


void testdrawbitmap(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  uint8_t icons[NUMFLAKES][3];
 
  // initialize
  for (uint8_t f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS] = random(display.width());
    icons[f][YPOS] = 0;
    icons[f][DELTAY] = random(5) + 1;
    
    Serial.print("x: ");
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(" y: ");
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(" dy: ");
    Serial.println(icons[f][DELTAY], DEC);
  }

  while (1) {
    // draw each icon
    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
    }
    display.display();
    delay(200);
    
    // then erase it + move it
    for (uint8_t f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK);
      // move it
      icons[f][YPOS] += icons[f][DELTAY];
      // if its gone, reinit
      if (icons[f][YPOS] > display.height()) {
        icons[f][XPOS] = random(display.width());
        icons[f][YPOS] = 0;
        icons[f][DELTAY] = random(5) + 1;
      }
    }
   }
}


void testdrawchar(void) {
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);

  for (uint8_t i=0; i < 168; i++) {
    if (i == '\n') continue;
    display.write(i);
    if ((i > 0) && (i % 21 == 0))
      display.println();
  }    
  display.display();
}

void testdrawcircle(void) {
  for (int16_t i=0; i<display.height(); i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
    display.display();
  }
}

void testscrolltext(void) {
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(10,0);
  display.clearDisplay();
  display.println("scroll");
  display.display();
 
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);    
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
}

I don't know about the cores... how can I see it? So what about the STM32F103C8T6? Do you have an idea how I can run that display on it?

Ok, you are using a standard example from the Adafruit library.

Please explain how you actually wired your 6 pins. Or post a photo of the wiring.

Regarding Cores. In the IDE->Tools->Board it will say either:

STM32 Boards (selected from submenu)
or
STM32 Boards (STM32duino.com)

David.

It's Generic STM32F103C series.

#define OLED_MOSI   9 //SDA -> D9(PB1)
#define OLED_CLK   10 //SCL -> D10(PB2)
#define OLED_DC    11 //DC -> D11(PB3)
#define OLED_CS    12 // Not connected
#define OLED_RESET 13 //RST -> D13(PB5)

GND -> to ground
VCC -> +5V

Here's the wiring setup, and there is no CS pin on the display itself...

I tried a BluePill with the ST Core. It compiled ok with Adafruit_SSD1306.h

I wired like this:

#define OLED_MOSI   PB15 //9
#define OLED_CLK    PB13 //10
#define OLED_DC     PA10 //11
#define OLED_CS     PB12 //12
#define OLED_RESET  PA9  //13

My display has got a CS pin. If I define OLED_CS as -1 or even PA8 (i.e. wrong pin), nothing happens.
If I hard-wire CS to GND, the sketch "works".

I am VERY sceptical about any device which does not have a CS pin.

David.

Edit. Oops. STM32F103C series. You must be using (STM32duino.com)

STM32 Boards (selected from submenu)
   Nucleo-64 series
   ...
   Generic STM32F103 series
   ...
STM32 Boards (STM32duino.com)
   Generic STM32F103C series
   Generic STM32F103R series
   Generic STM32F103T series
   Generic STM32F103V series
   ...

Anyway, the sketch should work fine on either core.

Hello, David! Unfortunately it doesn't work with your definition, but I've found the right pins.

// If using software SPI (the default case):
#define OLED_MOSI  PB7//9 //SDA -> D9(PB1)
#define OLED_CLK   PB8//10 //SCL -> D10(PB2)
#define OLED_DC    PA6//11 //DC -> D11(PB3)
#define OLED_CS    PB12//PB3//12 // Not connected
#define OLED_RESET PA7//13 //RST -> D13(PB5)

By the way, now I'm struggling with the I2C communication... Do you know the default I2C pins? And do I have to define again them?

I just gave you MY wiring. And confirmed that it works.

You can choose any set of pins for the Software constructor.
The important point is that you should be HONEST.

If you say that you have connected OLED_MOSI to PB7, does your wire actually go there?

I am not being funny. We all make mistakes. We have all had broken wires or bad solder joints.
You just have to be meticulous. I suggest making a schematic and a paper checklist. Then ticking off each connection after testing for end-points, breaks, shorts, ...

Please confirm that you are using STM32duino core.
The ST Core follows Arduino conventions fairly well for default I2C pins.
The STM32duino Core is a little different.

David.

p.s. the photo in #0 shows header pins that are NOT soldered. You must always solder header pins. Then use mating sockets e.g. female header or Dupont cables.