[MCU Notes] OLED controller SSD1306 and driver code

Publisher:温雅如风Latest update time:2019-02-18 Source: eefocusKeywords:MCU Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Preface:


I have rarely used OLED for a long time, and even if I did, I would refer to the code of experts. Recently, I had to study it again carefully. Write it down so that I don't forget it.


The 0.61-inch OLED I have on hand has a resolution of 96*16, which means there are 96 dots horizontally and 16 dots vertically. Here is the size diagram.



I haven't read too much information, and there is a lot of information on the Internet. Most of them are about SSD1306. Here I will simply record it. Take this 96*16 as an example. SSD has done paging in the vertical direction (y direction), and every 8 pixels are a group (8 pixels = 8 bits = one byte). So for 16 points in the y direction, it is divided into two pages, starting from 0, which is 0 and 1. The same is true for other resolutions, just add upwards. When driving, the most common method is from left to right, from top to bottom. It is worth noting that different models may have different ways of taking the module. Some have the high bit in front and some have the low bit in front. I am now using the low bit in front, which is still mentioned in the manual. The following is the software and configuration options for taking the module:


The software used is: PCtoLCD2002


The modulo configuration is as follows:


Effect picture:



Finally, I attach the detailed code (theoretically supports all SSD1306 controllers). I have also tried it on 12832 and there is no problem. You need to modify the macro definition yourself. The code has detailed Chinese comments:


#include "fy_oled12832.h"

#include "fy_oledfont.h"   




#define OLED_IIC_SCL_PIN GPIO_PIN_4

#define OLED_IIC_SCL_L() GPIO_WriteLow(OLED_IIC_SCL_PORT,OLED_IIC_SCL_PIN) //Clock signal of SCL IIC interface

#define OLED_IIC_SCL_H() GPIO_WriteHigh(OLED_IIC_SCL_PORT,OLED_IIC_SCL_PIN)//PB4


#define OLED_IIC_SDA_PORT GPIOB

#define OLED_IIC_SDA_PIN GPIO_PIN_5

#define OLED_IIC_SDA_L() GPIO_WriteLow(OLED_IIC_SDA_PORT,OLED_IIC_SDA_PIN) //SDA IIC interface data signal

#define OLED_IIC_SDA_H() GPIO_WriteHigh(OLED_IIC_SDA_PORT,OLED_IIC_SDA_PIN)//PB5

 

/*

96*16 pixels 

x[0-95]

y[0-15]

Note: The y direction is divided into two pages, each page has 8 pixels, which is exactly one byte.

*/


  

#define Max_x 96

#define Max_y 2    

#define OLED_IIC_SCL_PORT GPIOB

     

#define OLED_CMD 0X00 //write command

#define OLED_DATA 0X40 //Write data


static void Oled_IIC_Configuration(void)

{

GPIO_Init(OLED_IIC_SCL_PORT,OLED_IIC_SCL_PIN,GPIO_MODE_OUT_PP_LOW_FAST); //Set PB4 to push-pull output

GPIO_Init(OLED_IIC_SDA_PORT,OLED_IIC_SDA_PIN,GPIO_MODE_OUT_PP_LOW_FAST); //Set PB5 to push-pull output 

}


//IIC Start

static void Oled_IIC_Start(void)

{

OLED_IIC_SCL_H();

OLED_IIC_SDA_H();

OLED_IIC_SDA_L();

OLED_IIC_SCL_L();

}


//IIC Stop

static void Oled_IIC_Stop(void)

{

OLED_IIC_SCL_L();

OLED_IIC_SDA_L();

OLED_IIC_SDA_H();

OLED_IIC_SCL_H();

}


// IIC Send byte

static void Oled_IIC_SendByte(u8 dat)

{

u8 i;

for(i=0;i<8;i++)

{

OLED_IIC_SCL_L();

if(dat & 0x80)

OLED_IIC_SDA_H();

else 

OLED_IIC_SDA_L();

dat<<=1;

OLED_IIC_SCL_H();

}


OLED_IIC_SCL_L();

OLED_IIC_SCL_H();

}


//OLED writes a byte 

//dat: bytes written 

//cmd: command or data

void Oled_WriteByte(u8 dat,u8 cmd)

