网站空间怎么收费,官方网站welcome,网站建设的主要步骤有哪些,金华婺城区建设局网站模块简介 产品介绍
OLED (Organic Light-Emitting Diode)#xff1a;有机发光二极管又称为有机电激光显示#xff0c;OLED显示技术具有自发光的特性#xff0c;采用薄的有机材料涂层和玻璃基板#xff0c;当有电流通过时#xff0c;这些有机材料就会发光#xff0c;而且…模块简介 产品介绍
OLED (Organic Light-Emitting Diode)有机发光二极管又称为有机电激光显示OLED显示技术具有自发光的特性采用薄的有机材料涂层和玻璃基板当有电流通过时这些有机材料就会发光而且OLED显示屏幕可视角度大功耗低。OLED由于同时具备自发光、不需背光源(只上电是不会亮的驱动程序和接线正确才会点亮)、对比度高、厚度薄、视角广、反应速度快、可用于挠曲面板、使用温度范围广、结构及制程简单等优异之特性被认为是下一代的平面显示器新兴应用技术。
电气参数 模块尺寸 23.7 *23.8mm 电源电压 3.3-5.5V 驱动芯片 SSD1306
OLED屏幕原理
OLED本身是没有显存的他的现存是依赖SSD1306提供的而SSD1306提供一块显存。
SSD1306显存总共为128*64bit大小SSD1306将这些显存分成了8页。每页包含了128个字节。 单片机内部建立一个缓存(共128*8个字节每次修改的时候只是修改单片机上的缓存(实际上就是SRAM)修改完后一次性把STM32上的缓存数据写入到OLED的GRAM。这个方法也有坏处对于SRAM很小的单片机51系列就比较麻烦。
原理图 取字模
因为OLED屏显示的逻辑是根据一个十六进制数 一个点一个点的点亮对应值为1的像素点网上有很多取字模的网站这里推荐一个自己使用的取字模的网址
汉字字模在线 https://www.23bei.com/tool-223.html 参考代码
BUILD.gn
# Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the License);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an AS IS BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.import(//kernel/liteos_m/liteos.gni)
module_name get_path_info(rebase_path(.), name)
kernel_module(module_name){include_dirs [//drivers/hdf_core/framework/include/platform/,//drivers/hdf_core/framework/include/utils/,//drivers/hdf_core/framework/support/platform/include/gpio,//drivers/hdf_core/adapter/khdf/liteos_m/osal/include/,//drivers/hdf_core/framework/include/core/,//drivers/hdf_core/framework/include/osal/,//device/soc/esp/esp32/components/driver/include,//device/soc/esp/esp32/components/esp_adc_cal/include,//device/soc/esp/esp32/components/driver/esp32/include,]sources [ssd1306.c,ssd1306_fonts.c,ssd1306_demo.c,ssd1306_tests.c,]
}
ssd1306.c
#include ssd1306.h
#include math.h
#include stdlib.h
#include string.h // For memcpy#include stdio.h
#include unistd.h
#include cmsis_os2.h
#include stdio.h
#include cmsis_os2.h
#include ohos_run.h
#include esp_system.h
#include nvs_flash.h
#include esp_log.h
#include driver/gpio.h
#include driver/i2c.h#if defined(SSD1306_USE_I2C)#define SSD1306_I2C_IDX 0#define SSD1306_CTRL_CMD 0x00
#define SSD1306_CTRL_DATA 0x40
#define SSD1306_MASK_CONT (0x17)void ssd1306_Reset(void) {/* for I2C - do nothing */
}void HAL_Delay(uint32_t ms)
{usleep(ms * 1000);
}static uint32_t ssd1306_SendData(uint8_t* data, size_t size)
{int i;i2c_cmd_handle_t cmd_handle i2c_cmd_link_create();i2c_master_start(cmd_handle);i2c_master_write_byte(cmd_handle, SSD1306_I2C_ADDR, true);for(i 0; i size; i ){i2c_master_write_byte(cmd_handle, data[i], true);}i2c_master_stop(cmd_handle);esp_err_t error i2c_master_cmd_begin(I2C_NUM_0,cmd_handle,100/portTICK_PERIOD_MS);i2c_cmd_link_delete(cmd_handle);return error;
}static uint32_t ssd1306_WiteByte(uint8_t regAddr, uint8_t byte)
{uint8_t buffer[] {regAddr, byte};return ssd1306_SendData(buffer, sizeof(buffer));
}// Send a byte to the command register
void ssd1306_WriteCommand(uint8_t byte) {ssd1306_WiteByte(SSD1306_CTRL_CMD, byte);
}// Send data
void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) {uint8_t data[SSD1306_WIDTH * 2] {0};for (size_t i 0; i buff_size; i) {data[i*2] SSD1306_CTRL_DATA | SSD1306_MASK_CONT;data[i*21] buffer[i];}data[(buff_size - 1) * 2] SSD1306_CTRL_DATA;ssd1306_SendData(data, sizeof(data));
}#elif defined(SSD1306_USE_SPI)void ssd1306_Reset(void) {// CS High (not selected)HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET);// Reset the OLEDHAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_RESET);HAL_Delay(10);HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_SET);HAL_Delay(10);
}// Send a byte to the command register
void ssd1306_WriteCommand(uint8_t byte) {HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLEDHAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_RESET); // commandHAL_SPI_Transmit(SSD1306_SPI_PORT, (uint8_t *) byte, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED
}// Send data
void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) {HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLEDHAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_SET); // dataHAL_SPI_Transmit(SSD1306_SPI_PORT, buffer, buff_size, HAL_MAX_DELAY);HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED
}#else
#error You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro
#endif// Screenbuffer
static uint8_t SSD1306_Buffer[SSD1306_BUFFER_SIZE];// Screen object
static SSD1306_t SSD1306;/* Fills the Screenbuffer with values from a given buffer of a fixed length */
SSD1306_Error_t ssd1306_FillBuffer(uint8_t* buf, uint32_t len) {SSD1306_Error_t ret SSD1306_ERR;if (len SSD1306_BUFFER_SIZE) {memcpy(SSD1306_Buffer,buf,len);ret SSD1306_OK;}return ret;
}// Initialize the oled screen
void ssd1306_Init(void) {// Reset OLEDssd1306_Reset();// Wait for the screen to bootHAL_Delay(100);// Init OLEDssd1306_SetDisplayOn(0); //display offssd1306_WriteCommand(0x20); //Set Memory Addressing Modessd1306_WriteCommand(0x00); // 00b,Horizontal Addressing Mode; 01b,Vertical Addressing Mode;// 10b,Page Addressing Mode (RESET); 11b,Invalidssd1306_WriteCommand(0xB0); //Set Page Start Address for Page Addressing Mode,0-7#ifdef SSD1306_MIRROR_VERTssd1306_WriteCommand(0xC0); // Mirror vertically
#elsessd1306_WriteCommand(0xC8); //Set COM Output Scan Direction
#endifssd1306_WriteCommand(0x00); //---set low column addressssd1306_WriteCommand(0x10); //---set high column addressssd1306_WriteCommand(0x40); //--set start line address - CHECKssd1306_SetContrast(0xFF);#ifdef SSD1306_MIRROR_HORIZssd1306_WriteCommand(0xA0); // Mirror horizontally
#elsessd1306_WriteCommand(0xA1); //--set segment re-map 0 to 127 - CHECK
#endif#ifdef SSD1306_INVERSE_COLORssd1306_WriteCommand(0xA7); //--set inverse color
#elsessd1306_WriteCommand(0xA6); //--set normal color
#endif// Set multiplex ratio.
#if (SSD1306_HEIGHT 128)// Found in the Luma Python lib for SH1106.ssd1306_WriteCommand(0xFF);
#elsessd1306_WriteCommand(0xA8); //--set multiplex ratio(1 to 64) - CHECK
#endif#if (SSD1306_HEIGHT 32)ssd1306_WriteCommand(0x1F); //
#elif (SSD1306_HEIGHT 64)ssd1306_WriteCommand(0x3F); //
#elif (SSD1306_HEIGHT 128)ssd1306_WriteCommand(0x3F); // Seems to work for 128px high displays too.
#else
#error Only 32, 64, or 128 lines of height are supported!
#endifssd1306_WriteCommand(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM contentssd1306_WriteCommand(0xD3); //-set display offset - CHECKssd1306_WriteCommand(0x00); //-not offsetssd1306_WriteCommand(0xD5); //--set display clock divide ratio/oscillator frequencyssd1306_WriteCommand(0xF0); //--set divide ratiossd1306_WriteCommand(0xD9); //--set pre-charge periodssd1306_WriteCommand(0x11); // 0x22 by defaultssd1306_WriteCommand(0xDA); //--set com pins hardware configuration - CHECK
#if (SSD1306_HEIGHT 32)ssd1306_WriteCommand(0x02);
#elif (SSD1306_HEIGHT 64)ssd1306_WriteCommand(0x12);
#elif (SSD1306_HEIGHT 128)ssd1306_WriteCommand(0x12);
#else
#error Only 32, 64, or 128 lines of height are supported!
#endifssd1306_WriteCommand(0xDB); //--set vcomhssd1306_WriteCommand(0x30); //0x20,0.77xVcc, 0x30,0.83xVccssd1306_WriteCommand(0x8D); //--set DC-DC enablessd1306_WriteCommand(0x14); //ssd1306_SetDisplayOn(1); //--turn on SSD1306 panel// Clear screenssd1306_Fill(Black);// Flush buffer to screenssd1306_UpdateScreen();// Set default values for screen objectSSD1306.CurrentX 0;SSD1306.CurrentY 0;SSD1306.Initialized 1;
}// Fill the whole screen with the given color
void ssd1306_Fill(SSD1306_COLOR color) {/* Set memory */uint32_t i;for(i 0; i sizeof(SSD1306_Buffer); i) {SSD1306_Buffer[i] (color Black) ? 0x00 : 0xFF;}
}// Write the screenbuffer with changed to the screen
void ssd1306_UpdateScreen(void) {// Write data to each page of RAM. Number of pages// depends on the screen height://// * 32px 4 pages// * 64px 8 pages// * 128px 16 pagesuint8_t cmd[] {0X21, // 设置列起始和结束地址0X00, // 列起始地址 00X7F, // 列终止地址 1270X22, // 设置页起始和结束地址0X00, // 页起始地址 00X07, // 页终止地址 7};uint32_t count 0;uint8_t data[sizeof(cmd)*2 SSD1306_BUFFER_SIZE 1] {};// copy cmdfor (uint32_t i 0; i sizeof(cmd)/sizeof(cmd[0]); i) {data[count] SSD1306_CTRL_CMD | SSD1306_MASK_CONT;data[count] cmd[i];}// copy frame datadata[count] SSD1306_CTRL_DATA;memcpy(data[count], SSD1306_Buffer, sizeof(SSD1306_Buffer));count sizeof(SSD1306_Buffer);// send to i2c busuint32_t retval ssd1306_SendData(data, count);if (retval ! 0) {printf(ssd1306_UpdateScreen send frame data filed: %d!\r\n, retval);}
}// Draw one pixel in the screenbuffer
// X X Coordinate
// Y Y Coordinate
// color Pixel color
void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color) {if(x SSD1306_WIDTH || y SSD1306_HEIGHT) {// Dont write outside the bufferreturn;}// Check if pixel should be invertedif(SSD1306.Inverted) {color (SSD1306_COLOR)!color;}// Draw in the right colorif(color White) {SSD1306_Buffer[x (y / 8) * SSD1306_WIDTH] | 1 (y % 8);} else {SSD1306_Buffer[x (y / 8) * SSD1306_WIDTH] ~(1 (y % 8));}
}// Draw 1 char to the screen buffer
// ch char om weg te schrijven
// Font Font waarmee we gaan schrijven
// color Black or White
char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color) {uint32_t i, b, j;// Check if character is validif (ch 32 || ch 126)return 0;// Check remaining space on current lineif (SSD1306_WIDTH (SSD1306.CurrentX Font.FontWidth) ||SSD1306_HEIGHT (SSD1306.CurrentY Font.FontHeight)){// Not enough space on current linereturn 0;}// Use the font to writefor(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) {ssd1306_DrawPixel(SSD1306.CurrentX j, (SSD1306.CurrentY i), (SSD1306_COLOR) color);} else {ssd1306_DrawPixel(SSD1306.CurrentX j, (SSD1306.CurrentY i), (SSD1306_COLOR)!color);}}}// The current space is now takenSSD1306.CurrentX Font.FontWidth;// Return written char for validationreturn ch;
}// Write full string to screenbuffer
char ssd1306_DrawString(char* str, FontDef Font, SSD1306_COLOR color) {// Write until null-bytewhile (*str) {if (ssd1306_DrawChar(*str, Font, color) ! *str) {// Char could not be writtenreturn *str;}// Next charstr;}// Everything okreturn *str;
}// Position the cursor
void ssd1306_SetCursor(uint8_t x, uint8_t y) {SSD1306.CurrentX x;SSD1306.CurrentY y;
}// Draw line by Bresenhems algorithm
void ssd1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) {int32_t deltaX abs(x2 - x1);int32_t deltaY abs(y2 - y1);int32_t signX ((x1 x2) ? 1 : -1);int32_t signY ((y1 y2) ? 1 : -1);int32_t error deltaX - deltaY;int32_t error2;ssd1306_DrawPixel(x2, y2, color);while((x1 ! x2) || (y1 ! y2)){ssd1306_DrawPixel(x1, y1, color);error2 error * 2;if(error2 -deltaY){error - deltaY;x1 signX;}else{/*nothing to do*/}if(error2 deltaX){error deltaX;y1 signY;}else{/*nothing to do*/}}return;
}
//Draw polyline
void ssd1306_DrawPolyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color) {uint16_t i;if(par_vertex ! 0){for(i 1; i par_size; i){ssd1306_DrawLine(par_vertex[i - 1].x, par_vertex[i - 1].y, par_vertex[i].x, par_vertex[i].y, color);}}else{/*nothing to do*/}return;
}
/*Convert Degrees to Radians*/
static float ssd1306_DegToRad(float par_deg) {return par_deg * 3.14 / 180.0;
}
/*Normalize degree to [0;360]*/
static uint16_t ssd1306_NormalizeTo0_360(uint16_t par_deg) {uint16_t loc_angle;if(par_deg 360){loc_angle par_deg;}else{loc_angle par_deg % 360;loc_angle ((par_deg ! 0)?par_deg:360);}return loc_angle;
}
/*DrawArc. Draw angle is beginning from 4 quart of trigonometric circle (3pi/2)* start_angle in degree* sweep in degree*/
void ssd1306_DrawArc(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color) {#define CIRCLE_APPROXIMATION_SEGMENTS 36float approx_degree;uint32_t approx_segments;uint8_t xp1,xp2;uint8_t yp1,yp2;uint32_t count 0;uint32_t loc_sweep 0;float rad;loc_sweep ssd1306_NormalizeTo0_360(sweep);count (ssd1306_NormalizeTo0_360(start_angle) * CIRCLE_APPROXIMATION_SEGMENTS) / 360;approx_segments (loc_sweep * CIRCLE_APPROXIMATION_SEGMENTS) / 360;approx_degree loc_sweep / (float)approx_segments;while(count approx_segments){rad ssd1306_DegToRad(count*approx_degree);xp1 x (int8_t)(sin(rad)*radius);yp1 y (int8_t)(cos(rad)*radius);count;if(count ! approx_segments){rad ssd1306_DegToRad(count*approx_degree);}else{rad ssd1306_DegToRad(loc_sweep);}xp2 x (int8_t)(sin(rad)*radius);yp2 y (int8_t)(cos(rad)*radius);ssd1306_DrawLine(xp1,yp1,xp2,yp2,color);}return;
}
//Draw circle by Bresenhems algorithm
void ssd1306_DrawCircle(uint8_t par_x,uint8_t par_y,uint8_t par_r,SSD1306_COLOR par_color) {int32_t x -par_r;int32_t y 0;int32_t err 2 - 2 * par_r;int32_t e2;if (par_x SSD1306_WIDTH || par_y SSD1306_HEIGHT) {return;}do {ssd1306_DrawPixel(par_x - x, par_y y, par_color);ssd1306_DrawPixel(par_x x, par_y y, par_color);ssd1306_DrawPixel(par_x x, par_y - y, par_color);ssd1306_DrawPixel(par_x - x, par_y - y, par_color);e2 err;if (e2 y) {y;err err (y * 2 1);if(-x y e2 x) {e2 0;}else{/*nothing to do*/}}else{/*nothing to do*/}if(e2 x) {x;err err (x * 2 1);}else{/*nothing to do*/}} while(x 0);return;
}//Draw rectangle
void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) {ssd1306_DrawLine(x1,y1,x2,y1,color);ssd1306_DrawLine(x2,y1,x2,y2,color);ssd1306_DrawLine(x2,y2,x1,y2,color);ssd1306_DrawLine(x1,y2,x1,y1,color);return;
}void ssd1306_DrawBitmap(const uint8_t* bitmap, uint32_t size)
{uint8_t rows size * 8 / SSD1306_WIDTH;if (rows SSD1306_HEIGHT) {rows SSD1306_HEIGHT;}for (uint8_t y 0; y rows; y) {for (uint8_t x 0; x SSD1306_WIDTH; x) {uint8_t byte bitmap[(y * SSD1306_WIDTH / 8) (x / 8)];uint8_t bit byte (0x80 (x % 8));ssd1306_DrawPixel(x, y, bit ? White : Black);}}
}void ssd1306_DrawRegion(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* data, uint32_t size, uint32_t stride)
{if (x w SSD1306_WIDTH || y h SSD1306_HEIGHT || w * h 0) {printf(%dx%d %d,%d out of range or invalid!\r\n, w, h, x, y);return;}w (w SSD1306_WIDTH ? w : SSD1306_WIDTH);h (h SSD1306_HEIGHT ? h : SSD1306_HEIGHT);stride (stride 0 ? w : stride);uint8_t rows size * 8 / stride;for (uint8_t i 0; i rows; i) {uint32_t base i * stride / 8;for (uint8_t j 0; j w; j) {uint32_t idx base (j / 8);uint8_t byte idx size ? data[idx] : 0;uint8_t bit byte (0x80 (j % 8));ssd1306_DrawPixel(x j, y i, bit ? White : Black);}}
}void ssd1306_SetContrast(const uint8_t value) {const uint8_t kSetContrastControlRegister 0x81;ssd1306_WriteCommand(kSetContrastControlRegister);ssd1306_WriteCommand(value);
}void ssd1306_SetDisplayOn(const uint8_t on) {uint8_t value;if (on) {value 0xAF; // Display onSSD1306.DisplayOn 1;} else {value 0xAE; // Display offSSD1306.DisplayOn 0;}ssd1306_WriteCommand(value);
}uint8_t ssd1306_GetDisplayOn() {return SSD1306.DisplayOn;
}
ssd1306.h
#include ssd1306.h
#include math.h
#include stdlib.h
#include string.h // For memcpy#include stdio.h
#include unistd.h
#include cmsis_os2.h
#include stdio.h
#include cmsis_os2.h
#include ohos_run.h
#include esp_system.h
#include nvs_flash.h
#include esp_log.h
#include driver/gpio.h
#include driver/i2c.h#if defined(SSD1306_USE_I2C)#define SSD1306_I2C_IDX 0#define SSD1306_CTRL_CMD 0x00
#define SSD1306_CTRL_DATA 0x40
#define SSD1306_MASK_CONT (0x17)void ssd1306_Reset(void) {/* for I2C - do nothing */
}void HAL_Delay(uint32_t ms)
{usleep(ms * 1000);
}static uint32_t ssd1306_SendData(uint8_t* data, size_t size)
{int i;i2c_cmd_handle_t cmd_handle i2c_cmd_link_create();i2c_master_start(cmd_handle);i2c_master_write_byte(cmd_handle, SSD1306_I2C_ADDR, true);for(i 0; i size; i ){i2c_master_write_byte(cmd_handle, data[i], true);}i2c_master_stop(cmd_handle);esp_err_t error i2c_master_cmd_begin(I2C_NUM_0,cmd_handle,100/portTICK_PERIOD_MS);i2c_cmd_link_delete(cmd_handle);return error;
}static uint32_t ssd1306_WiteByte(uint8_t regAddr, uint8_t byte)
{uint8_t buffer[] {regAddr, byte};return ssd1306_SendData(buffer, sizeof(buffer));
}// Send a byte to the command register
void ssd1306_WriteCommand(uint8_t byte) {ssd1306_WiteByte(SSD1306_CTRL_CMD, byte);
}// Send data
void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) {uint8_t data[SSD1306_WIDTH * 2] {0};for (size_t i 0; i buff_size; i) {data[i*2] SSD1306_CTRL_DATA | SSD1306_MASK_CONT;data[i*21] buffer[i];}data[(buff_size - 1) * 2] SSD1306_CTRL_DATA;ssd1306_SendData(data, sizeof(data));
}#elif defined(SSD1306_USE_SPI)void ssd1306_Reset(void) {// CS High (not selected)HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET);// Reset the OLEDHAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_RESET);HAL_Delay(10);HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_SET);HAL_Delay(10);
}// Send a byte to the command register
void ssd1306_WriteCommand(uint8_t byte) {HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLEDHAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_RESET); // commandHAL_SPI_Transmit(SSD1306_SPI_PORT, (uint8_t *) byte, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED
}// Send data
void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) {HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLEDHAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_SET); // dataHAL_SPI_Transmit(SSD1306_SPI_PORT, buffer, buff_size, HAL_MAX_DELAY);HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED
}#else
#error You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro
#endif// Screenbuffer
static uint8_t SSD1306_Buffer[SSD1306_BUFFER_SIZE];// Screen object
static SSD1306_t SSD1306;/* Fills the Screenbuffer with values from a given buffer of a fixed length */
SSD1306_Error_t ssd1306_FillBuffer(uint8_t* buf, uint32_t len) {SSD1306_Error_t ret SSD1306_ERR;if (len SSD1306_BUFFER_SIZE) {memcpy(SSD1306_Buffer,buf,len);ret SSD1306_OK;}return ret;
}// Initialize the oled screen
void ssd1306_Init(void) {// Reset OLEDssd1306_Reset();// Wait for the screen to bootHAL_Delay(100);// Init OLEDssd1306_SetDisplayOn(0); //display offssd1306_WriteCommand(0x20); //Set Memory Addressing Modessd1306_WriteCommand(0x00); // 00b,Horizontal Addressing Mode; 01b,Vertical Addressing Mode;// 10b,Page Addressing Mode (RESET); 11b,Invalidssd1306_WriteCommand(0xB0); //Set Page Start Address for Page Addressing Mode,0-7#ifdef SSD1306_MIRROR_VERTssd1306_WriteCommand(0xC0); // Mirror vertically
#elsessd1306_WriteCommand(0xC8); //Set COM Output Scan Direction
#endifssd1306_WriteCommand(0x00); //---set low column addressssd1306_WriteCommand(0x10); //---set high column addressssd1306_WriteCommand(0x40); //--set start line address - CHECKssd1306_SetContrast(0xFF);#ifdef SSD1306_MIRROR_HORIZssd1306_WriteCommand(0xA0); // Mirror horizontally
#elsessd1306_WriteCommand(0xA1); //--set segment re-map 0 to 127 - CHECK
#endif#ifdef SSD1306_INVERSE_COLORssd1306_WriteCommand(0xA7); //--set inverse color
#elsessd1306_WriteCommand(0xA6); //--set normal color
#endif// Set multiplex ratio.
#if (SSD1306_HEIGHT 128)// Found in the Luma Python lib for SH1106.ssd1306_WriteCommand(0xFF);
#elsessd1306_WriteCommand(0xA8); //--set multiplex ratio(1 to 64) - CHECK
#endif#if (SSD1306_HEIGHT 32)ssd1306_WriteCommand(0x1F); //
#elif (SSD1306_HEIGHT 64)ssd1306_WriteCommand(0x3F); //
#elif (SSD1306_HEIGHT 128)ssd1306_WriteCommand(0x3F); // Seems to work for 128px high displays too.
#else
#error Only 32, 64, or 128 lines of height are supported!
#endifssd1306_WriteCommand(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM contentssd1306_WriteCommand(0xD3); //-set display offset - CHECKssd1306_WriteCommand(0x00); //-not offsetssd1306_WriteCommand(0xD5); //--set display clock divide ratio/oscillator frequencyssd1306_WriteCommand(0xF0); //--set divide ratiossd1306_WriteCommand(0xD9); //--set pre-charge periodssd1306_WriteCommand(0x11); // 0x22 by defaultssd1306_WriteCommand(0xDA); //--set com pins hardware configuration - CHECK
#if (SSD1306_HEIGHT 32)ssd1306_WriteCommand(0x02);
#elif (SSD1306_HEIGHT 64)ssd1306_WriteCommand(0x12);
#elif (SSD1306_HEIGHT 128)ssd1306_WriteCommand(0x12);
#else
#error Only 32, 64, or 128 lines of height are supported!
#endifssd1306_WriteCommand(0xDB); //--set vcomhssd1306_WriteCommand(0x30); //0x20,0.77xVcc, 0x30,0.83xVccssd1306_WriteCommand(0x8D); //--set DC-DC enablessd1306_WriteCommand(0x14); //ssd1306_SetDisplayOn(1); //--turn on SSD1306 panel// Clear screenssd1306_Fill(Black);// Flush buffer to screenssd1306_UpdateScreen();// Set default values for screen objectSSD1306.CurrentX 0;SSD1306.CurrentY 0;SSD1306.Initialized 1;
}// Fill the whole screen with the given color
void ssd1306_Fill(SSD1306_COLOR color) {/* Set memory */uint32_t i;for(i 0; i sizeof(SSD1306_Buffer); i) {SSD1306_Buffer[i] (color Black) ? 0x00 : 0xFF;}
}// Write the screenbuffer with changed to the screen
void ssd1306_UpdateScreen(void) {// Write data to each page of RAM. Number of pages// depends on the screen height://// * 32px 4 pages// * 64px 8 pages// * 128px 16 pagesuint8_t cmd[] {0X21, // 设置列起始和结束地址0X00, // 列起始地址 00X7F, // 列终止地址 1270X22, // 设置页起始和结束地址0X00, // 页起始地址 00X07, // 页终止地址 7};uint32_t count 0;uint8_t data[sizeof(cmd)*2 SSD1306_BUFFER_SIZE 1] {};// copy cmdfor (uint32_t i 0; i sizeof(cmd)/sizeof(cmd[0]); i) {data[count] SSD1306_CTRL_CMD | SSD1306_MASK_CONT;data[count] cmd[i];}// copy frame datadata[count] SSD1306_CTRL_DATA;memcpy(data[count], SSD1306_Buffer, sizeof(SSD1306_Buffer));count sizeof(SSD1306_Buffer);// send to i2c busuint32_t retval ssd1306_SendData(data, count);if (retval ! 0) {printf(ssd1306_UpdateScreen send frame data filed: %d!\r\n, retval);}
}// Draw one pixel in the screenbuffer
// X X Coordinate
// Y Y Coordinate
// color Pixel color
void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color) {if(x SSD1306_WIDTH || y SSD1306_HEIGHT) {// Dont write outside the bufferreturn;}// Check if pixel should be invertedif(SSD1306.Inverted) {color (SSD1306_COLOR)!color;}// Draw in the right colorif(color White) {SSD1306_Buffer[x (y / 8) * SSD1306_WIDTH] | 1 (y % 8);} else {SSD1306_Buffer[x (y / 8) * SSD1306_WIDTH] ~(1 (y % 8));}
}// Draw 1 char to the screen buffer
// ch char om weg te schrijven
// Font Font waarmee we gaan schrijven
// color Black or White
char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color) {uint32_t i, b, j;// Check if character is validif (ch 32 || ch 126)return 0;// Check remaining space on current lineif (SSD1306_WIDTH (SSD1306.CurrentX Font.FontWidth) ||SSD1306_HEIGHT (SSD1306.CurrentY Font.FontHeight)){// Not enough space on current linereturn 0;}// Use the font to writefor(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) {ssd1306_DrawPixel(SSD1306.CurrentX j, (SSD1306.CurrentY i), (SSD1306_COLOR) color);} else {ssd1306_DrawPixel(SSD1306.CurrentX j, (SSD1306.CurrentY i), (SSD1306_COLOR)!color);}}}// The current space is now takenSSD1306.CurrentX Font.FontWidth;// Return written char for validationreturn ch;
}// Write full string to screenbuffer
char ssd1306_DrawString(char* str, FontDef Font, SSD1306_COLOR color) {// Write until null-bytewhile (*str) {if (ssd1306_DrawChar(*str, Font, color) ! *str) {// Char could not be writtenreturn *str;}// Next charstr;}// Everything okreturn *str;
}// Position the cursor
void ssd1306_SetCursor(uint8_t x, uint8_t y) {SSD1306.CurrentX x;SSD1306.CurrentY y;
}// Draw line by Bresenhems algorithm
void ssd1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) {int32_t deltaX abs(x2 - x1);int32_t deltaY abs(y2 - y1);int32_t signX ((x1 x2) ? 1 : -1);int32_t signY ((y1 y2) ? 1 : -1);int32_t error deltaX - deltaY;int32_t error2;ssd1306_DrawPixel(x2, y2, color);while((x1 ! x2) || (y1 ! y2)){ssd1306_DrawPixel(x1, y1, color);error2 error * 2;if(error2 -deltaY){error - deltaY;x1 signX;}else{/*nothing to do*/}if(error2 deltaX){error deltaX;y1 signY;}else{/*nothing to do*/}}return;
}
//Draw polyline
void ssd1306_DrawPolyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color) {uint16_t i;if(par_vertex ! 0){for(i 1; i par_size; i){ssd1306_DrawLine(par_vertex[i - 1].x, par_vertex[i - 1].y, par_vertex[i].x, par_vertex[i].y, color);}}else{/*nothing to do*/}return;
}
/*Convert Degrees to Radians*/
static float ssd1306_DegToRad(float par_deg) {return par_deg * 3.14 / 180.0;
}
/*Normalize degree to [0;360]*/
static uint16_t ssd1306_NormalizeTo0_360(uint16_t par_deg) {uint16_t loc_angle;if(par_deg 360){loc_angle par_deg;}else{loc_angle par_deg % 360;loc_angle ((par_deg ! 0)?par_deg:360);}return loc_angle;
}
/*DrawArc. Draw angle is beginning from 4 quart of trigonometric circle (3pi/2)* start_angle in degree* sweep in degree*/
void ssd1306_DrawArc(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color) {#define CIRCLE_APPROXIMATION_SEGMENTS 36float approx_degree;uint32_t approx_segments;uint8_t xp1,xp2;uint8_t yp1,yp2;uint32_t count 0;uint32_t loc_sweep 0;float rad;loc_sweep ssd1306_NormalizeTo0_360(sweep);count (ssd1306_NormalizeTo0_360(start_angle) * CIRCLE_APPROXIMATION_SEGMENTS) / 360;approx_segments (loc_sweep * CIRCLE_APPROXIMATION_SEGMENTS) / 360;approx_degree loc_sweep / (float)approx_segments;while(count approx_segments){rad ssd1306_DegToRad(count*approx_degree);xp1 x (int8_t)(sin(rad)*radius);yp1 y (int8_t)(cos(rad)*radius);count;if(count ! approx_segments){rad ssd1306_DegToRad(count*approx_degree);}else{rad ssd1306_DegToRad(loc_sweep);}xp2 x (int8_t)(sin(rad)*radius);yp2 y (int8_t)(cos(rad)*radius);ssd1306_DrawLine(xp1,yp1,xp2,yp2,color);}return;
}
//Draw circle by Bresenhems algorithm
void ssd1306_DrawCircle(uint8_t par_x,uint8_t par_y,uint8_t par_r,SSD1306_COLOR par_color) {int32_t x -par_r;int32_t y 0;int32_t err 2 - 2 * par_r;int32_t e2;if (par_x SSD1306_WIDTH || par_y SSD1306_HEIGHT) {return;}do {ssd1306_DrawPixel(par_x - x, par_y y, par_color);ssd1306_DrawPixel(par_x x, par_y y, par_color);ssd1306_DrawPixel(par_x x, par_y - y, par_color);ssd1306_DrawPixel(par_x - x, par_y - y, par_color);e2 err;if (e2 y) {y;err err (y * 2 1);if(-x y e2 x) {e2 0;}else{/*nothing to do*/}}else{/*nothing to do*/}if(e2 x) {x;err err (x * 2 1);}else{/*nothing to do*/}} while(x 0);return;
}//Draw rectangle
void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) {ssd1306_DrawLine(x1,y1,x2,y1,color);ssd1306_DrawLine(x2,y1,x2,y2,color);ssd1306_DrawLine(x2,y2,x1,y2,color);ssd1306_DrawLine(x1,y2,x1,y1,color);return;
}void ssd1306_DrawBitmap(const uint8_t* bitmap, uint32_t size)
{uint8_t rows size * 8 / SSD1306_WIDTH;if (rows SSD1306_HEIGHT) {rows SSD1306_HEIGHT;}for (uint8_t y 0; y rows; y) {for (uint8_t x 0; x SSD1306_WIDTH; x) {uint8_t byte bitmap[(y * SSD1306_WIDTH / 8) (x / 8)];uint8_t bit byte (0x80 (x % 8));ssd1306_DrawPixel(x, y, bit ? White : Black);}}
}void ssd1306_DrawRegion(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* data, uint32_t size, uint32_t stride)
{if (x w SSD1306_WIDTH || y h SSD1306_HEIGHT || w * h 0) {printf(%dx%d %d,%d out of range or invalid!\r\n, w, h, x, y);return;}w (w SSD1306_WIDTH ? w : SSD1306_WIDTH);h (h SSD1306_HEIGHT ? h : SSD1306_HEIGHT);stride (stride 0 ? w : stride);uint8_t rows size * 8 / stride;for (uint8_t i 0; i rows; i) {uint32_t base i * stride / 8;for (uint8_t j 0; j w; j) {uint32_t idx base (j / 8);uint8_t byte idx size ? data[idx] : 0;uint8_t bit byte (0x80 (j % 8));ssd1306_DrawPixel(x j, y i, bit ? White : Black);}}
}void ssd1306_SetContrast(const uint8_t value) {const uint8_t kSetContrastControlRegister 0x81;ssd1306_WriteCommand(kSetContrastControlRegister);ssd1306_WriteCommand(value);
}void ssd1306_SetDisplayOn(const uint8_t on) {uint8_t value;if (on) {value 0xAF; // Display onSSD1306.DisplayOn 1;} else {value 0xAE; // Display offSSD1306.DisplayOn 0;}ssd1306_WriteCommand(value);
}uint8_t ssd1306_GetDisplayOn() {return SSD1306.DisplayOn;
} ssd1306_demo.c
/** Copyright (c) 2020, HiHope Community.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions are met:** 1. Redistributions of source code must retain the above copyright notice, this* list of conditions and the following disclaimer.** 2. Redistributions in binary form must reproduce the above copyright notice,* this list of conditions and the following disclaimer in the documentation* and/or other materials provided with the distribution.** 3. Neither the name of the copyright holder nor the names of its* contributors may be used to endorse or promote products derived from* this software without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/#include stdio.h
#include unistd.h#include ohos_init.h
#include cmsis_os2.h
#include stdio.h
#include cmsis_os2.h
#include ohos_run.h
#include esp_system.h
#include nvs_flash.h
#include esp_log.h
#include driver/gpio.h
#include driver/i2c.h#include ssd1306.h
#include ssd1306_tests.h#define OLED_I2C_BAUDRATE 400*1000void TestGetTick(void)
{}/*** 汉字字模在线 https://www.23bei.com/tool-223.html* 数据排列从左到右从上到下* 取模方式横向8位左高位
**/
void TestDrawChinese1(void)
{const uint32_t W 16, H 16;uint8_t fonts[][32] {/* [字库][HZK1616宋体] [数据排列]:从左到右从上到下 [取模方式]:横向8点左高位 [正负反色]:否 [去掉重复后]共6个字符[总字符库] 鸿蒙实验箱*/{/*-- ID:0,字符: ,ASCII编码:A1A1,对应字:宽x高16x16,画布:宽W16 高H16,共32字节*/0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,},{/*-- ID:1,字符:鸿,ASCII编码:BAE8,对应字:宽x高16x16,画布:宽W16 高H16,共32字节*/0x40,0x20,0x30,0x48,0x10,0xFC,0x02,0x88,0x9F,0xA8,0x64,0x88,0x24,0xA8,0x04,0x90,0x14,0x84,0x14,0xFE,0xE7,0x04,0x3C,0x24,0x29,0xF4,0x20,0x04,0x20,0x14,0x20,0x08,},{/*-- ID:2,字符:蒙,ASCII编码:C3C9,对应字:宽x高16x16,画布:宽W16 高H16,共32字节*/0x04,0x48,0x7F,0xFC,0x04,0x40,0x7F,0xFE,0x40,0x02,0x8F,0xE4,0x00,0x00,0x7F,0xFC,0x06,0x10,0x3B,0x30,0x05,0xC0,0x1A,0xA0,0x64,0x90,0x18,0x8E,0x62,0x84,0x01,0x00,},{/*-- ID:3,字符:实,ASCII编码:CAB5,对应字:宽x高16x16,画布:宽W16 高H16,共32字节*/0x02,0x00,0x01,0x00,0x7F,0xFE,0x48,0x02,0x86,0x84,0x02,0x80,0x10,0x80,0x0C,0x80,0x04,0x84,0xFF,0xFE,0x01,0x00,0x01,0x40,0x02,0x20,0x04,0x10,0x18,0x0C,0x60,0x04,},{/*-- ID:4,字符:验,ASCII编码:D1E9,对应字:宽x高16x16,画布:宽W16 高H16,共32字节*/0x08,0x40,0xFC,0x40,0x08,0xA0,0x48,0xA0,0x49,0x10,0x4A,0x0E,0x4D,0xF4,0x48,0x00,0x7C,0x48,0x06,0x48,0x05,0x48,0x1D,0x50,0xE5,0x10,0x44,0x24,0x17,0xFE,0x08,0x00,},{/*-- ID:5,字符:箱,ASCII编码:CFE4,对应字:宽x高16x16,画布:宽W16 高H16,共32字节*/0x12,0x44,0x1F,0x7E,0x28,0xA0,0x45,0x10,0x08,0x04,0x08,0xFE,0xFE,0x84,0x08,0x84,0x18,0xFC,0x1C,0x84,0x2A,0x84,0x28,0xFC,0x48,0x84,0x88,0x84,0x08,0xFC,0x08,0x84}};ssd1306_Fill(Black);for (size_t i 0; i sizeof(fonts)/sizeof(fonts[0]); i) {ssd1306_DrawRegion(i * W, 18, W, H, fonts[i], sizeof(fonts[0]), W);}ssd1306_UpdateScreen();sleep(1);
}void TestDrawChinese2(void)
{const uint32_t W 12, H 12, S 16;/* [字库][HZK1212宋体] [数据排列]:从左到右从上到下 [取模方式]:横向8点左高位 [正负反色]:否 [去掉重复后]共9个字符[总字符库] 屏案例*/uint8_t fonts[][24] {{/*-- ID:0,字符: ,ASCII编码:A1A1,对应字:宽x高12x12,画布:宽W16 高H12,共24字节*/0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,},{/*-- ID:1,字符:,ASCII编码:A3AD,对应字:宽x高12x12,画布:宽W16 高H12,共24字节*/0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,},{/*-- ID:2,字符:,ASCII编码:A3CF,对应字:宽x高12x12,画布:宽W16 高H12,共24字节*/0x00,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,},{/*-- ID:3,字符:,ASCII编码:A3CC,对应字:宽x高12x12,画布:宽W16 高H12,共24字节*/0x00,0x00,0x78,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x31,0x00,0x33,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,},{/*-- ID:4,字符:,ASCII编码:A3C5,对应字:宽x高12x12,画布:宽W16 高H12,共24字节*/0x00,0x00,0x7F,0x00,0x33,0x00,0x31,0x00,0x34,0x00,0x3C,0x00,0x34,0x00,0x31,0x00,0x33,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,},{/*-- ID:5,字符:,ASCII编码:A3C4,对应字:宽x高12x12,画布:宽W16 高H12,共24字节*/0x00,0x00,0x7C,0x00,0x36,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x36,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,},{/*-- ID:6,字符:屏,ASCII编码:C6C1,对应字:宽x高12x12,画布:宽W16 高H12,共24字节*/0x7F,0xE0,0x40,0x20,0x7F,0xE0,0x48,0x80,0x45,0x00,0x5F,0xE0,0x44,0x80,0x7F,0xF0,0x44,0x80,0x44,0x80,0x48,0x80,0x90,0x80,},{/*-- ID:7,字符:案,ASCII编码:B0B8,对应字:宽x高12x12,画布:宽W16 高H12,共24字节*/0x04,0x00,0x7F,0xF0,0xC8,0x20,0x7F,0xF0,0x11,0x00,0x0E,0x00,0x71,0xC0,0x04,0x00,0xFF,0xF0,0x15,0x00,0x24,0xC0,0xC4,0x30,},{/*-- ID:8,字符:例,ASCII编码:C0FD,对应字:宽x高12x12,画布:宽W16 高H12,共24字节*/0x10,0x10,0x1F,0x90,0x24,0x50,0x27,0x50,0x69,0x50,0xA9,0x50,0x35,0x50,0x22,0x50,0x22,0x10,0x24,0x10,0x28,0x50,0x30,0x20}};ssd1306_Fill(Black);for (size_t i 0; i sizeof(fonts)/sizeof(fonts[0]); i) {ssd1306_DrawRegion(i * H, 18, W, H, fonts[i], sizeof(fonts[0]), S); //y 18 居中显示}ssd1306_UpdateScreen();sleep(1);
}void Ssd1306TestTask(void* arg)
{(void) arg;i2c_config_t i2c_initer {.clk_flags 0, // 选择默认时钟源.master.clk_speed 50000, // 指定速率为100Kbit,最大可以为400Kbit.mode I2C_MODE_MASTER, // 主机模式.scl_io_num 17, // 指定SCL的GPIO口.scl_pullup_en true, // SCL接上拉电阻.sda_io_num 16, // 指定SDA的GPIO口.sda_pullup_en true, // SDA接上拉电阻};if(i2c_param_config(I2C_NUM_0, i2c_initer) ESP_OK){printf(i2c parm config success\r\n);}else{printf(config fail\r\n);}if(i2c_driver_install(I2C_NUM_0,I2C_MODE_MASTER,0,0,0) ESP_OK ){printf(i2c driver install success\r\n);}else{printf(driver fail\r\n);}//WatchDogDisable();usleep(20*1000);ssd1306_Init();ssd1306_Fill(Black);ssd1306_SetCursor(0, 0);while (1) {TestDrawChinese1();ssd1306_UpdateScreen();usleep(10000);TestDrawChinese2();ssd1306_UpdateScreen();usleep(10000);}
}void Ssd1306TestDemo(void)
{osThreadAttr_t attr;attr.name Ssd1306Task;attr.attr_bits 0U;attr.cb_mem NULL;attr.cb_size 0U;attr.stack_mem NULL;attr.stack_size 10240;attr.priority osPriorityNormal;if (osThreadNew(Ssd1306TestTask, NULL, attr) NULL) {printf([Ssd1306TestDemo] Falied to create Ssd1306TestTask!\n);}
}
OHOS_APP_RUN(Ssd1306TestDemo);
代码分析
OLED屏幕分为页寻址模式水平地址模式垂直地址模式。
这里用的是页寻址模式页寻址模式如下图把整个OLED屏幕分成了八页说白了就是把OLED的屏幕把宽平均分成了八份。比如想要在第0列第三行的开头显示一个点那就是按位来配置0000 01000x08。 通过I2C时序与SSD1306显存进行通信把取好的字模数组中的每一项取出并点亮对应的像素点即可
实验现象 按下ESP32开发板上的EN键,即可观察到实验现象: OLED屏显示汉字