玩转 ESP32 + Arduino (八) U8G2驱动OLED

OLED驱动芯片:SSD1306
开发平台: vscode+platformIO
开发板:ESP32 Divkit v1

目前Arduino平台上使用最广泛的OLED库: U8G2
github地址: https://github.com/olikraus/u8g2/

设置和参考手册:https://github.com/olikraus/u8g2/wiki

U8g2:单色显示器库,版本2

U8g2是用于嵌入式设备的单色图形库。U8g2支持单色OLED和LCD,包括以下控制器:SSD1305,SSD1306,SSD1309,SSD1322,SSD1325,SSD1327,SSD1329,SSD1606,SSD1607,SH1106,SH1107,SH1108,SH1122,T6963,RA8835,LC7981,PCD8544,PCF8812,HX12 ,UC1601,UC1604,UC1608,UC1610,UC1611,UC1701,ST7565,ST7567,ST7588,ST75256,NT7534,IST3020,ST7920,LD7032,KS0108,SED1520,SBN1661,IL3820,MAX7219(完整列表请参见此处)。

为什么要运用U8g2库?

  • U8g2库平台支持性好,基本上支持绝大部分Arduino开发板;
  • U8g2库显示控制器支持性好,基本上市面上的OLED都完美支持;
  • U8g2库 API众多,特别支持了中文,支持了不同字体,这是一个对于开发者俩说不小的福利。

支持单片机平台:

一. u8g2的安装

再platformIO.ini中配置库

lib_deps =
  # Using a library name
  U8g2

二. u8g2函数库

方法可以分为四大类:

  • 基本函数
  • 绘制相关函数
  • 显示配置相关函数
  • 缓存相关函数

U8g2库函数详解

三. 基本函数

⭐1. u8g2.begin() —— 构造U8G2

初始化显示器, 清屏, 唤醒屏幕

/**
 * 初始化U8g2库
 * @Note 关联方法 initDisplay clearDisplay setPowerSave
 */
bool U8G2::begin(void)

2. u8g2.beginSimple() —— 构造U8G2

只是初始化显示器, 并不清屏, 也不唤醒屏幕

3. u8g2.initDisplay() —— 初始化显示控制器

/**
 * 初始化显示控制器
 */
void U8G2::initDisplay(void)

4. u8g2.clearDisplay() —— 清除屏幕内容

/**
 * 清除屏幕
 */
void U8G2::clearDisplay(void)

⭐5. u8g2.setPowerSave() —— 是否开启省电模式

/**
 * 清除显示缓冲区
 * @param is_enable
 *        1 表示启用显示器的省电模式,屏幕上看不到任何东西
 *        0 表示禁用省电模式
 */
void U8G2::setPowerSave(uint8_t is_enable)

⭐6. u8g2.clear() —— 清除操作

/**
 * 清除屏幕显示,清除缓冲区,光标回到左上角原点位置(0,0)
 * @Note 关联方法 home clearDisplay clearBuffer
 */
void U8G2::clear(void)

⭐7. u8g2.clearBuffer() —— 清除缓冲区

/**
 * 清除内存中数据缓冲区
 */
void U8G2::clearBuffer(void)

8. u8g2.disableUTF8Print() —— 禁用 UTF8打印

/**
 * 禁用Arduino平台下支持输出UTF8字符集,默认是开启
 */
void U8G2::disableUTF8Print(void)

9. u8g2.enableUTF8Print() —— 启用 UTF8打印

/**
 * 开启Arduino平台下支持输出UTF8字符集
 */
void U8G2::enableUTF8Print(void)

开启UTF-8后,我们可以使用其UTF-8字库

#include <Arduino.h>
#include <U8g2lib.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); // ESP32 Thing, HW I2C with pin remapping

void setup(void)
{
  u8g2.begin();
  u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
}
void loop(void)
{
  u8g2.setFont(u8g2_font_unifont_t_chinese2); // use chinese2
  u8g2.firstPage();
  do
  {
    u8g2.setCursor(0, 20);
    u8g2.print("helloworld"); // Chinese "Hello World"
    u8g2.setCursor(0, 40);
    u8g2.print("你好世界"); // Chinese "Hello World"
  } while (u8g2.nextPage());
  delay(1000);
}

10. u8g2.home() —— 重置显示光标的位置