{

Oled_IIC_Start();

Oled_IIC_SendByte(0x78);

Oled_IIC_SendByte(cmd);

Oled_IIC_SendByte(dat);

Oled_IIC_Stop();

}


//Coordinate setting

void Oled_SetPos(u8 x, u8 y) 

Oled_WriteByte(0xb0+y,OLED_CMD);

Oled_WriteByte(((x&0xf0)>>4)|0x10,OLED_CMD);

Oled_WriteByte((x&0x0f),OLED_CMD); 

}      

     

//Clear screen   

void Oled_Clear(void)  

{  

u8 i,n;     

for(i=0;i

{  

Oled_WriteByte (0xb0+i,OLED_CMD); //Set page address (0~1)

Oled_WriteByte (0x00,OLED_CMD); //Set display position - column low address

Oled_WriteByte (0x10,OLED_CMD); //Set display position - column high address   

for(n=0;n

} //Update the display

}


//Display a character at the specified position

void Oled_ShowChar(u8 x,u8 y,u8 chr)

{     

u8 c=0,i=0;

c=chr-' '; //Get the offset value

if(x>Max_x-1)

{

  x=0;

  y++;

  if(y>Max_y-1) return;

}//Here y represents the page address 6*8 characters so the page is increased by one

Oled_SetPos(x,y);

for(i=0;i<6;i++) //6*8 character dot matrix occupies 6 columns, 8 pixels per column (one byte), that is, 6 columns on a page

Oled_WriteByte(F6x8[c][i],OLED_DATA);

}


// Display a character string

void Oled_ShowString(u8 x,u8 y,u8 *chr)

{

u8 j=0;

if(y>Max_y-1) return;

while (chr[j]!='\0')

{

Oled_ShowChar(x,y,chr[j]);

x+=6; //6*8 character matrix occupies 6 columns, so add 6

if(x>Max_x-6){x=0;y++;}          

j++;

}

}


//Display Chinese characters 16*16

void Oled_ShowCHinese(u8 x,u8 y,u8 no)

{          

u8 t;

Oled_SetPos(x,y);

for(t=0;t<16;t++)//Write the first page first

{

Oled_WriteByte(Hzk[2*no][t],OLED_DATA);

}

Oled_SetPos(x,y+1);

for(t=0;t<16;t++)//Write the second page

{

Oled_WriteByte(Hzk[2*no+1][t],OLED_DATA);

}

}



//Initialize SSD1306     

void Oled_Configuration(void)

{

  Oled_IIC_Configuration();

  Delay_ms(100);


Oled_WriteByte(0xAE,OLED_CMD);//--display off

Oled_WriteByte(0x00,OLED_CMD);//---set low column address

Oled_WriteByte(0x10,OLED_CMD);//---set high column address

Oled_WriteByte(0x40,OLED_CMD);//--set start line address  

Oled_WriteByte(0xB0,OLED_CMD);//--set page address

Oled_WriteByte(0x81,OLED_CMD); // contract control

Oled_WriteByte(0xFF,OLED_CMD);//--128   

Oled_WriteByte(0xA1,OLED_CMD);//set segment remap 

Oled_WriteByte(0xA6,OLED_CMD);//--normal / reverse

Oled_WriteByte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)

Oled_WriteByte(0x0F,OLED_CMD);//--1/16 duty

Oled_WriteByte(0xC8,OLED_CMD);//Com scan direction

Oled_WriteByte(0xD3,OLED_CMD);//-set display offset

Oled_WriteByte(0x00,OLED_CMD);//

Oled_WriteByte(0xD5,OLED_CMD);//set osc division

Oled_WriteByte(0x80,OLED_CMD);//

Oled_WriteByte(0xD9,OLED_CMD);//set pre-charge period

Oled_WriteByte(0x22,OLED_CMD);//

Oled_WriteByte(0xDA,OLED_CMD);//set COM pins

Oled_WriteByte(0x02,OLED_CMD);//

Oled_WriteByte(0xDB,OLED_CMD);//set vcomh

Oled_WriteByte(0x40,OLED_CMD);//

Oled_WriteByte(0x8D,OLED_CMD);//set charge pump enable

Oled_WriteByte(0x14,OLED_CMD);//

Oled_WriteByte(0xAF,OLED_CMD);//--turn on oled panel

}  



void Oled_TEST(void)

{

Delay_ms(200); //Delay 200ms

Oled_Configuration(); //OLED initialization

Delay_ms(200); //Delay 200ms

Oled_Clear(); //Clear screen

Delay_ms(200); //Delay 200ms


while (1)

  

  Oled_Clear(); //Clear screen

  Oled_ShowString(0,0,"012345678ABCDEFGQWERTYUIOO");//Display numbers


  Delay_ms(2000);

  

  Oled_Clear(); //Clear the screen

  Oled_ShowCHinese(8,0,0); //Display the Chinese character "火"

  Oled_ShowCHinese(24,0,1); //Display Chinese character "星"

  Oled_ShowCHinese(40,0,2); //Display Chinese character "科"

  Oled_ShowCHinese(56,0,3); //Display Chinese character "技"

  

  Delay_ms(2000);

}

}


