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