2025-08-30 7:48 AM - last edited on 2025-09-03 8:23 AM by Saket_Om
Hi,
I'm trying to get a few lines of text displayed on an OLED screen using 4-wire SPI on an STM32H755 board, but I haven't succeeded yet.
I've looked into the sample code provided by the manufacturer (which is Arduino-based), but it hasn’t helped much so far.
Has anyone worked with this display or with the SSD1322 controller before?
I’m mainly looking for example code for the STM32 platform.
I’ll be uploading my current progress to my GitHub repo.
Thanks in advance!
2025-08-30 9:15 AM
Hi,
you set the SPI mode in Cube ? correct for ssd1322 ? did you check it with a scope ?
+
There are many libs, just look at another lib, copy it + adapt and try .
maybe try:
or this, for stm32F4 :
https://github.com/wjklimek1/SSD1322_OLED_library
2025-09-01 2:23 AM
Hi @AScha.3 ,
I've spent a long time trying to get it working, but I still can't achieve a clean and proper image. The display behaves as if it's 256x64, not 128x64 — only the left half shows readable content, while the right side is filled with garbage.
In fact, I had to manually offset text by 57 pixels from the left just to make it display properly. Without that, even the left part of the screen would appear distorted. :(
Here’s what I’ve tried so far:
I'm now wondering — maybe someone here has experience using an SSD1322 display with a physical resolution of 128x64, not 256x64?
Could the issue be caused by incorrect column address setup, remap configuration, or GDDRAM write pattern?
I’ll share my code if needed.
/* oled_ssd1322.c */
#include <string.h>
#include <stdio.h>
#include "oled_ssd1322.h"
#include "font6x8.h"
/* If your logo is large, get it as extern */
extern const uint8_t NHD_Logo[];
/* Inline control helpers */
static inline void CS_LOW (void) { HAL_GPIO_WritePin(SSD1322_CS_Port, SSD1322_CS_Pin, GPIO_PIN_RESET); }
static inline void CS_HIGH(void) { HAL_GPIO_WritePin(SSD1322_CS_Port, SSD1322_CS_Pin, GPIO_PIN_SET); }
static inline void DC_CMD (void) { HAL_GPIO_WritePin(SSD1322_DC_Port, SSD1322_DC_Pin, GPIO_PIN_RESET); }
static inline void DC_DAT (void) { HAL_GPIO_WritePin(SSD1322_DC_Port, SSD1322_DC_Pin, GPIO_PIN_SET); }
static inline void DEBUG_TOGGLE(void) { HAL_GPIO_TogglePin(DEBUG_PIN_PORT, DEBUG_PIN_PIN); }
static inline void DEBUG_HIGH(void) { HAL_GPIO_WritePin(DEBUG_PIN_PORT, DEBUG_PIN_PIN, GPIO_PIN_SET); }
static inline void DEBUG_LOW(void) { HAL_GPIO_WritePin(DEBUG_PIN_PORT, DEBUG_PIN_PIN, GPIO_PIN_RESET); }
/* Transmit with SPI (retry) */
static HAL_StatusTypeDef ssd1322_spi_tx(const uint8_t *data, uint16_t len)
{
HAL_StatusTypeDef ret;
for (int attempt = 0; attempt < SSD1322_SPI_RETRY_MAX; ++attempt) {
ret = HAL_SPI_Transmit(&hspi2, (uint8_t*)data, len, 100);
if (ret == HAL_OK) return HAL_OK;
HAL_Delay(1);
}
return ret;
}
void SSD1322_EntireDisplayOn(void) {
SSD1322_SendCommand(0xA5); // Entire display ON (all pixels white)
}
void SSD1322_EntireDisplayOff(void) {
SSD1322_SendCommand(0xA4); // Entire display OFF (normal)
}
/* Send command */
void SSD1322_SendCommand(uint8_t cmd)
{
DC_CMD();
CS_LOW();
ssd1322_spi_tx(&cmd, 1);
CS_HIGH();
}
/* Command + data */
void SSD1322_SendCommandWithData(uint8_t cmd, const uint8_t *data, uint16_t len)
{
DC_CMD();
CS_LOW();
ssd1322_spi_tx(&cmd, 1);
if (len) {
DC_DAT();
ssd1322_spi_tx(data, len);
}
CS_HIGH();
}
/* Reset pulse */
static void SSD1322_Reset(void)
{
HAL_GPIO_WritePin(SSD1322_RST_Port, SSD1322_RST_Pin, GPIO_PIN_RESET);
HAL_Delay(150);
HAL_GPIO_WritePin(SSD1322_RST_Port, SSD1322_RST_Pin, GPIO_PIN_SET);
HAL_Delay(150);
}
/* Column/row settings */
void SSD1322_SetColumn(uint8_t a, uint8_t b)
{
SSD1322_SendCommandWithData(0x15, (uint8_t[]){a, b}, 2);
}
void SSD1322_SetRow(uint8_t a, uint8_t b)
{
SSD1322_SendCommandWithData(0x75, (uint8_t[]){a, b}, 2);
}
/* Display ON/OFF */
void SSD1322_DisplayOnOff(bool on)
{
if (on) SSD1322_SendCommand(0xAF);
else SSD1322_SendCommand(0xAE);
}
/* Initialization sequence */
void SSD1322_Init(void)
{
SSD1322_Reset();
SSD1322_DisplayOnOff(false);
SSD1322_SendCommandWithData(0xFD, (uint8_t[]){0x12},1); // Command Lock
SSD1322_SendCommandWithData(0xB3, (uint8_t[]){0x91},1); // Display Clock
SSD1322_SendCommandWithData(0xCA, (uint8_t[]){0x3F},1); // MUX Ratio
SSD1322_SendCommandWithData(0xA2, (uint8_t[]){0x00},1); // Display Offset
SSD1322_SendCommandWithData(0xAB, (uint8_t[]){0x01},1); // Function Select (internal VDD)
SSD1322_SendCommandWithData(0xA1, (uint8_t[]){0x00},1); // Start Line
SSD1322_SendCommandWithData(0xA0, (uint8_t[]){0x16,0x11},2); // Remap
SSD1322_SendCommandWithData(0xC7, (uint8_t[]){0x0F},1); // Master Contrast
SSD1322_SendCommandWithData(0xC1, (uint8_t[]){0x9F},1); // Contrast
SSD1322_SendCommandWithData(0xB1, (uint8_t[]){0x72},1); // Phase Length
SSD1322_SendCommandWithData(0xBB, (uint8_t[]){0x1F},1); // Precharge Voltage
SSD1322_SendCommandWithData(0xB4, (uint8_t[]){0xA0,0xFD},2);// Display Enhancement A (VSL)
SSD1322_SendCommandWithData(0xBE, (uint8_t[]){0x04},1); // VCOMH
SSD1322_SendCommand(0xA6); // Normal Display
SSD1322_SendCommand(0xA9); // Exit Partial
SSD1322_SendCommandWithData(0xD1, (uint8_t[]){0xA2,0x20},2); // Display Enhancement B
SSD1322_SendCommandWithData(0xB5, (uint8_t[]){0x00},1); // GPIO
SSD1322_SendCommand(0xB9); // Default Grayscale
SSD1322_SendCommandWithData(0xB6, (uint8_t[]){0x08},1); // 2nd Precharge
SSD1322_DisplayOnOff(true);
}
/* Framebuffer: 2-bit grayscale (0..3), 64 rows x 128 columns */
uint8_t framebuf[64][128];
/* 2-bit -> byte mapping */
static inline uint8_t gray2byte(uint8_t g) {
switch (g & 0x03) {
case 0: return 0x00;
case 1: return 0x55;
case 2: return 0xAA;
case 3: return 0xFF;
default: return 0x00;
}
}
/* Writes framebuffer to GDDRAM */
void SSD1322_RefreshFromFramebuffer(void)
{
SSD1322_SetColumn(0x00, 0x7F);
SSD1322_SetRow(0x00, 0x3F);
SSD1322_SendCommand(0x5C); // Write RAM
uint8_t linebuf[256];
for (int row = 0; row < 64; row++) {
for (int col = 0; col < 128; col++) {
uint8_t b = gray2byte(framebuf[row][col]);
// linebuf[col * 2 + 0] = b;
// linebuf[col * 2 + 1] = b;
linebuf[col] = b;
}
DC_DAT();
CS_LOW();
ssd1322_spi_tx(linebuf, sizeof(linebuf));
CS_HIGH();
}
}
void DrawText(const char *s, int y)
{
int len = strlen(s);
int x0 = 57; // leaves 57 pixels of space from the left
for (int i = 0; i < len; i++) {
SSD1322_DrawChar(x0 + i * 6, y, s[i]);
}
}
/* Simple character drawing (6x8) */
void SSD1322_DrawChar(int x, int y, char c)
{
if (c < 32 || c > 127) return;
const uint8_t *glyph = Font6x8[c - 32];
for (int col = 0; col < 6; col++) {
int fx = x + col;
if (fx < 0 || fx >= 128) continue;
uint8_t column_bits = glyph[col];
for (int row = 0; row < 8; row++) {
int fy = y + row;
if (fy < 0 || fy >= 64) continue;
uint8_t pixel_on = (column_bits >> row) & 0x01;
framebuf[fy][fx] = pixel_on ? 3 : 0;
}
}
}
/* Clears the display via framebuffer */
void SSD1322_Clear(void)
{
for (int r=0; r<64; r++)
for (int c=0; c<128; c++)
framebuf[r][c] = 0;
SSD1322_RefreshFromFramebuffer();
}
/* Centered string (single line) */
void SSD1322_DrawStringCentered(const char *s)
{
int len = 0;
for (const char *p = s; *p; ++p) len++;
int total_width = len * 6 + (len - 1) * 1;
int x0 = (128 - total_width) / 2;
int y0 = (64 - 8) / 2;
/* clear */
for (int r=0;r<64;r++)
for (int c=0;c<128;c++)
framebuf[r][c]=0;
for (int i = 0; i < len; i++) {
int x = x0 + i * (6 + 1);
SSD1322_DrawChar(x, y0, s[i]);
}
SSD1322_RefreshFromFramebuffer();
}
/* Draws a scrolling string with offset (horizontal scroll) */
void SSD1322_DrawStringAtOffset(const char *s, int y, int offset)
{
// Clear only that line
for (int row = y; row < y + 8; row++)
for (int col = 0; col < 128; col++)
if (row >= 0 && row < 64)
framebuf[row][col] = 0;
int x = -offset;
for (int i = 0; s[i]; i++) {
SSD1322_DrawChar(x, y, s[i]);
x += 7; // 6px + 1 space
}
}
/* Scroll line structure and management */
void ScrollLine_Init(scrolling_line_t *line, const char *fmt, int y)
{
snprintf(line->text, sizeof(line->text), fmt);
int len = 0;
for (const char *p = line->text; *p; ++p) len++;
line->text_pixel_width = len * 7 - 1;
line->offset = 0;
line->direction = 1;
line->y = y;
}
void ScrollLine_Tick(scrolling_line_t *line)
{
if (line->text_pixel_width <= 128) {
int pad = (128 - line->text_pixel_width) / 2;
SSD1322_DrawStringAtOffset(line->text, line->y, -pad);
} else {
SSD1322_DrawStringAtOffset(line->text, line->y, line->offset);
line->offset += line->direction;
if (line->offset + 128 >= line->text_pixel_width) line->direction = -1;
if (line->offset <= 0) line->direction = 1;
}
}
/* Helper to clear the framebuffer */
void SSD1322_ClearFramebuffer(void)
{
// Since static framebuf is defined in this file, we can access it directly
for (int r = 0; r < 64; r++) {
for (int c = 0; c < 128; c++) {
framebuf[r][c] = 0;
}
}
}
// Set a single pixel
void SSD1322_SetPixel(int x, int y, uint8_t gray)
{
if (x < 0 || x >= 128 || y < 0 || y >= 64) return;
framebuf[y][x] = gray & 0x03; // 0..3
}
2025-09-01 3:24 AM - edited 2025-09-01 3:44 AM
1. GOOD - so far, some success.
2. >issue be caused by incorrect column address setup, remap configuration
Yes, this looks typical for wrong address/pixel count/offset etc. , or a missing/puzzled data line.
So : is manufact.exaple correct ? there should be the matching values for the init-values.
Size of screen is set here, so check values for display size here:
/* Column/row settings */ void SSD1322_SetColumn(uint8_t a, uint8_t b) { SSD1322_SendCommandWithData(0x15, (uint8_t[]){a, b}, 2); } void SSD1322_SetRow(uint8_t a, uint8_t b) { SSD1322_SendCommandWithData(0x75, (uint8_t[]){a, b}, 2); }
you dont show your code...so i only can guess.
2025-09-01 3:55 AM
Strangely, when I use the values shared by the manufacturer for the line, the image becomes more distorted. It's a very strange situation.
Below, I share the sample code provided by the manufacturer for Arduino.
/*
/ Program for writing to NHD-2.7-12864 OLED with SSD1322 controller with 4-wire Serial Interface
/ This code is written for the Arduino Due using Serial Interface
/
/ Newhaven Display invests time and resources providing this open source code,
/ Please support Newhaven Display by purchasing products from Newhaven Display!
* Copyright (c) 2025, Newhaven Display International
*
* This code is provided as an example only and without any warranty by Newhaven Display.
* Newhaven Display accepts no responsibility for any issues resulting from its use.
* The developer of the final application incorporating any parts of this
* sample code is responsible for ensuring its safe and correct operation
* and for any consequences resulting from its use.
* See the GNU General Public License for more details.
*
* Use Horizontal Orientation when converting BMP to hex code to display custom image using LCD assistant.
*/
//---------------------------------------------------------
#define OLED_DC 49 //Register Select signal
#define OLED_RESET 48 //Reset signal
#define OLED_CS 47 //Chip select signal
#define OLED_CLK 52 //Serial clock signal
#define OLED_MOSI 51 //Serial data signal
/****************************************************
* Hex Table for Image Pic *
*****************************************************/
unsigned char NHD_Logo [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xD9, 0x83, 0xC6, 0x31, 0x98, 0xC1, 0x82, 0x0C, 0x3C, 0x63, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0xD9, 0x87, 0xC6, 0x33, 0x98, 0xC1, 0x83, 0x0C, 0x7C, 0x73, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x1D, 0x86,
0x03, 0x33, 0x18, 0xC3, 0xC3, 0x18, 0xC0, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7F, 0xDD, 0x8E, 0xE3, 0x7B, 0x1F,
0xC3, 0x61, 0xB8, 0xFC, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xDF, 0x8F, 0xC1, 0xDF, 0x1F, 0xC6, 0x61, 0xB1,
0xFC, 0x6F, 0x00, 0x00, 0x00, 0x3C, 0x01, 0xC0, 0x1B, 0x84, 0x01, 0xCE, 0x18, 0xC7, 0xE0, 0xF0, 0xC0, 0x67, 0x00,
0x00, 0x00, 0x7E, 0x07, 0x9F, 0xDB, 0x87, 0xE1, 0xCE, 0x18, 0xCE, 0x70, 0xE0, 0x7C, 0x67, 0x00, 0x00, 0x00, 0x7F,
0xFE, 0x3F, 0xD9, 0x83, 0xE0, 0xCC, 0x18, 0xCC, 0x38, 0x60, 0x3C, 0x63, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xE0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x3C, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1F, 0x80, 0x0E, 0x00, 0x3F, 0x0C, 0x3F, 0x8F, 0xC3, 0x00, 0xC3, 0x18, 0x00, 0x00, 0x00, 0x00, 0x3F,
0xFF, 0xFC, 0x00, 0x3F, 0x8C, 0x3F, 0x8C, 0xE3, 0x01, 0xC3, 0x98, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00,
0x31, 0xCC, 0x30, 0x0C, 0x63, 0x01, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x30, 0xCC, 0x3F,
0x0E, 0xC3, 0x03, 0x20, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x30, 0xCC, 0x03, 0x8F, 0xC3, 0x03,
0xF0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x8C, 0x3F, 0x8C, 0x03, 0x07, 0xF0, 0x60, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x8C, 0x3F, 0x0C, 0x03, 0xE6, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x83, 0x41, 0xE0, 0x70, 0x78, 0x24, 0x0C,
0x0F, 0x06, 0x0F, 0x06, 0x81, 0x80, 0x80, 0x00, 0x01, 0x83, 0xC0, 0xC0, 0xE0, 0x58, 0x34, 0x0C, 0x06, 0x06, 0x09,
0x07, 0x81, 0x80, 0x80, 0x00, 0x01, 0x82, 0xC0, 0xC0, 0xC0, 0x70, 0x3C, 0x1E, 0x06, 0x06, 0x09, 0x05, 0x83, 0xC0,
0x80, 0x00, 0x01, 0x82, 0x40, 0xC0, 0x70, 0x58, 0x2C, 0x12, 0x06, 0x06, 0x0F, 0x04, 0x82, 0x40, 0xE0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/****************************************************
* Function Commands *
*****************************************************/
void data(unsigned char d) // Data Output Serial Interface
{
digitalWrite(OLED_CS, LOW);
digitalWrite(OLED_DC, HIGH);
for (unsigned int n = 0; n < 8; n++) {
digitalWrite(OLED_MOSI, (d & 0x80) ? HIGH : LOW); // Set MOSI based on the MSB
d <<= 1; // Shift data left
digitalWrite(OLED_CLK, LOW);
digitalWrite(OLED_CLK, HIGH); // Pulse the clock
}
digitalWrite(OLED_CS, HIGH);
}
void command(unsigned char d) // Command Output Serial Interface
{
digitalWrite(OLED_CS, LOW);
digitalWrite(OLED_DC, LOW);
for (unsigned int n = 0; n < 8; n++) {
digitalWrite(OLED_MOSI, (d & 0x80) ? HIGH : LOW); // Set MOSI based on the MSB
d <<= 1; // Shift the data left by 1 bit
digitalWrite(OLED_CLK, LOW);
digitalWrite(OLED_CLK, HIGH); // Pulse the clock
}
digitalWrite(OLED_CS, HIGH);
}
/****************************************************
* Display Commands *
*****************************************************/
void Set_Column_Address_12864(unsigned char a, unsigned char b)
{
command(0x15); // Set Column Address
data(a); // Default => 0x00
data(b); // Default => 0x77
}
//--------------------------------------------------------------------------
void Set_Write_RAM_12864()
{
command(0x5C); // Enable MCU to Write DATA RAM
}
//--------------------------------------------------------------------------
void Set_Row_Address_12864(unsigned char a, unsigned char b)
{
command(0x75); // Set Row Start and End Address
data(a); // Default => 0x00
data(b); // Default => 0x7F
}
//--------------------------------------------------------------------------
void Set_Remap_12864(unsigned char a, unsigned char b)
{
command(0xA0); // Set Remap
data(a); // Default => 0x00
data(b); // Default => 0x00
}
//--------------------------------------------------------------------------
void Set_Display_Start_Line_12864(unsigned char a)
{
command(0xA1); // Set Display RAM Display Start Line
data(a); // Default => 0x00
}
//--------------------------------------------------------------------------
void Set_Display_Offset_12864(unsigned char a)
{
command(0xA2); // Set Verticle Shift
data(a); // Default => 0x00
}
//--------------------------------------------------------------------------
void Display_Mode_12864(unsigned char a)
{
command(a); // 0xA4 => Entire Display OFF
// 0xA5 => Entire Display ON, all pixels Grayscale level 15
// 0xA6 => Normal Display (Default)
// 0xA7 => Inverse Display
}
//--------------------------------------------------------------------------
void Enable_Partial_Display_12864(unsigned char a, unsigned char b)
{
command(0xA8); // Turns ON partial mode
data(a); // Address of start row
data(b); // Address of end row.
}
//--------------------------------------------------------------------------
void Exit_Partial_Display_12864()
{
command(0xA9); // Exit Partial Display Mode
}
//--------------------------------------------------------------------------
void Function_Selection_12864(unsigned char a)
{
command(0xAB); // Function Selection
data(a); // Default => 0x01
}
//--------------------------------------------------------------------------
void Set_Sleep_Mode_12864(unsigned char a)
{
command(a); // 0xAE => Sleep Mode ON
// 0xAF => Sleep Mode OFF
}
//--------------------------------------------------------------------------
void Set_Phase_Length_12864(unsigned char a)
{
command(0xB1); // Set Phase Length
data(a); // Default => 0x97
}
//--------------------------------------------------------------------------
void Set_Display_Clock__Oscillator_Frequency_12864(unsigned char a)
{
command(0xB3); // Set Osc Frequency
data(a); //
}
//--------------------------------------------------------------------------
void Enable_External_VSL(unsigned char a, unsigned char b)
{
command(0xB4); // Enable External VSL
data(a); //
data(b); //
}
//--------------------------------------------------------------------------
void Set_GPIO_12864(unsigned char a)
{
command(0xB5); // Set GPIO
data(a); //
}
//--------------------------------------------------------------------------
void Set_Second_Precharge_Period_12864(unsigned char a)
{
command(0xB6); // Set Second Precharge Period
data(a); //
}
//--------------------------------------------------------------------------
void Default_Grayscale_Command_12864()
{
command(0xB9); // Sets Default Grayscale
}
//--------------------------------------------------------------------------
void Set_Precharge_Voltage_12864(unsigned char a)
{
command(0xBB); // Set Precharge Voltage Level
data(a); // Default => 0x17
}
//--------------------------------------------------------------------------
void Set_VCOMH_Voltage_12864(unsigned char a)
{
command(0xBE); // Set Second Precharge Period
data(a); // Default => 0x04
}
//--------------------------------------------------------------------------
void Set_Contrast_Control_12864(unsigned char a)
{
command(0xC1); // Set Contrast Control Level
data(a); // Default => 0x7F
}
//--------------------------------------------------------------------------
void Master_Contrast_Control_12864(unsigned char a)
{
command(0xC7); // Master Contrast Control
data(a); // Default => 0x0F
}
//--------------------------------------------------------------------------
void Set_Multiplex_Ratio_12864(unsigned char a)
{
command(0xCA); // Set MUX Ratio
data(a); // Default => 0x7F
}
//--------------------------------------------------------------------------
void Display_Enhancement_12864(unsigned char a)
{
command(0xD1); // Display Enhancement
data(a); //
data(0x20); //
}
//--------------------------------------------------------------------------
void Set_Command_Lock_12864(unsigned char a)
{
command(0xFD); // Set Lock/Unlock Commands
data(a); // Default => 0x12
}
//--------------------------------------------------------------------------
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Show Blank (Clear Screen)
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void ClearPixel_12864()
{
Set_Column_Address_12864(0x1C, 0x5B);
Set_Row_Address_12864(0x00, 0x3F);
Set_Write_RAM_12864();
for (unsigned int i = 0; i < 64 * 128; i++) {
data(0x00); // Clear pixel by sending 0
delayMicroseconds(100);
}
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Show Checkboard (Full Screen)
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void FillPixel_12864()
{
unsigned int i, j;
Set_Column_Address_12864(0x1C,0x5B); //1C & 5B = DISPLAY Start & End address.
Set_Row_Address_12864(0x00,0x3F);
Set_Write_RAM_12864();
for(i=0;i<32;i++) //Columns
{
for(j=0;j<64;j++) //Rows
{
data(0xFF);
delayMicroseconds(100);
data(0x00);
delayMicroseconds(100);
}
for(j=0;j<64;j++) //Rows
{
data(0x00);
delayMicroseconds(100);
data(0xFF);
delayMicroseconds(100);
}
}
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Show Image (Full Screen)
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Driver IC Mapping = 256x64 (2 SEG Lines Tied to 1 COM Line to form 1 Pixel)
// 8 bits (1 Byte) = 1 Pixel.
// Function parses through Hex Table Data and spreads 1 Byte of data over 8 Pixels.
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void ImageDisplay_12864(unsigned char *image)
{
unsigned int i, l, n, buff;
//Set_Remap_12864(0x04,0x11); //To flip 180 degrees
Set_Column_Address_12864(0x1C,0x5B);
Set_Row_Address_12864(0x00,0x3F);
Set_Write_RAM_12864();
for(i=0;i<1024;i++){
buff = *image;
n = 7;
for(l=0;l<8;l++){
if((buff >> n) & 0x80 == 0x80){
data(0xFF);
}
else{
data(0x00);
}
n--;
}
image++;
}
}
/****************************************************
* Initialization For controller *
*****************************************************/
void OLED_Init_12864()
{
// Turn off the display before starting initialization
Set_Sleep_Mode_12864(0xAE); // Display OFF
// Unlock commands for OLED
Set_Command_Lock_12864(0x12);
// Set display clock and oscillator frequency
Set_Display_Clock__Oscillator_Frequency_12864(0x91);
// Configure display settings
Set_Multiplex_Ratio_12864(0x3F); // Set Multiplex Ratio
Set_Display_Offset_12864(0x00); // Set Display Offset
Function_Selection_12864(0x01); // Function Selection
Set_Display_Start_Line_12864(0x00); // Set Display Start Line
// Set remap for display orientation
Set_Remap_12864(0x16, 0x11); // Adjust A[1] & A[4] to flip display
// Adjust contrast and phase length
Master_Contrast_Control_12864(0x0F); // Master Contrast Control
Set_Contrast_Control_12864(0x9F); // Set Contrast Control
Set_Phase_Length_12864(0x72); // Set Phase Length
// Set voltage and charge settings
Set_Precharge_Voltage_12864(0x1F); // Set Precharge Voltage
Enable_External_VSL(0xA0, 0xFD); // Enable External VSL
Set_VCOMH_Voltage_12864(0x04); // Set VCOMH Voltage
// Configure display mode and enhancement
Display_Mode_12864(0xA6); // Normal Display Mode
Display_Enhancement_12864(0xA2); // Display Enhancement
// Set GPIO and default grayscale settings
Set_GPIO_12864(0x00); // Set GPIO
Default_Grayscale_Command_12864(); // Default Linear Grayscale Table
// Set second precharge period
Set_Second_Precharge_Period_12864(0x08); // Set Second Precharge Period
// Turn the display back on after initialization
Set_Sleep_Mode_12864(0xAF); // Display ON
}
/*****************************************************
* Setup Function, to run once *
*****************************************************/
void setup()
{
pinMode(OLED_CLK, OUTPUT);
pinMode(OLED_MOSI, OUTPUT);
pinMode(OLED_DC, OUTPUT);
pinMode(OLED_RESET, OUTPUT);
pinMode(OLED_CS, OUTPUT);
digitalWrite(OLED_RESET, LOW);
delay(150);
digitalWrite(OLED_RESET, HIGH);
delay(150);
OLED_Init_12864(); //Initialization Sequence
delay(10);
}
/*****************************************************
* Loop Function, to run repeatedly *
*****************************************************/
void loop() {
FillPixel_12864();
delay(1000); //1 second delay
ClearPixel_12864();
delay(250); //1/4 second delay
ImageDisplay_12864(NHD_Logo);
delay(2000); //2 second delay
command(0xA7);
delay(2000); //2 second delay
command(0xA6);
delay(2000); //2 second delay
ClearPixel_12864();
delay(250); //1/4 second delay
}
2025-09-01 4:31 AM
Hmmm.
did you set 128x64 pix ? ->
/* Column/row settings */ void SSD1322_SetColumn(uint8_t a, uint8_t b) { SSD1322_SendCommandWithData(0x15, (uint8_t[]){a, b}, 2); } void SSD1322_SetRow(uint8_t a, uint8_t b) { SSD1322_SendCommandWithData(0x75, (uint8_t[]){a, b}, 2); }
this:
Set_Column_Address_12864(0x1C,0x5B); Set_Row_Address_12864(0x00,0x3F);
then it should show 128x64 pix.
2025-09-01 5:01 AM
I've tryied it and result :(
I don't understand that where is the problem
2025-09-01 6:20 AM - edited 2025-09-01 6:21 AM
Ok. :)
So what i do with new display:
- first find driver, that should work. (ok now.)
- init display, then cls (write all pixel with...black here.) try. -> shows clean...nothing, if working ok.
- maybe next: write full area in...white. -> full bright area, can see if all pixel working, addr ok..etc. try.
- then cls, black, write some char at pos 4;4; to see is orientation ok, char font ok , try.
- then..use it, now it should work as it should.
+
With your "error pattern" : is it 100% constant on some reset/restarts ? (to exclude errors on connection lines).
or some lines/gaps always litte bit different positions?