/**
 * 重置显示光标的位置,回到原点(0,0)
 * @Note 关联方法 print clear
 */
void U8G2::home(void)

四. 绘制相关函数

1. u8g2.drawBox() —— 画实心方形

/**
 * 画实心方形,左上角坐标为(x,y),宽度为w,高度为h
 * @param x 左上角的x坐标
 * @param y 左上角的y坐标
 * @param w 方形的宽度
 * @param h 方形的高度
 * @Note 关联方法 drawFrame setDrawColor
 */
void U8G2::drawBox(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)

如果支持绘制颜色(也就是不是单色显示器),那么由setDrawColor设置;

#include <Arduino.h>
#include <U8g2lib.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); // ESP32 Thing, HW I2C with pin remapping

void setup(void)
{
  u8g2.begin();
}
void loop(void)
{
  u8g2.drawBox(3,7,25,15);
  u8g2.sendBuffer();
  delay(1000);
}

2. u8g2.drawCircle() —— 画空心圆

/**
 * 画空心圆,圆心坐标为(x0,y0),半径为rad
 * @param x0 圆点的x坐标
 * @param y0 圆点的y坐标
 * @param rad 圆形的半径
 * @param opt 圆形选项
 *        U8G_DRAW_ALL 整个圆
 *        U8G2_DRAW_UPPER_RIGHT 右上部分的圆弧
 *        U8G2_DRAW_UPPER_LEFT  左上部分的圆弧
 *        U8G2_DRAW_LOWER_LEFT  左下部分的圆弧
 *        U8G2_DRAW_LOWER_RIGHT 右下部分的圆弧
 *        选项可以通过 | 操作符来组合
 * @Note 关联方法 drawDisc setDrawColor
 */
void U8G2::drawCircle(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t opt = U8G2_DRAW_ALL)
  • 如果支持绘制颜色(也就是不是单色显示器),那么由setDrawColor设置;
  • 直径等于2rad + 1;

例: 画圆动画 (4帧😂😂😂😂)

#include <Arduino.h>
#include <U8g2lib.h>

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); // ESP32 Thing, HW I2C with pin remapping

void setup(void)
{
  u8g2.begin();
}
void loop(void)
{
  u8g2.clear();
  u8g2.drawCircle(64, 32, 25, U8G2_DRAW_UPPER_RIGHT);
  u8g2.sendBuffer();
  delay(1000);
  u8g2.drawCircle(64, 32, 25, U8G2_DRAW_LOWER_RIGHT);
  u8g2.sendBuffer();
  delay(1000);
  u8g2.drawCircle(64, 32, 25, U8G2_DRAW_LOWER_LEFT);
  u8g2.sendBuffer();
  delay(1000);
  u8g2.drawCircle(64, 32, 25, U8G2_DRAW_UPPER_LEFT);
  u8g2.sendBuffer();
  delay(1000);
}

3. u8g2.drawDisc() —— 画实心圆

/**
 * 画实心圆,圆心坐标为(x0,y0),半径为rad
 * @param x0 圆点的x坐标
 * @param y0 圆点的y坐标
 * @param rad 圆形的半径
 * @param opt 圆形选项
 *        U8G_DRAW_ALL 整个圆
 *        U8G2_DRAW_UPPER_RIGHT 右上部分的圆弧
 *        U8G2_DRAW_UPPER_LEFT  左上部分的圆弧
 *        U8G2_DRAW_LOWER_LEFT  左下部分的圆弧
 *        U8G2_DRAW_LOWER_RIGHT 右下部分的圆弧
 *       选项可以通过 | 操作符来组合
 * @Note 关联方法 drawCircle setDrawColor
 */
void U8G2::drawDisc(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t opt = U8G_DRAW_ALL)
  • 如果支持绘制颜色(也就是不是单色显示器),那么由setDrawColor设置;
  • 直径等于2rad + 1;

4. u8g2.drawEllipse() —— 画空心椭圆