Fonts:

#ifndef __FY_OLEDFONT_H

#define __FY_OLEDFONT_H    


const unsigned char F6x8[][6] =

{

    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp

    { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // !

    { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // "

    { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // #

    { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $

    { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // %

    { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // &

    { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // '

    { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // (

    { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // )

    { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // *

    { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // +

    { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // ,

    { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, // -

    { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // .

    { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // /

    { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0

    { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1

    { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2

    { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3

    { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4

    { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5

    { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6

    { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7

    { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8

    { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9

    { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // :

    { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;

    { 0x08, 0x1C, 0x2A, 0x49, 0x08, 0x08 }, // <

    { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // =

    { 0x08, 0x08, 0x49, 0x2A, 0x1C, 0x08 }, // >

    { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?

    { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @

    { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A

    { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B

    { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C

    { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D

    { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E

    { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F

    { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G

    { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H

    { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I

    { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J

    { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K

    { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L

    { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M

    { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N

    { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O

    { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P

    { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q

    { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R

    { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S

    { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T

    { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U

    { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V

    { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W

    { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X

    { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y

    { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z

    { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [

    { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // 55

    { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ]

    { 0x04, 0x02, 0xFF, 0x02, 0x04, 0x00 }, // ^

    { 0x00, 0x20, 0x40, 0xFF, 0x40, 0x20 }, // _

    { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // '

    { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a

    { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b

    { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c

    { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d

    { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e

    { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f

    { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g

    { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h

    { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i

    { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j

    { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k

    { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l

    { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m

    { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n

    { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o

    { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p

    { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q

    { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r

    { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s

    { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t

    { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u

    { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v

    { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w

    { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x

    { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y

    { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z

    { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 } // horiz lines

};

char Hzk[][32]={


{0x00,0x00,0xC0,0x38,0x00,0x00,0x00,0xFF,0x00,0x00,0x40,0x20,0x18,0x00,0x00,0x00},

{0x80,0x81,0x40,0x20,0x10,0x0C,0x03,0x00,0x03,0x0C,0x10,0x20,0x40,0x80,0x80,0x00},/*"火",0*/


{0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00,0x00},

{0x00,0x44,0x42,0x49,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x41,0x40,0x00,0x00},/*"星",1*/


{0x24,0x24,0xA4,0xFE,0xA3,0x22,0x00,0x22,0xCC,0x00,0x00,0xFF,0x00,0x00,0x00,0x00},

{0x08,0x06,0x01,0xFF,0x00,0x01,0x04,0x04,0x04,0x04,0x04,0xFF,0x02,0x02,0x02,0x00},/*"科",2*/


{0x10,0x10,0x10,0xFF,0x10,0x90,0x08,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x08,0x00},

{0x04,0x44,0x82,0x7F,0x01,0x80,0x80,0x40,0x43,0x2C,0x10,0x28,0x46,0x81,0x80,0x00},/*"技术",3*/


};


#endif



/******************************************END OF FILE* *********************************************/



Test routine:


void Oled_TEST(void)

{

Delay_ms(200); //Delay 200ms

Oled_Configuration(); //OLED initialization

Delay_ms(200); //Delay 200ms

Oled_Clear(); //Clear screen

Delay_ms(200); //Delay 200ms


while (1)

  

  Oled_Clear(); //Clear screen

  Oled_ShowString(0,0,"012345678ABCDEFGQWERTYUIOO");//Display characters


  Delay_ms(2000);

  

  Oled_Clear(); //Clear the screen

  Oled_ShowCHinese(8,0,0); //Display the Chinese character "火"

  Oled_ShowCHinese(24,0,1); //Display Chinese character "星"

  Oled_ShowCHinese(40,0,2); //Display Chinese character "科"

  Oled_ShowCHinese(56,0,3); //Display Chinese character "技"

  

  Delay_ms(2000);

}

}



That’s it!

--------------------- 

Author: Silent Little Universe 

Source: CSDN 

Original text: https://blog.csdn.net/qq997758497/article/details/78511281 

Copyright Statement: This article is an original article by the blogger. Please attach the blog link when reprinting!


Keywords:MCU Reference address:[MCU Notes] OLED controller SSD1306 and driver code

Previous article:[MCU Notes] Practical method to quickly convert nonlinear tables in code into arrays
Next article:[MCU Notes] STM8S series MCU FLASH operation

Recommended ReadingLatest update time:2024-11-23 08:11

STM32 MCU PWM output test
environment: Host: XP Development environment: MDK4.23 MCU:STM32F103CBT6   illustrate: Use the internal 8M crystal oscillator, multiply it to 64M to supply the TIM3 timer, and generate 640K, 50% square wave on PA6 (channel 1) source code: Initialize the clock: //Initialize RCC clock   void init_rcc(void)   {  
[Microcontroller]
STM32 MCU PWM output test
51 single chip microcomputer c language --- delay
1. _nop_() is suitable for a small delay at the us level There is no empty statement in the standard C language. However, in C language programming of microcontrollers, it is often necessary to use several empty instructions to produce a short delay effect. This is easy to achieve in assembly language, just write a f
[Microcontroller]
Preparation for learning 51 single chip microcomputer
     Preparation: First, you need a circuit board, whether it is a learning board or a minimum system board, at least one, because the microcontroller is a practical technology, you can't play without a board. It's like you go to a driving school to learn how to drive, the instructor only tells you the theory, asks yo
[Microcontroller]
Preparation for learning 51 single chip microcomputer
C Programming for MCU<3>
Note: The following programs have been debugged by me and are successful. Purpose: The switch controls the buzzer sound and LED light display The procedure is as follows: #include reg52.h sbit S5=P1^5;      //switch control sbit k1=P3^5;      //buzzer sbit led1=P3^6;    //small light sbit led2=P3^7; void mai
[Microcontroller]
Getting Started with PIC Microcontrollers
The first step is to download a development environment. There are two types of PIC development environments: MPLAB IDE and MPLAB X IDE. X requires JAVA to be installed, so it is recommended to install the old version first. The following is the link: http://www.microchip.com/stellen ... 9&part=SW007002. After open
[Microcontroller]
Getting Started with PIC Microcontrollers
Research on the application of complex system based on single chip microcomputer with dual CPU
This paper introduces the characteristics of the MC145152-2 chip and analyzes the method of designing a 1 800 MHz frequency synthesizer using this chip. This frequency synthesizer has low phase noise and high frequency stability, and it will be widely used in mobile communications and other fields. Keywords: freq
[Industrial Control]
Research on the application of complex system based on single chip microcomputer with dual CPU
Design of running water lamp based on 51 single chip microcomputer
Three buttons: A button to start, B button to control different water flow speeds (low, medium and high), C button Design idea 1 (no interruption): The positive poles of the 8 LED lights are connected to the power supply, and the negative poles are connected to the microcontroller I/O port. Infinite loop: Set port
[Microcontroller]
Design of running water lamp based on 51 single chip microcomputer
51 MCU serial communication program set
Serial communication microcontroller program beep bit p3.7 ;buzzer definition         org 00h       jmp main         org 23h ;Serial interrupt entry address       jmp com_int ;Serial interrupt service routine ; ************** Main program starts *******************         org 30h   main: mov sp,#30h ;Set up stack  
[Microcontroller]
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号