STM32 I2C Library for SD1306 OLED

STM32 I2C Library for SD1306 OLED

Please read Liability Disclaimer and License Agreement CAREFULLY

Search on internet for fonts that you can use with this library.

Example usage

SD1306_Init();
SD1306_SetCursor(0,0);
SD1306_WriteString("Grozea Ion",Font_7x10,_WHITE);
SD1306_SetCursor(0,30);
SD1306_WriteString("Star",Font_7x10,_WHITE);
SD1306_SetCursor(0,40);
SD1306_WriteString("Tracker",Font_7x10,_WHITE);
SD1306_UpdateScreen();

SD1306.h

 

#ifndef __SD1306_H
#define __SD1306_H

#ifdef __cplusplus
extern "C" {
#endif
    
#include "i2c.h"
#include "fonts.h"
#define SD1306_WIDTH                                0x80//128
#define SD1306_HEIGHT                                0x40//64
#define SD1306_VCC_STATE                            0x02
#define SD1306_EXTERNALVCC                            0x01
#define SD1306_BUFF_Size                            ((SD1306_WIDTH * SD1306_HEIGHT) / 8)
#define SD1306_I2C_ADDR                                0x78
//#define SD1306_I2C_ADDR                            0x7A
// Scrolling #defines
#define SD1306_ACTIVATE_SCROLL                        0x2F
#define SD1306_DEACTIVATE_SCROLL                    0x2E
#define SD1306_SET_VERTICAL_SCROLL_AREA                0xA3
#define SD1306_RIGHT_HORIZONTAL_SCROLL                0x26
#define SD1306_LEFT_HORIZONTAL_SCROLL                0x27
#define SD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL    0x29
#define SD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL    0x2A

#define SD1306_INVERTDISPLAY                        0xA7    
#define SD1306_NORMALDISPLAY                        0xA6    

#define SD1306_SETLOWCOLUMN                            0x00
#define SD1306_SETHIGHCOLUMN                        0x10
#define SD1306_SETCONTRAST                            0x81

typedef enum {
    _BLACK = 0x00, /*!< Black color, no pixel */
    _WHITE = 0x01  /*!< Pixel is set. Color depends on LCD */
} SD1306_COLOR;

typedef struct {
    uint8_t CurrentX;
    uint8_t CurrentY;
    uint8_t Inverted;
} SD1306_t;

void SD1306_Init(void);
void SD1306_InvertDisplay(uint8_t i);

void SD1306_Scroll_R(uint8_t start, uint8_t stop);
void SD1306_Scroll_L(uint8_t start, uint8_t stop);
void SD1306_Scroll_DR(uint8_t start, uint8_t stop);
void SD1306_Scroll_DL(uint8_t start, uint8_t stop);
void SD1306_Scroll_Stop(void);
void SD1306_Dim(uint8_t dim);

void SD1306_Fill(SD1306_COLOR color);
void SD1306_UpdateScreen(void);
void SD1306_DrawPixel(uint8_t x, uint8_t y, SD1306_COLOR color);
char SD1306_WriteChar(char ch, FontDef Font, SD1306_COLOR color);
char SD1306_WriteString(char* str, FontDef Font, SD1306_COLOR color);
void SD1306_SetCursor(uint8_t x, uint8_t y);
void SD1306_SetFont(uint8_t FontSize);
#ifdef __cplusplus
}
#endif

#endif /* __SSD1306_H */

 

 

SD1306.c

 

#include "SD1306.h"

static uint8_t SD1306_Buffer[SD1306_BUFF_Size];
static SD1306_t SD1306;

static void SD1306_WriteCommand(uint8_t command)
{
    
    HAL_I2C_Mem_Write(&hi2c1, SD1306_I2C_ADDR, SD1306_SETLOWCOLUMN, 1, &command, 1, PORT_TIMEOUT);
    //ToDo make it work with DMA
    //while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY){}
    //HAL_I2C_Mem_Write_DMA(&hi2c1, SD1306_I2C_ADDR, SD1306_SETLOWCOLUMN, 1, &command, 1);
}