/**
 * 画空心椭圆,圆心坐标为(x0,y0),半径为rad
 * @param x0 圆点的x坐标
 * @param y0 圆点的y坐标
 * @param rx 椭圆形水平x方向的半径
 * @param ry 椭圆形竖直y方向的半径
 * @param opt 圆形选项
 *        U8G_DRAW_ALL 整个椭圆
 *        U8G2_DRAW_UPPER_RIGHT 右上部分的圆弧
 *        U8G2_DRAW_UPPER_LEFT  左上部分的圆弧
 *        U8G2_DRAW_LOWER_LEFT  左下部分的圆弧
 *        U8G2_DRAW_LOWER_RIGHT 右下部分的圆弧
 *        选项可以通过 | 操作符来组合
 * @Note 关联方法 drawCircle
 */
void U8G2::drawEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t opt)

5. u8g2.drawFilledEllipse() —— 画实心椭圆

/**
 * 画实心椭圆,圆心坐标为(x0,y0),半径为rad
 * @param x0 圆点的x坐标
 * @param y0 圆点的y坐标
 * @param rx 椭圆形水平x方向的半径
 * @param ry 椭圆形竖直y方向的半径
 * @param opt 圆形选项
 *        U8G_DRAW_ALL 整个椭圆
 *        U8G2_DRAW_UPPER_RIGHT 右上部分的圆弧
 *        U8G2_DRAW_UPPER_LEFT  左上部分的圆弧
 *        U8G2_DRAW_LOWER_LEFT  左下部分的圆弧
 *        U8G2_DRAW_LOWER_RIGHT 右下部分的圆弧
 *        选项可以通过 | 操作符来组合
 * @Note 关联方法 drawCircle
 */
void U8G2::drawFilledEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t opt)

6. u8g2.drawFrame() —— 画空心方形

/**
 * 画空心方形,左上角坐标为(x,y),宽度为w,高度为h
 * @param x 左上角的x坐标
 * @param y 左上角的y坐标
 * @param w 方形的宽度
 * @param h 方形的高度
 * @Note 关联方法 setDrawColor
 */
void U8G2::drawFrame(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)

7. u8g2.drawGlyph() —— 绘制字体字集的符号

/**
 * 绘制字体字集里面定义的符号
 * @param x 左上角的x坐标
 * @param y 左上角的y坐标
 * @param encoding 字符的unicode值
 * @Note 关联方法 setFont
 */
void U8G2::drawGlyph(u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding)

8. u8g2.drawHLine() —— 绘制水平线

/**
 * 绘制水平线
 * @param x 左上角的x坐标
 * @param y 左上角的y坐标
 * @param w 水平线的长度
 * @Note 关联方法 setDrawColor
 */
 void U8G2::drawHLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w)

9. u8g2.drawLine() —— 两点之间绘制线

/**
 * 绘制线,从坐标(x0,y0) 到(x1,y1)
 * @param x0 端点0的x坐标
 * @param y0 端点0的y坐标
 * @param x1 端点1的x坐标
 * @param y1 端点1的y坐标
 * @Note 关联方法 setDrawColor
 */
 void U8G2::drawLine(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t x1, u8g2_uint_t y1)

10. u8g2.drawPixel() —— 绘制像素点

/**
 * 绘制像素点,坐标(x,y)
 * @param x 像素点的x坐标
 * @param y 像素点的y坐标
 * @Note 关联方法 setDrawColor
 */
void U8G2::drawPixel(u8g2_uint_t x, u8g2_uint_t y)
  • 我们可以利用这个绘制方法自定义自己的图形显示

11. u8g2.drawRBox() —— 绘制圆角实心方形

/**
 * 绘制圆角实心方形,左上角坐标为(x,y),宽度为w,高度为h,圆角半径为r
 * @param x 左上角的x坐标
 * @param y 左上角的y坐标
 * @param w 方形的宽度
 * @param h 方形的高度
 * @param r 圆角半径
 */
void U8G2::drawRBox(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)

12. u8g2.drawRFrame() —— 绘制圆角空心方形

/**
 * 绘制圆角空心方形,左上角坐标为(x,y),宽度为w,高度为h,圆角半径为r
 * @param x 左上角的x坐标
 * @param y 左上角的y坐标
 * @param w 方形的宽度
 * @param h 方形的高度
 * @param r 圆角半径
 */
void U8G2::drawRFrame(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)

13. u8g2.drawStr() —— 绘制字符串

/**
 * 绘制字符串
 * @param x 左上角的x坐标
 * @param y 左上角的y坐标
 * @param s 绘制字符串内容
 * @return 字符串的长度
 */
