一:安装Arduino
二:安装ESP8266开发包
三:u8g2库的简介与安装
u8g2简介:
U8g2 是一个用于嵌入式设备的单色图形库。U8g2支持单色OLED和LCD,并支持如SSD1306等多种类型的OLED驱动。
u8g2的安装:
我们可以直接在Arduino的库管理中搜索和安装:(对网络环境要求较高)
我们也可以直接去下载源码然后导入:
四:U8g2库的基础使用
使用U8g2库进行OLED的显示十分简单,首先要包含两个库,U8g2lib和Wire,后者是IIC通信需要用。
对于IIC接口的OLED,需要在程序中指定一下引脚的接口定义,如果是SPI接口,可以参考U8g2库自带例程中SPI接口是使用方法。、
然后在Ardunio的setup中进行u8g2的初始化。
最后在Ardunio的loop中编写自己想要的代码逻辑了,温馨提醒,在U8g2库在loop中的通用写法是使用do{}while()的形式:
u8g2.firstPage();
do
{
//自己的的逻辑
} while (u8g2.nextPage());
delay(1000);
接下来是一个简单的显示示例:
#include <U8g2lib.h>
#include <Wire.h>
#define SCL 5
#define SDA 4
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/SCL, /*data=*/SDA, /*reset=*/U8X8_PIN_NONE);
void setup()
{
u8g2.begin();
u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
}
void loop()
{
u8g2.setFont(u8g2_font_unifont_t_symbols);
u8g2.firstPage();
do
{
u8g2.setCursor(0, 15); //指定显示位置
u8g2.print("Hello World!"); //使用print来显示字符串
} while (u8g2.nextPage());
delay(1000);
}
注意,setCursor(0, 15),是将画图位置移动到x=0,y=15处,然后以这个点的右上区域进行字符串的显示,这样看起来就是显示在OLED的第一行,如果你设置setCursor(0, 0),字符串实际是到屏幕外面了,不会显示!
五:U8g2常用API函数
5.1:基础设置
- setFont(font) 设置字体
- font:u8g2的字体,比较常用的有u8g2_font_unifont_t_symbols(通常使用这个)和u8g2_font_wqy12_t_gb2312b(用于显示汉字)等
- setFontMode(num) 设置字体背景颜色模式
- num:启用(1)透明模式
- num:禁用(0)透明模式
- setDrawColor(color) 设置所有绘图函数的位值
- color:0(显示RAM中的清晰像素值)
- color:1(设置像素值)
- color:2(异或模式)
5.2: 画像素点
- drawPixel(x,y)
可以设置指定坐标显示画点,例如我们可以显示所有的点:
#include <U8g2lib.h>
#include <Wire.h>
#define SCL 5
#define SDA 4
//定义了一个宏定义,用于延时显示每一次的画图,方便观察OLED的显示过程:
#define SEND_BUFFER_DISPLAY_MS(ms)\
do {\
u8g2.sendBuffer(); \
delay(ms);\
}while(0);
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/SCL, /*data=*/SDA, /*reset=*/U8X8_PIN_NONE);
void setup()
{
u8g2.begin();
u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
}
//画像素点-填充屏幕
void testDrawPixelToFillScreen()
{
int t = 1000;
u8g2.clearBuffer();
for (int j = 0; j < 64; j++)
{
for (int i = 0; i < 128; i++)
{
u8g2.drawPixel(i, j);
}
}
SEND_BUFFER_DISPLAY_MS(t);
}
void loop()
{
testDrawPixelToFillScreen();
}
5.3: 画直线:
- drawLine(x0,y0,x1,y1) 画一条线
- x0,y0线的起点
- x1,y1线的终点
- drawHLine(x,y,w) 画一条水平线
- x,y线的起点
- w水平线的长度(宽度)
- drawVLine(x,y,h) 画一条竖直线
- x,y线的起点
- h竖直线的长度(高度)
测试函数:
//画直线
void testDrawLine()
{
int t = 500;
u8g2.clearBuffer();
u8g2.drawStr(33, 14, "drawLine");
u8g2.drawLine(0, 0, 127, 63);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawLine(0, 0, 127, 0);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawLine(32, 15, 127, 15);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawLine(33, 16, 127, 16);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawLine(127, 0, 127, 15);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawLine(127, 16, 127, 63);
SEND_BUFFER_DISPLAY_MS(t);
}
5.4:画空心/实心(圆角)矩形、
- drawFrame(x,y,w,h) 绘制一个空心框
- drawBox(x,y,w,h) 绘制一个实心矩形
- drawRFrame(x,y,w,h,r) 绘制一个空心框(圆角)
- drawRBox(x,y,w,h,r) 绘制一个实心矩形 (圆角)
- x,y起点坐标
- w,h框的宽度和高度
- r圆角的半径
测试函数:
//画空心圆角矩形
void testDrawRFrame()
{
int t = 500;
int x = 16;
int y = 32;
int w = 50;
int h = 20;
int r = 3;
u8g2.clearBuffer();
u8g2.drawStr(0, 15, "drawRFrame");
u8g2.drawRFrame(x, y, w, h, r);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawRFrame(x+w+5, y-10, w-20, h+20, r);
SEND_BUFFER_DISPLAY_MS(t);
}
5.5: 画空心/实心圆
- drawCircle(x,y,rad,opt) 绘制一个空心圆
- drawDisc(x,y,rad,opt) 绘制一个实心圆
- x,y为圆心坐标
- rad为圆的半径
- opt为选择画的部分,分为:
- U8G2_DRAW_UPPER_RIGHT(右上)
- U8G2_DRAW_UPPER_LEFT(左上)
- U8G2_DRAW_LOWER_LEFT(左下)
- U8G2_DRAW_LOWER_RIGHT(右下)
- U8G2_DRAW_ALL(全部)
测试函数:
空心圆:
//画空心圆
void testDrawCircle()
{
int t = 500;
int stx = 0; //画图起始x
int sty = 16; //画图起始y
int with = 16;//一个图块的间隔
int r = 15; //圆的半径
u8g2.clearBuffer();
u8g2.drawStr(0, 15, "drawCircle");
u8g2.drawCircle(stx, sty - 1 + with, r, U8G2_DRAW_UPPER_RIGHT); //右上
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawCircle(stx + with, sty, r, U8G2_DRAW_LOWER_RIGHT); //右下
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawCircle(stx - 1 + with * 3, sty - 1 + with, r, U8G2_DRAW_UPPER_LEFT); //左上
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawCircle(stx - 1 + with * 4, sty, r, U8G2_DRAW_LOWER_LEFT); //左下
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawCircle(stx - 1 + with * 2, sty - 1 + with * 2, r, U8G2_DRAW_ALL);//整个圆
SEND_BUFFER_DISPLAY_MS(t);
}
注意,U8g2库画出的圆,因像素点的显示原理,圆的直径占用的宽度不是半径的2倍,而是2倍再加一个像素点。
5.6:画空心/实心椭圆
- drawEllipse(x,y,rx,ry,opt) 绘制一个空心椭圆
- drawFilledEllipse(x,y,rx,ry,opt) 绘制一个实心椭圆
x,y
为圆心坐标rx,ry
为与椭圆x和y方向的半径opt
与画圆时的作用一致
椭圆的显示与圆的显示类似,只是椭圆可以分别指定x和y方向的半径
5.7:字符串、汉字和变量显示:
字符串的显示,可以使用drawStr函数,也可以使用通用风格的print函数。
- drawStr(x,y,string) 绘制一个字符串
x,y
起点坐标string
字符串
如果想要使用print显示汉字,需要先设置如下两句:
u8g2.enableUTF8Print();//enable UTF8
u8g2.setFont(u8g2_font_wqy12_t_gb2312b);//设置中文字符集
如果想要显示变量,使用print函数即可:
字符串、汉字、变量的测试函数如下:
//字符串/文字/变量显示测试
void testDrawStr()
{
int t = 1000;
u8g2.clearBuffer();
u8g2.drawStr(0, 14, "drawStr / print");
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawStr(0, 32, "~!@#$%^&*()_+");
SEND_BUFFER_DISPLAY_MS(t);
u8g2.enableUTF8Print();//enable UTF8
u8g2.setFont(u8g2_font_wqy12_t_gb2312b);//设置中文字符集
u8g2.setCursor(0, 48);
u8g2.print("码农爱学习");
SEND_BUFFER_DISPLAY_MS(t);
int a = 234;
u8g2.setCursor(0, 64);
u8g2.print("int a = ");
u8g2.setCursor(40, 64);
u8g2.print(a);//显示变量
SEND_BUFFER_DISPLAY_MS(t);
}
5.8:画内置图标:
- drawGlyph(x,y,addr) 绘制U8g2内置的图标
x,y
起点坐标addr
内置图标的地址
U8g2库内置了需要预先定义的图形,通过drawGlyp函数以及指定的地址,即可看OLED上显示对应的图标:
各个图形的地址定义如下:
编写一个测试程序:
void testGlyph()
{
int t = 1000;
u8g2.clearBuffer();
u8g2.drawStr(0, 14, "drawGlyph");
u8g2.drawGlyph(0, 32, 0x23f0);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawGlyph(16, 32, 0x23f3);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawGlyph(32, 32, 0x2603);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawGlyph(48, 32, 0x2615);
SEND_BUFFER_DISPLAY_MS(t);
u8g2.drawGlyph(64, 32, 0x2618);
SEND_BUFFER_DISPLAY_MS(t);
}
5.9:画自定义图片
- drawXBM(x,y,w,h,addr) 绘制一个实心矩形 (圆角)
x,y
起点坐标w,h
图片的宽度和高度`addr
图片(数组)的地址
自定义图片的显示,需要先将图形转换为数组,
测试程序:
// width: 128, height: 48
const unsigned char bilibili[] 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, ... 省略若干行 };
void testDrawXBM()
{
int t = 1000;
u8g2.clearBuffer();
u8g2.drawStr(0, 14, "drawXBM");
u8g2.drawXBM(0, 16, 128, 48, bilibili);
SEND_BUFFER_DISPLAY_MS(t);
}
总结: