本教程的硬件环境为
Arduino Nano (ATmega328p)
0.96寸 OLED-128X64 SPI 接口
官方介绍为Universal Graphics Library for 8 Bit Embedded Systems。详见https://code.google.com/p/u8glib/wiki/userreference。
支持多种平台,Arduino,AVR,ARM。在Arduino中使用是非常方便与强大的。支持多种屏幕,比较常用的有OLED,LCD12864,LCD5110等。
github地址:https://github.com/olikraus/u8glib
u8glib库的下载地址:https://bintray.com/olikraus/u8glib
本文最后附上简单的作图代码,已编译验证。
库函数:
> firstPage 图像显示
> nextPage
> drawPixe 点
> drawLine 线
> drawHLine 水平线
> drawVLine 垂直线
> drawTriangle 三角(实心)
> drawFrame 矩形框
> drawRFrame 圆角矩形框
> drawBox 矩形(实心)
> drawRBox 圆角矩形(实心)
> drawCircle 圆
> drawDisc 圆形(实心)
> drawEllipse 圆弧
> drawFilledEllipse 扇形(实心)
> drawStr 显示字符串
> print 输出
> drawBitmapP 画位图
> drawXMBP 画大尺寸位图
> getHeight 获得显示器高度
> getWidth 获得显示器宽度
> getStrWidth 获得字符串宽度
> setFont 设置字体
> setPrintPos 设置输出位置
> setColorIndex 设置显示与否
> setRot90 /180 /270 显示内容旋转
> setFontPosTop
若要使图像显示开机画面,u8glib库提供了如下的picture loop。
firstPage
1)方法定义
u8g.firstPage(void) // 调用此过程,标志着图像循环的开始
nextPage
1)方法定义
u8g.nextPage(void) //调用此过程,标志着图像循环的结束
例子
#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g( ... );
void setup() { ... }
void loop() {
u8g.firstPage();
do {
//display
}while(u8g.nextPage());
}
//详见https://code.google.com/p/u8glib/wiki/tpictureloop
1. 几何图形
drawPixel // 画一个点
1)方法定义
u8g.drawPixel(uint8_t x, uint8_t y)
2)参数 x:点的横坐标 y:点的纵坐标
3)例子
u8g.drawPixel(14, 23);
drawLine // 画一条线段
1)方法定义
u8g.drawLine(u8g_uint_t x1, u8g_uint_t y1, u8g_uint_t x2, u8g_uint_t y2)
2)参数
x1: 线段起点 横坐标 y1: 线段起点 纵坐标 x2: 线段终点 横坐标 y2: 线段终点 纵坐标
3)例子
u8g.drawLine(7, 10, 40, 55);
drawHLine //画一条向右的水平线段
1)方法定义
u8g.drawHLine(u8g_uint_t x, u8g_uint_t y, u8g_uint_t w)
2)参数 x:线段起点 横坐标 y:线段起点 纵坐标 w:水平宽度(w个像素点)
3)例子见最下边的drawVLine。
drawVLine //画一条向下的垂直线段
1)方法定义
u8g.drawHLine(u8g_uint_t x, u8g_uint_t y, u8g_uint_t h)
2)参数 x:线段起点 横坐标 y:线段起点 纵坐标 h:垂直高度(h个像素点)
3)例子
u8g.drawHLine(60,12, 30);
u8g.drawVLine(10,20, 20);
drawTriangle // 画一个实心的三角形。至于空心三角形用drawLine即可画出。
1)方法定义
u8g.drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
2)参数 x0:其中一角的 横坐标 y0:其中一角的 纵坐标 x1:另一角的 横坐标 y1:另一角的 纵坐标
x2:最后一角的 横坐标 y2:最后一角的 纵坐标
3)例子
u8g.drawTriangle(14,9, 45,32, 9,42); //第一个三角形
u8g.drawTriangle(14,55, 45,33, 9,43); //第二个三角形
drawFrame // 画一个空心矩形
1)方法定义
u8g.drawFrame(u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)
2)参数
x:方框左上角点的横坐标 y:方框左上角点的纵坐标 w:方框的宽 h:方框的高
3)例子
u8g.drawFrame(10, 12, 30, 20); // 方框的长宽包括了边框所在的像素点
drawRFrame //画一个圆角空心矩形
1)方法定义
u8g.drawRFrame(u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h, u8g_uint_t r)
其中 最好满足:w>=2x(r+1), h>=2x(r+1)。
2)参数
x:圆角矩形左上角 横坐标 y:圆角矩形左上角 纵坐标 w:圆角矩形 宽度 h:圆角矩形 高度 r:圆角弧度的半径
3)例子
u8g.drawRFrame(10,12, 30,20, 5);
drawBox //画一个实心矩形
1)方法定义
u8g.drawBox(u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h)
2)参数 x:矩形左上角的 横坐标 y:矩形左上角的 纵坐标 w:矩形的 宽 h:矩形的高
3)例子
u8g.drawBox(10,12,20,30);
drawRBox //画一个圆角实心矩形,与drawRFrame类似。
1)方法定义
u8g.drawRBox(u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h, u8g_uint_t r)
2)参数
x:圆角矩形左上角 横坐标 y:圆角矩形左上角 纵坐标 w:矩形的 宽 h:矩形的 高 r:圆角弧度半径
drawCircle //画一个空心圆
1)方法定义
u8g.drawCircle(u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rad, uint8_t opt = U8G_DRAW_ALL)
2)参数 x0:圆心 横坐标 y0:圆心 纵坐标 rad:半径 opt:
U8G_DRAW_UPPER_RIGHT 上部右侧 1/4 圆弧
U8G_DRAW_UPPER_LEFT 上部左侧 1/4 圆弧
U8G_DRAW_LOWER_LEFT 下部左侧 1/4 圆弧
U8G_DRAW_LOWER_RIGHT 下部右侧 1/4 圆弧
U8G_DRAW_ALL 整圆(默认)
3)例子
u8g.drawCircle(20,20, 14); //整圆
u8g.drawCircle(20,20, 14, U8G_DRAW_UPPER_RIGHT); // 1/4 圆
drawDisc //画一个实心圆,直径=2*rad+1
1)方法定义
u8g.drawDisc(u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rad, uint8_t opt = U8G_DRAW_ALL)
2)参数
x0:圆心 横坐标 y0:圆心 纵坐标 rad:半径
opt:
U8G_DRAW_UPPER_RIGHT 上部右侧 1/4 扇形
U8G_DRAW_UPPER_LEFT 上部左侧 1/4 扇形
U8G_DRAW_LOWER_LEFT 下部左侧 1/4 扇形
U8G_DRAW_LOWER_RIGHT 下部右侧 1/4 扇形
U8G_DRAW_ALL 整圆(默认)
drawEllipse //圆一个椭圆(空心)
1)方法定义
u8g.drawEllipse(u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rx, u8g_uint_t ry, uint8_t opt)
2)参数
x0,y0:椭圆圆心 横、纵坐标 rx:水平方向半径 ry:垂直方向半径
opt:
U8G_DRAW_UPPER_RIGHT 上部右侧 1/4 椭圆弧
U8G_DRAW_UPPER_LEFT 上部左侧 1/4 椭圆弧
U8G_DRAW_LOWER_LEFT 下部左侧 1/4 椭圆弧
U8G_DRAW_LOWER_RIGHT 下部右侧 1/4 椭圆弧
U8G_DRAW_ALL 整圆(默认)
3)例子
u8g.drawEllipse(20,20, 14,17); //相同圆心的椭圆与圆
u8g.drawCircle(20,20, 14);
drawFilledEllipse // 画一个椭圆(实心)
1)方法定义
u8g.drawFilledEllipse(u8g_uint_t x0, u8g_uint_t y0, u8g_uint_t rx, u8g_uint_t ry, uint8_t opt)
2)参数
x0,y0:椭圆圆心 横、纵坐标 rx:水平方向半径 ry:垂直方向半径
opt:
U8G_DRAW_UPPER_RIGHT 上部右侧 1/4 椭圆
U8G_DRAW_UPPER_LEFT 上部左侧 1/4 椭圆
U8G_DRAW_LOWER_LEFT 下部左侧 1/4 椭圆
U8G_DRAW_LOWER_RIGHT 下部右侧 1/4 椭圆
U8G_DRAW_ALL 整圆(默认)
2. 字符显示
drawStr //显示字符,使用前要使用setFont函数设置要显示字符的字体
1)方法定义
u8g.drawStr(u8g_uint_t x, u8g_uint_t y, const char *s)
另外还有 drawStr90(); drawStr180(); drawStr270(); 使字符顺时针旋转响应的角度。
2)参数
x:字符左下角的横坐标 y:字符左下角的纵坐标 *s:要显示的字符
3)例子
u8g.setFont(u8g_font_osb18);
u8g.drawStr(0, 20, "ABC");
u8g.drawStr90(0,20, "ABC"); //字符旋转90度
print //打印要显示的字符,包括变量值、字符串等。
1)方法定义
u8g.print(...) //使用前需用setPrintPos()函数设置位置
3. 图形显示
drawXBMP //此函数是一个显示一个位图的方法。
1)方法定义
u8g.(u8g_uint_t x, u8g_uint_t y, u8g_uint_t w, u8g_uint_t h, const u8g_pgm_uint8_t *bitmap)
2)参数
x:位图左上角的横坐标 y:位图左上角的纵坐标 w:位图的宽 h:位图的高
//bitmap:位图对象 PS:在任何画图软件中,必须把图片属性调位单位图1bit
3)例子
static unsigned char u8g_logo_bits[] U8G_PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0xe0, 0xff, 0xff, 0x3f,
0xe3, 0xe1, 0xff, 0xff, 0x3f, 0xf3, 0xf1, 0xff, 0xff, 0x3f, 0xf3, 0xf1, 0xfe, 0xbf, 0x37,
0xf3, 0x11, 0x1c, 0x1f, 0x30, 0xf3, 0x01, 0x08, 0x8c, 0x20, 0xf3, 0x01, 0x00, 0xc0, 0x39,
0xf3, 0x81, 0xc7, 0xc1, 0x39, 0xf3, 0xc1, 0xc7, 0xc9, 0x38, 0xf3, 0xc1, 0xc3, 0x19, 0x3c,
0xe3, 0x89, 0x01, 0x98, 0x3f, 0xc7, 0x18, 0x00, 0x08, 0x3e, 0x0f, 0x3c, 0x70, 0x1c, 0x30,
0x3f, 0xff, 0xfc, 0x87, 0x31, 0xff, 0xff, 0xbf, 0xc7, 0x23, 0x01, 0x00, 0x00, 0xc6, 0x23,
0x03, 0x00, 0x00, 0x0e, 0x30, 0xff, 0xff, 0x3f, 0x1f, 0x3c, 0xff, 0xff, 0x3f, 0xff, 0x3f,
0xff, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x3f
}; //数据可以自行下载一个 “字模提取”软件,方便、简洁、中文。
u8g.drawXBMP( 0, 0, 38, 24, u8g_logo_bits);
drawBitmapP //此函数是一个显示一个位图的方法。
1)方法定义
u8g.drawBitmapP(u8g_uint_t x, u8g_uint_t y, u8g_uint_t cnt, u8g_uint_t h, const u8g_pgm_uint8_t *bitmap)
2)参数
x:位图左上角的横坐标 y:位图左上角的纵坐标 cnt:在水平方向上的位图的字节数。该位图的宽度是cnt* 8(1字节=8位)
h:位图的高 *bitmap:位图对象 PS:在任何画图软件中,必须把图片属性调位单位图1bit
3)例子
const uint8_t rook_bitmap[] U8G_PROGMEM = {
0x00, // 00000000
0x55, // 01010101
0x7f, // 01111111
0x3e, // 00111110
0x3e, // 00111110
0x3e, // 00111110
0x3e, // 00111110
0x7f // 01111111
};
u8g.drawBitmapP(0,0, 1, 8, rook_bitmap);
4. 获取
getHeight //获得屏幕的高度,本函数放置在picture loop里面或外部皆可
1)方法定义
u8g.getHeight(void)
2)返回值
“屏幕高度”
getWidth //获得屏幕宽度,本函数放置在picture loop里面或外部皆可
1)方法定义
u8g.getWidth(void)
2)返回值
“屏幕宽度”
3)例子
w = u8g.getWidth();
h = u8g.getHeight();
getStrWidth //获得所显示字符串的宽度,即按照不同字体显示的字符串共占了多少像素。
1)方法定义
u8g.getStrWidth(const char *s)
2)返回值
“字符串的宽度”
3)例子
int w; //设置一个存储变量
u8g.setFont(u8g_font_osb18); //设置字体
u8g.drawStr(0,20, "ABC");
w = u8g.getStrWidth("ABC"); //获得显示的字符串宽度
u8g.drawFrame(0,10, w,11); //画一个以获得的字符串宽度为宽度的方框。
5. 设置显示属性
setFont //设置要显示字符的字体。
1)方法定义
u8g.setFont(const u8g_fntpgm_uint8_t *font)
2)参数
*font:字体样式。u8glib提供的字体样式https://code.google.com/p/u8glib/wiki/fontsize
setPrintPos //设置下文中print()的显示位置
1)方法定义
u8g.setPrintPos(u8g_uint_t x, u8g_uint_t y)
2)参数
x:横坐标 y:纵坐标
setColorIndex //对于单色OLED,此函数功能为是否显示对象。可以理解为透明还是不透明。对于有灰度值的屏幕则是一个灰度值。
1)方法定义
u8g.setColorIndex(uint8_t color_index)
2)参数
color_index:
①1:表示显示,不透明
②0:表示不显示,透明。
3)例子
u8g.setColorIndex(1);
u8g.drawBox(10, 12, 20, 30);
u8g.setColorIndex(0);
u8g.drawPixel(28, 14); // 点亮一个 点,位置在 (28, 14)
setRot90 or 180 or 270 //将显示的结果旋转90°或180°或270°
1)方法定义
u8g.setRot90()
u8g.setRot180()
u8g.setRot270()
2)参数
3)例子
u8g.setFont(u8g_font_osb18);//正常显示
u8g.drawStr(0,20, "ABC");
u8g.setRot90(); //旋转90° : or setRot180(); setRot270();
u8g.setFont(u8g_font_osb18);
u8g.drawStr(0,20, "ABC");
setFontPosTop //使用drawStr显示字符串时,默认标准为显示字符的左下角坐标。(参考drawSt)
1)方法定义
u8g.setFontPosTop(void) //本函数可理解为将坐标位置改为显示字符串的左上角为坐标标准。具体用法可参考例子。
3)例子
u8g.setFont(u8g_font_osb18);
u8g.setFontPosTop();
u8g.drawStr(0, 20, "ABC");
示例代码
函数调用格式既可以用
u8g.draw…,可以用display.draw…,或者
d.draw…。
有用记得点个赞
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2
#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH 16
#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
//以下为定义显示的内容
static const uint8_t PROGMEM Heart_16x16[] = {
0x00,0x00,0x18,0x18,0x3C,0x3C,0x7E,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0x7F,0xFE,0x3F,0xFC,0x1F,0xF8,0x0F,0xF0,0x07,0xE0,0x03,0xC0,0x00,0x00//未命名文件0
};//显示一个心形
static const uint8_t PROGMEM Strong_16x16[] =
{0x10,0x10,0x28,0x48,0x84,0x02,0x7D,0x44,
0x44,0x44,0x54,0x24,0x04,0x04,0xF8,0x00,
0x20,0x20,0x20,0x24,0x24,0x25,0x24,0x24,
0x24,0x24,0x24,0x24,0x21,0x21,0x29,0x10};
void setup() {
Serial.begin(115200);
//delay(500);
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // 定义I2C地址
display.display(); // 显示adafruit 的开机logo,不需要可以注释掉。
delay(2000); //延时2000ms
}
void loop() {
test_SSD1306();
}
void test_SSD1306(void){
//检测全屏显示(看看有没有大面积坏点)
display.fillScreen(WHITE);
display.display();
delay(2000);
//画点 点坐标(10,10)
display.clearDisplay(); //清除缓存
display.drawPixel(10, 10, WHITE);
display.display();
delay(2000);
// 画线 从(0,0)到(50,50)
display.clearDisplay();
display.drawLine(0, 0,50,50, WHITE);
display.display();
delay(2000);
//画空心矩形 左上角坐标(x0,y0) 右下角坐标(x1,y1)
display.clearDisplay();
display.drawRect(0,0,128,64,WHITE);
display.display();
delay(2000);
//画个实心矩形
display.clearDisplay();
display.fillRect(0,0,64,64,WHITE);
display.display();
delay(2000);
//画空心圆
display.clearDisplay();
display.drawCircle(20,20,20,WHITE);
display.display();
delay(2000);
//画实心圆
display.clearDisplay();
display.fillCircle(20,20,20,WHITE);
display.display();
delay(2000);
//画空心三角形
display.clearDisplay();
display.drawTriangle(20,0,0,20,40,20,WHITE);
display.display();
delay(2000);
//画实心三角形
display.clearDisplay();
display.fillTriangle(20,0,0,20,40,20,WHITE);
display.display();
delay(2000);
//画空心圆角矩形
display.clearDisplay();
display.drawRoundRect(0,0,40,40,5,WHITE);
display.display();
delay(2000);
//画实心圆角矩形
display.clearDisplay();
display.fillRoundRect(0,0,40,40,5,WHITE);
display.display();
delay(2000);
//画心形(楼主自己用取模软件画的)
display.clearDisplay();
display.drawBitmap(16,16,Heart_16x16,16,16,WHITE);
display.display();
delay(2000);
//显示英文 数字
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Hello, Arduino!");//显示字符串
display.setTextColor(BLACK, WHITE);
display.println(3.141592);//显示数字
display.setTextSize(2);//定义文字尺寸
display.setTextColor(WHITE);
display.print("0x"); display.println(0xDEADBEEF, HEX);
display.display();
delay(2000);
//显示单个文字 有木有发现就是调用drawBitmap
display.clearDisplay(); // clears the screen and buffer
display.drawBitmap(16,16,Strong_16x16,16,16,WHITE);
display.display();
delay(2000);
}