u8g2_uint_t U8g2::drawStr(u8g2_uint_t x, u8g2_uint_t y, const char *s)
  • 需要先设置字体,调用setFont方法;
  • 这个方法不能绘制encoding超过256的,超过256需要用drawUTF8或者drawGlyph;说白了就是一般用来显示英文字符;
  • x,y属于字符串左下角的坐标;

14. u8g2.drawTriangle() —— 绘制实心三角形

/**
 * 绘制实心三角形,定点坐标分别为(x0,y0),(x1,y1),(x2,y2)
 */
void U8G2::drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) 

15. u8g2.drawUTF8() —— 绘制UTF8编码的字符

/**
 * 绘制UTF8编码的字符串
 * @param x 字符串在屏幕上的左下角x坐标
 * @param y 字符串在屏幕上的左下角y坐标
 * @param s 需要绘制的UTF-8编码字符串
 * @return 返回字符串的长度
 */
u8g2_uint_t U8g2::drawUTF8(u8g2_uint_t x, u8g2_uint_t y, const char *s)

16. u8g2.drawVLine() —— 绘制竖直线

/**
 * 绘制竖直线
 * @param x 左上角坐标x
 * @param y 左上角坐标y
 * @param h 高度
 */
void U8G2::drawVLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t h) 

⭐17. u8g2.drawXBM()/drawXBMP() —— 绘制图像

/**
 * 绘制图像
 * @param x 左上角坐标x
 * @param y 左上角坐标y
 * @param w 图形宽度
 * @param h 图形高度
 * @param bitmap 图形内容
 * @Note 关联方法 setBitmapMode
 */