void SD1306_Init(void) {
    HAL_Delay(100);
    /* Init LCD */
    SD1306_WriteCommand(0xAE); //display off
    SD1306_WriteCommand(0x20); //Set Memory Addressing Mode   
    SD1306_WriteCommand(SD1306_SETHIGHCOLUMN); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
    SD1306_WriteCommand(0xB0); //Set Page Start Address for Page Addressing Mode,0-7
    SD1306_WriteCommand(0xC8); //Set COM Output Scan Direction
    SD1306_WriteCommand(SD1306_SETLOWCOLUMN); //---set low column address
    SD1306_WriteCommand(SD1306_SETHIGHCOLUMN); //---set high column address
    SD1306_WriteCommand(0x40); //--set start line address
    SD1306_WriteCommand(SD1306_SETCONTRAST); //--set contrast control register
    SD1306_WriteCommand(0xFF);
    SD1306_WriteCommand(0xA1); //--set segment re-map 0 to 127
    SD1306_WriteCommand(0xA6); //--set normal display
    SD1306_WriteCommand(0xA8); //--set multiplex ratio(1 to 64)
    SD1306_WriteCommand(0x3F); //
    SD1306_WriteCommand(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
    SD1306_WriteCommand(0xD3); //-set display offset
    SD1306_WriteCommand(SD1306_SETLOWCOLUMN); //-not offset
    SD1306_WriteCommand(0xD5); //--set display clock divide ratio/oscillator frequency
    SD1306_WriteCommand(0xF0); //--set divide ratio
    SD1306_WriteCommand(0xD9); //--set pre-charge period
    SD1306_WriteCommand(0x22); //
    SD1306_WriteCommand(0xDA); //--set com pins hardware configuration
    SD1306_WriteCommand(0x12);
    SD1306_WriteCommand(0xDB); //--set vcomh
    SD1306_WriteCommand(0x20); //0x20,0.77xVcc
    SD1306_WriteCommand(0x8D); //--set DC-DC enable
    SD1306_WriteCommand(0x14); //
    SD1306_WriteCommand(0xAF); //--turn on SSD1306 panel
    /* Clearen scherm */
    SD1306_Fill(_BLACK);
    /* Update screen */
    SD1306_UpdateScreen();
    /* Set default values */
    SD1306.CurrentX = 0;
    SD1306.CurrentY = 0;
}

void SD1306_InvertDisplay(uint8_t i) {
  if (i) {
    SD1306_WriteCommand(SD1306_INVERTDISPLAY);
  } else {
    SD1306_WriteCommand(SD1306_NORMALDISPLAY);
  }
}

// startscrollright
// Activate a right handed scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(SD1306_SETLOWCOLUMN, 0x0F)
void SD1306_Scroll_R(uint8_t start, uint8_t stop){
  SD1306_WriteCommand(SD1306_RIGHT_HORIZONTAL_SCROLL);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(start);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(stop);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(0XFF);
  SD1306_WriteCommand(SD1306_ACTIVATE_SCROLL);
}

// startscrollleft
// Activate a right handed scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(SD1306_SETLOWCOLUMN, 0x0F)
void SD1306_Scroll_L(uint8_t start, uint8_t stop){
  SD1306_WriteCommand(SD1306_LEFT_HORIZONTAL_SCROLL);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(start);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(stop);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(0XFF);
  SD1306_WriteCommand(SD1306_ACTIVATE_SCROLL);
}

// startscrolldiagright
// Activate a diagonal scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(SD1306_SETLOWCOLUMN, 0x0F)
void SD1306_Scroll_DR(uint8_t start, uint8_t stop){
  SD1306_WriteCommand(SD1306_SET_VERTICAL_SCROLL_AREA);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(SD1306_HEIGHT);
  SD1306_WriteCommand(SD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(start);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(stop);
  SD1306_WriteCommand(0X01);
  SD1306_WriteCommand(SD1306_ACTIVATE_SCROLL);
}

// startscrolldiagleft
// Activate a diagonal scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(SD1306_SETLOWCOLUMN, 0x0F)
void SD1306_Scroll_DL(uint8_t start, uint8_t stop){
  SD1306_WriteCommand(SD1306_SET_VERTICAL_SCROLL_AREA);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(SD1306_HEIGHT);
  SD1306_WriteCommand(SD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(start);
  SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
  SD1306_WriteCommand(stop);
  SD1306_WriteCommand(0X01);
  SD1306_WriteCommand(SD1306_ACTIVATE_SCROLL);
}

void SD1306_Scroll_Stop(void){
  SD1306_WriteCommand(SD1306_DEACTIVATE_SCROLL);
}

// Dim the display
// dim = 1: display is dimmed
// dim = 0: display is normal
void SD1306_Dim(uint8_t dim) {
  uint8_t contrast;
  if (dim) {
    contrast = 0; // Dimmed display
  } else {
    if (SD1306_VCC_STATE == SD1306_EXTERNALVCC) {
      contrast = 0x9F;
    } else {
      contrast = 0xCF;
    }
  }
  // the range of contrast to too small to be really useful
  // it is useful to dim the display
  SD1306_WriteCommand(SD1306_SETCONTRAST);
  SD1306_WriteCommand(contrast);
}

void SD1306_Fill(SD1306_COLOR color) {
    /* Set memory */
    uint16_t i;
    for(i = 0; i < SD1306_BUFF_Size ; i++)
    {
        SD1306_Buffer[i] = color;
    }
}

void SD1306_UpdateScreen(void) {
    uint8_t i;
    for (i = 0; i < 8; i++) {
        while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY){}
        SD1306_WriteCommand(0xB0 + i);
        SD1306_WriteCommand(SD1306_SETLOWCOLUMN);
        SD1306_WriteCommand(SD1306_SETHIGHCOLUMN);
        HAL_I2C_Mem_Write(&hi2c1, SD1306_I2C_ADDR, 0x40, 1, &SD1306_Buffer[SD1306_WIDTH * i], SD1306_WIDTH, PORT_TIMEOUT);
        //HAL_I2C_Mem_Write_DMA(&hi2c1, SD1306_I2C_ADDR, 0x40, 1, &SD1306_Buffer[SD1306_WIDTH * i], SD1306_WIDTH);
    }
}

void SD1306_DrawPixel(uint8_t x, uint8_t y, SD1306_COLOR color)
{
    if (x >= SD1306_WIDTH || y >= SD1306_HEIGHT) {
        return;
    }
    
    if (SD1306.Inverted) {
        color = (SD1306_COLOR)!color;
    }
    
    if (color == _WHITE)    {
        SD1306_Buffer[x + (y / 8) * SD1306_WIDTH] |= 1 << (y % 8);
    } 
    else {
        SD1306_Buffer[x + (y / 8) * SD1306_WIDTH] &= ~(1 << (y % 8));
    }
}

char SD1306_WriteChar(char ch, FontDef Font, SD1306_COLOR color)
{
    uint32_t i, b, j;
    if (SD1306_WIDTH <= (SD1306.CurrentX + Font.FontWidth) ||    SD1306_HEIGHT <= (SD1306.CurrentY + Font.FontHeight))    {
        return 0;
    }
    
    for (i = 0; i < Font.FontHeight; i++)    {
        b = Font.data[(ch - 32) * Font.FontHeight + i];
        for (j = 0; j < Font.FontWidth; j++) {
            if ((b << j) & 0x8000) {
                SD1306_DrawPixel(SD1306.CurrentX + j, (SD1306.CurrentY + i), (SD1306_COLOR) color);
            } 
            else {
                SD1306_DrawPixel(SD1306.CurrentX + j, (SD1306.CurrentY + i), (SD1306_COLOR)!color);
            }
        }
    }
    
    // De huidige positie is nu verplaatst
    SD1306.CurrentX += Font.FontWidth;
    // We geven het geschreven char terug voor validatie
    return ch;
}

char SD1306_WriteString(char* str, FontDef Font, SD1306_COLOR color)
{
    while (*str) {
        if (SD1306_WriteChar(*str, Font, color) != *str){
            return *str;
        }
        str++;
    }
    return *str;
}

void SD1306_SetCursor(uint8_t x, uint8_t y) 
{
    SD1306.CurrentX = x;
    SD1306.CurrentY = y;
}

 

Comments powered by CComment

Who’s online

We have 32 guests and no members online