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!
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
- Popular Resources
- Popular amplifiers
- Wireless Sensor Network Technology and Applications (Edited by Mou Si, Yin Hong, and Su Xing)
- Modern Electronic Technology Training Course (Edited by Yao Youfeng)
- Modern arc welding power supply and its control
- Small AC Servo Motor Control Circuit Design (by Masaru Ishijima; translated by Xue Liang and Zhu Jianjun, by Masaru Ishijima, Xue Liang, and Zhu Jianjun)
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- STMicroelectronics discloses its 2027-2028 financial model and path to achieve its 2030 goals
- 2024 China Automotive Charging and Battery Swapping Ecosystem Conference held in Taiyuan
- State-owned enterprises team up to invest in solid-state battery giant
- The evolution of electronic and electrical architecture is accelerating
- The first! National Automotive Chip Quality Inspection Center established
- BYD releases self-developed automotive chip using 4nm process, with a running score of up to 1.15 million
- GEODNET launches GEO-PULSE, a car GPS navigation device
- Should Chinese car companies develop their own high-computing chips?
- Infineon and Siemens combine embedded automotive software platform with microcontrollers to provide the necessary functions for next-generation SDVs
- Continental launches invisible biometric sensor display to monitor passengers' vital signs
- EEWORLD University Hall ---- A Global View of Analog IC Design
- Introduction to TOP2004 Universal Programmer
- It's still a boost problem. The unit price of lithium battery 4.2V is boosted to 50V
- Altium designer safety spacing setting problem
- If the lift table you buy has a hidden camera, but the manufacturer does not inform you in advance, do you make a profit or a loss?
- Series Feedback Regulated Power Supply
- How to solve the abnormal application of RS-485 automatic transceiver circuit?
- Ask for advice on purchasing SMD transformer
- DSP_28335_SCI_FIFO transceiver experiment
- Why are the punctuation marks in my code like this? Shouldn't they be like the one in the picture below?