void U8G2::drawXBM(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
void U8G2::drawXBMP(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
  • drawXBM和drawXBMP区别在于 XBMP支持PROGMEM;

18. u8g2.firstPage()/nextPage() —— 绘制命令

/**
 * 绘制图像
 */
void U8G2::firstPage(void)
uint8_t U8G2::nextPage(void)
  • firstPage方法会把当前页码位置变成0;
  • 修改内容处于firstPage和nextPage之间,每次都是重新渲染所有内容;
  • 优势点:该方法消耗的ram空间,比sendBuffer消耗的ram空间要少;

实例:

  u8g2.firstPage();
  do {
    /* all graphics commands have to appear within the loop body. */    
    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawStr(0,20,"Hello World!");
  } while ( u8g2.nextPage() );

⭐19. u8g2.print() —— 绘制内容

/**
 * 绘制内容
 * @Note 关联方法  setFont setCursor enableUTF8Print
 */
void U8G2::print(...)

⭐20. u8g2.sendBuffer() —— 绘制缓冲区的内容

/**
 * 绘制缓冲区的内容
 * @Note 关联方法  clearBuffer
 */
void U8G2::sendBuffer(void)
  • sendBuffer的RAM占用空间大,需要结合构造器的buffer选项(请继续往下看,先有个概念)使用;
  • 不管是fistPage、nextPage还是sendBuffer,都涉及到一个叫做 current page position的概念;

五. 显示配置相关函数

1. u8g2.getAscent()

/**
 * 获取基准线以上的高度
 * @return 返回高度值
 * @Note 关联方法  setFont getDescent setFontRefHeightAll
 */
int8_t U8G2::getAscent(void)
  • 跟字体有关(setFont)

示例:下面例子,ascent是18

2. u8g2.getDescent() —— 获取基准线以下的高度

/**
 * 获取基准线以下的高度
 * @return 返回高度值
 * @Note 关联方法  setFont setFontRefHeightAll
 */
int8_t U8G2::getDescent(void)
  • 跟字体有关(setFont);

示例:下面例子,descent是-5

3. u8g2.getDisplayHeight() —— 获取显示器的高度

/**
 * 获取显示器的高度
 * @return 返回高度值
 */
u8g2_uint_t getDisplayHeight(void)

4. u8g2.getDisplayWidth() —— 获取显示器的宽度

/**
 * 获取显示器的宽度
 * @return 返回宽度值
 */
u8g2_uint_t getDisplayWidth(void)

5. u8g2.getMaxCharHeight() —— 获取当前字体里的最大字符的高度

/**
 * 获取当前字体里的最大字符的高度
 * @return 返回高度值
 * @Note 关联方法 setFont
 */
u8g2_uint_t getMaxCharHeight(void)

6. u8g2.getMaxCharWidth() —— 获取当前字体里的最大字符的宽度

/**
 * 获取当前字体里的最大字符的宽度
 * @return 返回宽度值
 * @Note 关联方法 setFont
 */
u8g2_uint_t getMaxCharWidth(void)

7. u8g2.getStrWidth() —— 获取字符串的像素宽度

/**
 * 获取字符串的像素宽度
 * @param s 绘制字符串
 * @return 返回字符串的像素宽度值
 * @Note 关联方法 setFont drawStr
 */
u8g2_uint_t U8G2::getStrWidth(const char *s)

⭐8. u8g2.getUTF8Width() —— 获取UTF-8字符串的像素宽度

/**
 * 获取UTF-8字符串的像素宽度
 * @param s 绘制字符串
 * @return 返回字符串的像素宽度值
 * @Note 关联方法 setFont drawStr
 */
u8g2_uint_t U8G2::getUTF8Width(const char *s)

9. u8g2.setAutoPageClear() —— 设置自动清除缓冲区

/**
 * 是否自动清除缓冲区
 * @param mode 0 表示关闭
 *             1 表示开启,默认是开启
 */
void U8G2::setAutoPageClear(uint8_t mode)
  • 建议该方法保持默认就好,如果用户禁止了,那么需要自己维护缓冲区的状态或者手动调用clearBuffer;

10. u8g2.setBitmapMode() —— 设置位图模式

/**
 * 设置位图模式(定义drawXBM方法是否绘制背景颜色)
 * @param is_transparent
 *         0 绘制背景颜色,不透明,默认是该值
 *         1 不绘制背景颜色,透明
 * @Note 关联方法 drawXBM
 */
void U8G2::setBitmapMode(uint8_t is_transparent)

11. u8g2.setBusClock() —— 设置总线时钟

/**
 * 设置总线时钟(I2C SPI)
 * @param mode clock_speed 总线时钟频率(Hz)
 * @Note 关联方法 begin
 */
void U8G2::setBusClock(uint32_t clock_speed);
  • 仅仅Arduino平台支持;
  • 必须在u8g2.begin() 或者 u8g2.initDisplay()之前调用;

12. u8g2.setClipWindow() —— 限制绘图区域大小

/**
 * 设置采集窗口,窗口范围从左上角(x0,y0)到右下角(x1,y1)
 * 也就是我们绘制的内容只能在规范范围内显示
 * @param x0 左上角x坐标
 * @param y0 左上角y坐标
 * @param x1 右下角x坐标
 * @param y1 右下角y坐标
 * @Note 关联方法 begin
 */
void U8G2::setClipWindow(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t x1, u8g2_uint_t y1 );
  • 可以通过 setMaxClipWindow 去掉该限制

⭐13. u8g2.setCursor() —— 设置光标位置

/**
 * 设置绘制光标位置(x,y)
 * @Note 关联方法 print
 */
void U8G2::setCursor(u8g2_uint_t x, u8g2_uint_t y)

14. u8g2.setDisplayRotation() —— 设置显示器的旋转角度

/**
 * 设置显示器的旋转角度
 * @param u8g2_cb 旋转选项
 *        U8G2_R0 不做旋转 水平
 *        U8G2_R1 旋转90度
 *        U8G2_R2 旋转180度
 *        U8G2_R3 旋转270度
 *        U8G2_MIRROR 不做旋转 水平,显示内容是镜像的,暂时不理解
 */
void setDisplayRotation(const u8g2_cb_t *u8g2_cb)

15. u8g2.setDrawColor() —— 设置绘制颜色

/**
 * 设置绘制颜色(暂时还没有具体去了解用法)
 */
void U8G2::setDrawColor(uint8_t color)

⭐16. u8g2.setFont() —— 设置字体集

/**
 * 设置字体集(字体集用于字符串绘制方法或者glyph绘制方法)
 * @param font 具体的字体集
 * @Note 关联方法  drawUTF8 drawStr drawGlyph print
 */
void U8G2::setFont(const uint8_t *font)
请看第九章获取字库更多信息

17. u8g2.setFontMode() 设置显示模式

启用(1)或禁用(0)透明模式

18. u8g2.setFontDirection() —— 设置字体方向

/**
 * 定义字符串绘制或者图形绘制的方向
 * @param dir 方向
 * @param 关联方法 drawStr
 */
void U8G2::setFontDirection(uint8_t dir)

六. 缓存相关函数

1. u8g2.getBufferPtr() —— 获取缓存空间的地址

/**
 * 获取缓存空间的地址
 * @return 返回缓存空间起始地址
 * @Note 关联方法 getBufferTileHeight, getBufferTileWidth, clearBuffer
 */
uint8_t *U8G2::getBufferPtr(void)

2. u8g2.getBufferTileHeight() —— 获取缓冲区的Tile高度

/**
 * 获取缓冲区的Tile高度
 * @return 返回高度值
 */
uint8_t U8G2::getBufferTileHeight(void)
  • 一个tile等于8个像素点.

3. u8g2.getBufferTileWidth() —— 获取缓冲区的Tile宽度

/**
 * 获取缓冲区的Tile宽度
 * @return 返回宽度值
 */
uint8_t U8G2::getBufferTileWidth(void)

4. u8g2.getBufferCurrTileRow() —— 获取缓冲区的当前Tile row

/**
 * 获取缓冲区的当前Tile row行数
 * @return 返回当前的tilerow
 */
uint8_t U8G2::getBufferCurrTileRow(void)

5. u8g2.setBufferCurrTileRow() —— 设置缓冲区的当前Tile row

/**
 * 设置缓冲区的当前Tile row
 * @param 当前的tilerow
 */
void U8G2::setBufferCurrTileRow(uint8_t  row)
  • 在 firstPage/nextPage 循环时,由于底层调用了setBufferCurrTileRow,所以尽量不要自己手动调用该方法

七. U8g2绘制模式

U8g2支持三种绘制模式:

  • Full screen buffer mode,全屏缓存模式
  • Page mode (This is the U8glib picture loop) 分页模式
  • U8x8, character only mode 仅仅支持普通字符

1. Full screen buffer mode

特点:

  • 绘制速度快
  • 所有的绘制方法都可以使用
  • 需要大量的ram空间

用法:

  1. 清除缓冲区 u8g2.clearBuffer()
  2. 操作一些绘制方法
  3. 发送缓冲区的内容到显示器 u8g2.sendBuffer().

2. Page mode

特点:

  • 绘制速度慢
  • 所有的绘制方法都可以使用
  • 需要少量的ram空间

3. U8x8 character mode

特点:

  • 绘制速度快
  • 并不是对所有的显示器都有效
  • 图形绘制不可用
  • 不需要ram空间
    使用U8X8构造器,比如:
U8X8_ST7565_EA_DOGM128_4W_SW_SPI(clock, data, cs, dc [, reset])

八. 用法

  1. 包含头文件
#include <U8g2lib.h>
  1. U8g2对象初始化

看例程里有无数条代表着各种屏幕的写好的U8g2初始化语句,选择适合的一条解除注释即可

我的ESP32 DEVKIT V1+SSD1306(IIC)是选择这个:

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); // ESP32 Thing, HW I2C with pin remapping
  1. 初始化屏幕
u8g2.begin();
  1. 使用第六节的一种方法开始吧

九. 关于字库

1. 命名规则

<prefix> '_' <name> '_' <purpose> <char set>
  • prefix基本上都是 u8g2;
  • name 字体名称
  • purpose 用法
字符 描述
t 透明字体,不要使用背景色
h 所有的图形有通用的高度
m 所有字形都有共同的高度和宽度(等宽)
8 所有图示符都可以放入8x8像素的方框中
  • char set 字符设置
字符 描述
f 最多包含256个字体
r 字体中只包含ASCII代码32到127范围内的字形.
u 字体中只包含ASCII代码32到95(大写字符)范围内的字形.
n 字体中只包含数字和用于写入日期和时间字符串的额外字形
其他自定义字符列表.

2. 所有字库

https://github.com/olikraus/u8g2/wiki/fntlistall

3. 符号字库参考

https://github.com/olikraus/u8g2/wiki/fntgrpiconic

示例: 显示所有iconic图标

#include <Arduino.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); // ESP32 Thing, HW I2C with pin remapping

void setup()
{
  u8g2.begin();
}
void loop()
{
  for (size_t i = 64; i < 288; i++)
  {
    u8g2.setFont(u8g2_font_tenstamps_mn);
    u8g2.setCursor(0, 20);
    u8g2.print("   ");//为了不全屏刷新的情况下清空局部显示区域
    u8g2.setCursor(0, 20);
    u8g2.print(i);
    u8g2.setFont(u8g2_font_inr33_mf);
    u8g2.setCursor(64, 48);
    u8g2.print("   ");//为了不全屏刷新的情况下清空局部显示区域
    u8g2.setFont(u8g2_font_open_iconic_all_4x_t);
    u8g2.drawGlyph(64, 48, i);
    u8g2.sendBuffer();
    delay(1500);
  }
}

4. 中文字库

https://github.com/olikraus/u8g2/wiki/fntgrpwqy

可以看到, 最小的字高12px, 最大的字高18px,如果想要更大的字,请取XBM格式字模

十. 一个小车的动画

#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); // ESP32 Thing, HW I2C with pin remapping
void setup(void)
{
  u8g2.begin();
  u8g2.setFont(u8g2_font_10x20_tf);
  u8g2.setFontRefHeightExtendedText();
  u8g2.setDrawColor(1);
  u8g2.setFontPosTop();
  u8g2.setFontDirection(0);
}

void loop(void)
{
  for (int i = -31; i < 128; i++)
  {
    u8g2.clearBuffer();
    u8g2.drawStr(0, 0, "Fashional Car");
    u8g2.drawBox(0 + i, 54 - i % 2, 31, 6);
    u8g2.drawBox(7 + i, 48 - i % 2, 17, 6);
    u8g2.drawDisc(7 + i, 59, 4);
    u8g2.drawDisc(22 + i, 59, 4);
    switch (i % 6)
    {
    case 0:
      u8g2.drawDisc(-6 + i, 59, 1);
      break;
    case 1:
      u8g2.drawDisc(-12 + i, 58, 2);
      break;
    case 2:
      u8g2.drawDisc(-16 + i, 57, 3);
      break;
    default:
      break;
    }
    Serial.println(i);
    delay(50);
    u8g2.sendBuffer();
  }
}

十一. 显示XBM图片

我使用了在线转换器:

https://convertio.co/zh/image-converter/?utm_source=chrome_extension

整个转换过程很简单, 转换好的XBM文件用记事本打开就能看到数组了, 感觉比传统的 Img2Lcd 或者 PCtoLCD2002 好用

#include <Arduino.h>
#include "U8g2lib.h"
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21); // ESP32 Thing, HW I2C with pin remapping

static const unsigned char al_logo[] U8X8_PROGMEM = {
  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, 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, 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, 
  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, 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, 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, 
  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, 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, 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, 
  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, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 
  0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x0A, 0x00, 0x00, 
  0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 
  0xC0, 0x08, 0x80, 0x01, 0x07, 0x00, 0x70, 0x00, 0x00, 0x06, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x10, 0x80, 0x1D, 0xC0, 0x03, 0x0F, 0x00, 0xF8, 0x00, 
  0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0xC0, 0x03, 
  0xEF, 0x00, 0xF8, 0x01, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
  0x30, 0x18, 0xC0, 0x03, 0xE7, 0x01, 0xFC, 0x01, 0x00, 0x1F, 0x00, 0x00, 
  0x00, 0x07, 0x00, 0x00, 0x88, 0x57, 0xE0, 0x03, 0xEF, 0x03, 0xFE, 0x01, 
  0x00, 0x1F, 0x0F, 0x00, 0x80, 0x07, 0x00, 0x00, 0xCC, 0x7E, 0xE0, 0x01, 
  0xC7, 0x03, 0xFF, 0x00, 0x00, 0xFF, 0x1F, 0x00, 0x80, 0x07, 0x00, 0x00, 
  0x02, 0x00, 0xE0, 0x0F, 0x87, 0x83, 0xFF, 0x07, 0x00, 0xFF, 0x0F, 0x00, 
  0xC0, 0x07, 0x00, 0x00, 0x00, 0x06, 0xF0, 0x1F, 0x37, 0xC1, 0xFF, 0x0F, 
  0x80, 0x7F, 0x01, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x04, 0xF0, 0x1F, 
  0xFF, 0xC0, 0xBF, 0x0F, 0x80, 0xBF, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 
  0x00, 0x16, 0xF8, 0x1C, 0xFF, 0xC0, 0x17, 0x0F, 0x80, 0x0F, 0x00, 0x00, 
  0xF0, 0x03, 0x00, 0x00, 0x00, 0x1D, 0x78, 0x9C, 0x1F, 0xC0, 0xFD, 0x0F, 
  0x80, 0x47, 0x07, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x00, 0x05, 0x30, 0xFF, 
  0x07, 0xE0, 0xFF, 0x0F, 0x80, 0xFF, 0x3F, 0x00, 0xF8, 0x01, 0x00, 0x00, 
  0x00, 0x00, 0xE0, 0xFF, 0x07, 0xE0, 0xBF, 0x0F, 0x80, 0xFF, 0x7E, 0x00, 
  0xFC, 0x00, 0x00, 0x00, 0x80, 0x64, 0xE0, 0x3D, 0x33, 0xE0, 0x9F, 0x07, 
  0xE0, 0x0F, 0x78, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x80, 0x05, 0x60, 0x9C, 
  0x33, 0xE0, 0x8B, 0x0F, 0xF0, 0x03, 0xF0, 0x00, 0xFE, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x30, 0x9F, 0x63, 0xE0, 0x8D, 0x0F, 0x7C, 0x00, 0xF0, 0x00, 
  0xFF, 0x03, 0x00, 0x00, 0x00, 0x30, 0xE0, 0x9D, 0xE9, 0xE0, 0xBC, 0x07, 
  0x3F, 0xF0, 0xF8, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x80, 0x01, 0xE0, 0xDE, 
  0xF1, 0xE0, 0xBE, 0x0F, 0x1E, 0xFC, 0xF9, 0x80, 0xDF, 0x0F, 0x00, 0x00, 
  0x80, 0x02, 0x80, 0xDF, 0xF0, 0xE1, 0xBF, 0x07, 0x04, 0xFF, 0x79, 0xC0, 
  0x9F, 0x1F, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x7F, 0xE0, 0xE0, 0x9F, 0x07, 
  0xC0, 0xBF, 0x7D, 0xC0, 0x0F, 0x7E, 0x00, 0x00, 0xC0, 0x0C, 0x08, 0x2E, 
  0x00, 0xE0, 0x8C, 0x0F, 0xF0, 0x0F, 0x7C, 0xE0, 0x07, 0xFC, 0x01, 0x00, 
  0xC0, 0x0C, 0x1E, 0x00, 0xC0, 0xE1, 0xCC, 0x07, 0xFE, 0x0B, 0x3E, 0xF0, 
  0x03, 0xF8, 0x07, 0x00, 0x80, 0x28, 0x3C, 0x00, 0xE2, 0xE3, 0xD2, 0x07, 
  0xFE, 0x38, 0x3E, 0xF0, 0x03, 0xE0, 0x1F, 0x00, 0xA0, 0x2D, 0x3C, 0xFF, 
  0xDF, 0xE7, 0xF8, 0x07, 0x00, 0xF0, 0x3F, 0xF8, 0x01, 0xC0, 0xFF, 0x02, 
  0xA0, 0x01, 0xF8, 0x71, 0x8E, 0xE7, 0xFE, 0x07, 0x00, 0xF0, 0x1F, 0xFC, 
  0x00, 0x80, 0xFF, 0x1F, 0x00, 0x0C, 0xF0, 0x60, 0x80, 0xE7, 0xFF, 0x07, 
  0x00, 0xE0, 0x0F, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x20, 0x00, 
  0xC0, 0xE3, 0xC3, 0x07, 0x00, 0xE0, 0x0F, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 
  0x00, 0x08, 0x00, 0x00, 0x20, 0xE0, 0xC1, 0x03, 0x00, 0xC0, 0x03, 0x0C, 
  0x00, 0x00, 0xF0, 0x1F, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x80, 0x03, 
  0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x03, 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, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x02, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00,};
void setup()
{
  Serial.begin(115200);
  u8g2.begin();
}
void loop()
{
  u8g2.firstPage();
  do
  {
    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawXBMP(0, 0, 128, 64, al_logo);
  } while (u8g2.nextPage());
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342