功能介绍
OLED(Organic Light-Emitting Diode)显示屏是利用有机电自发光二极管制成的显示屏。由于同时具备自发光有机电激发光二极管,不需背光源、对比度高、厚度薄、视角广、反应速度快等优点。
0.96 OLED显示模块的显示尺寸是0.96寸,像素分辨率是128x64像素,可以用于显示数字、字母、汉字、图片等信息。0.96 OLED显示模块实物如图3.20.1所示。显示一个汉字的最小像素分辨率需要16x16像素,所以,128x64分辨率最多可以显示8x4个汉字。
图3.20.1 0.96 OLED显示模块实物图
0.96 OLED显示模块,常见的驱动芯片是SSD1306,模块接口有4针和7针接口,4针接口是IIC的通信方式,7针接口是SPI的通讯方式。在此推荐使用IIC通信方式的4针接口。0.96寸的OLED显示模块只是常见的尺寸,还有其他不同显示分辨率和大小的显示模块,使用时根据实际需要选择,在此我们以IIC通信方式的0.96寸、128x64分辨率为例介绍,本模块的供电电压为DC3.3V-5V。因为采用IIC通信方式,在IIC总线上的所有设备都有唯一的地址,常见的OLED显示模块的实际地址是0x78或者0x7A,在生产厂商的资料中一般会给出这个地址,还有部分的模块可以通过跳线选择地址,使用时需要注意这个IIC的地址,地址不对,通信就没办法完成。在Arduino编程时,库函数做了IIC地址的处理,使用时需要设置地址为0x3c或者0x3d,常见的0.96寸OLED显示屏的默认地址都是0x3c,在不清楚IIC地址的情况下,首选0x3c测试。
接线说明
Arduino | 0.96 OLED显示模块(IIC) | 说明 |
---|---|---|
VCC/+/5V | VCC/+/5V | 供电引脚 |
GND/G/- | GND/G/- | 电源地线 |
A4 | SDA | IIC接口的数据线 |
A5 | SCL | IIC接口的时钟线 |
使用说明:
1.按照接线说明完成接线,注意供电引脚必须连接正确。注意,此时通电OLED显示屏是不会有任何变化的,原因就是OLED是自发光显示方式,不需要背光灯,所以没有显示信息的时候显示屏上不会有任何变化。
2.通过查看本模块厂家资料,找到IIC通信地址,记下这个地址。
3(a).Arduino IDE 编程
采用Arduino IDE编程时,需要调用到库文件,OLED的库文件有很多,可以在工具菜单中的“库管理器”中自行搜索使用。在此推荐两个库“Adafruit_SSD1306”和“CN_SSD1306_Wire”。“Adafruit_SSD1306”即可满足画线、画圆等图形界面的设计,还可已实现特定图片的显示以及ASICC的显示。如果使用时需要显示中文字符,推荐使用“CN_SSD1306_Wire”库,此库目前在“库管理器”中搜索不到,可以自行到网络上搜索。
3(b).Mixly编程
使用Mixly编程时,OLED显示屏程序模块在“显示器”—>“显示屏”下,展开“显示屏”后,里面有多个显示屏的初始化程序模块,在此我们需要选择“初始化SSD1306(12864)…”程序模块,如图3.20.2所示,此模块是必须模块,是用来初始化OLED的硬件连接等一些基础设置的。在这个程序模块中,第一个参数“SDD1306(12864)”是现在显示屏的型号及显示屏的分辨率,在此我们默认就好;第二个参数“u8g2”是显示屏的名称,可以根据需要修改,在此我们以默认设置为易;第三个参数屏幕旋转的度数,非必要不用设置,默认旋转零度设置;第四、第五两个参数是OLED显示屏和Arduino的硬件连接设置,我们默认OLED屏采用IIC接口连接,采用默认就好;最后一个参数设备地址默认是0x3C,在此默认就好,除非你知道如何设置显示屏上的地址选择跳线。
图3.20.2 OLED显示屏初始化程序模块
如图3.20.2所示,初始化模块下方还有一句语句“显示屏u8g2刷新显示页面page1”,这里的“page1”是我们实际需要显示的程序模块所在的地方,在展开的“显示屏”程序模块中,有一个紫色的程序块“page1”,如图3.20.3所示。默认程序块中有两条程序块,分别是设置显示的字体字号和显示的实际文本信息。在实际使用时,我们需要根据需要修改内部的程序实现我们所想要得显示效果,具体使用方法请参照参考程序。还有很多正对OLED显示屏的程序模块,比如汉字显示、图片显示、画圆、画线等基础的GUI程序模块,使用时可以根据需求自行选择。
图3.20.3 OLED显示程序模块
参考程序:
Arduino IDE参考程序
/**************************************************************************
*@mainpage Arduino库,用于基于SSD1306驱动程序的单色OLED。
------> http://www.adafruit.com/category/63_98
是一个基于SSD1306驱动程序的单色OLED示例
**************************************************************************/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED 显示屏横向(宽)的像素点数量
#define SCREEN_HEIGHT 64 // OLED 显示屏纵向(高)的像素点数量
// 创建一个IIC接口的一个OLED对象,名称是display
#define OLED_RESET 4 // Reset 引脚,默认就好
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES 10 // 动画示例中雪花的数量
#define LOGO_HEIGHT 16
#define LOGO_WIDTH 16
static const unsigned char PROGMEM logo_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
void setup() {
Serial.begin(9600);
// 显示屏采用内部3.3V电压,IIC地址是0x3c
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // 如果失败,则一直循环,不会进入继续向下
}
// 显示缓冲区内的内容
display.display();
delay(2000);
//清除缓冲区内容
display.clearDisplay();
//点亮两个像素点,白色(100,10)(101,10)
display.drawPixel(100, 10, SSD1306_WHITE);
display.drawPixel(101, 10, SSD1306_WHITE);
// 显示缓冲区内容,需要调用display.display();
display.display();
delay(2000);
testdrawline(); // 画线,很多线
testdrawrect(); // 绘制矩形轮廓
testfillrect(); // 绘制矩形(填充)
testdrawcircle(); // 画圆(轮廓)
testfillcircle(); // 画圆(填充)
testdrawroundrect(); // 绘制圆角矩形(轮廓)
testfillroundrect(); // 绘制圆角矩形(填充)
testdrawtriangle(); // 绘制三角形(轮廓)
testfilltriangle(); // 绘制三角形(填充)
testdrawchar(); // 绘制默认字体的字符 ASICC码表显示
testdrawstyles(); // 绘制“样例”字符
testscrolltext(); // 显示滚动文本
testdrawbitmap(); // 画一个小位图图像
// 反转并恢复显示,中间暂停
display.invertDisplay(true);
delay(1000);
display.invertDisplay(false);
delay(1000);
testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); //设置位图动画,内部已经循环
}
void loop() {
}
//############################
// 画线,很多线
//############################
void testdrawline() {
int16_t i;
display.clearDisplay(); // 清除显示缓冲区
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
display.display(); // 更新显示
delay(1);
}
for(i=0; i<display.height(); i+=4) {
display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for(i=display.width()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
display.display();
delay(1);
}
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for(i=0; i<display.height(); i+=4) {
display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
display.display();
delay(1);
}
for(i=0; i<display.width(); i+=4) {
display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000); // Pause for 2 seconds
}
//###########################
// 绘制矩形轮廓testdrawrect();
//###########################
void testdrawrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2; i+=2) {
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
display.display(); // Update screen with each newly-drawn rectangle
delay(1);
}
delay(2000);
}
//###########################
// testfillrect(); // 绘制矩形(填充)
//###########################
void testfillrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2; i+=3) {
// 使用反向颜色,使矩形交替为白色/黑色
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(2000);
}
//############################
// 画圆(轮廓) testdrawcircle();
//############################
void testdrawcircle(void) {
display.clearDisplay();
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000);
}
//############################
// 画圆(填充) testfillcircle();
//############################
void testfillcircle(void) {
display.clearDisplay();
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
// 反转色,实现黑白显示
display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(2000);
}
//############################
// 绘制圆角矩形(轮廓) testdrawroundrect();
//############################
void testdrawroundrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2-2; i+=2) {
display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000);
}
//############################
// 绘制圆角矩形(填充)testfillroundrect();
//############################
void testfillroundrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2-2; i+=2) {
// 使用反向颜色,黑白交替显示
display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(2000);
}
//############################
// 绘制三角形(轮廓) testdrawtriangle();
//############################
void testdrawtriangle(void) {
display.clearDisplay();
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
display.drawTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
display.display();
delay(1);
}
delay(2000);
}
//############################
// 绘制三角形(填充) testfilltriangle();
//############################
void testfilltriangle(void) {
display.clearDisplay();
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
// 使用反向颜色,使三角形交替为白色/黑色
display.fillTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
display.display();
delay(1);
}
delay(2000);
}
//############################
// 绘制默认字体的字符 ASICC码表显示 testdrawchar();
//############################
void testdrawchar(void) {
display.clearDisplay();
display.setTextSize(1); // 显示字号1
display.setTextColor(SSD1306_WHITE); // 白色显示
display.setCursor(0, 0); // 初始坐标
display.cp437(true); // 使用完整的256字符“代码页437”字体
// Not all the characters will fit on the display. This is normal.
// Library will draw what it can and the rest will be clipped.
for(int16_t i=0; i<256; i++) {
if(i == '\n') display.write(' ');
else display.write(i);
}
display.display();
delay(2000);
}
//############################
// 显示ASICC字符 testdrawstyles();
//############################
void testdrawstyles(void) {
display.clearDisplay();
display.setTextSize(1); // 显示字号1
display.setTextColor(SSD1306_WHITE); // 白色显示
display.setCursor(0,0); // 显示起始坐标
display.println(F("Hello, world!"));
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // 显示反向文本
display.println(3.141592,7);//显示3.14,7个有效数字
display.setTextSize(2); // 显示字号2
display.setTextColor(SSD1306_WHITE);
//显示十六进制数
display.print(F("0x"));
display.println(0xDEADBEEF, HEX);
display.display();
delay(2000);
}
//############################
// 显示滚动文本 testscrolltext();
//############################
void testscrolltext(void) {
display.clearDisplay();
display.setTextSize(2); // 显示字号为2
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);//起始显示坐标
display.println(F("Arduino"));
display.display(); // Show initial text
delay(100);
// 滚动显示
display.startscrollright(0x00, 0x0f);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x0f);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrolldiagright(0x00, 0x07);
delay(2000);
display.startscrolldiagleft(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
}
//############################
// 画一个小位图图像 testdrawbitmap();
//############################
void testdrawbitmap(void) {
display.clearDisplay();
display.drawBitmap(
(display.width() - LOGO_WIDTH ) / 2,
(display.height() - LOGO_HEIGHT) / 2,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
display.display();
delay(1000);
}
#define XPOS 0
#define YPOS 1
#define DELTAY 2
//############################
//设置位图动画 testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT);
//############################
void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
int8_t f, icons[NUMFLAKES][3];
// 初始化雪花片的位置
for(f=0; f< NUMFLAKES; f++) {
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
Serial.print(F("x: "));
Serial.print(icons[f][XPOS], DEC);
Serial.print(F(" y: "));
Serial.print(icons[f][YPOS], DEC);
Serial.print(F(" dy: "));
Serial.println(icons[f][DELTAY], DEC);
}
for(;;) { // 死循环
display.clearDisplay(); // 清除显示
// 绘制每个雪花
for(f=0; f< NUMFLAKES; f++) {
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
}
display.display(); // Show the display buffer on the screen
delay(200); // Pause for 1/10 second
// 更新每个雪花的坐标
for(f=0; f< NUMFLAKES; f++) {
icons[f][YPOS] += icons[f][DELTAY];
// 雪花落到底部
if (icons[f][YPOS] >= display.height()) {
// Reinitialize to a random position, just off the top
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
}
}
}
}
本例程是库文件中的示例程序,实现显示LOGO图片,完成画线,画圆,画矩形等图形的绘制,最后循环显示多片雪花下落的动画。
Mixly参考程序
此例程实现了再OLED显示屏上显示一个横向的三角符号,并在坐标位(40,30)处显示了一个变量的值,此变量将会每500ms自动加一。在显示过程中,当变量值小于等于10的时候,显示的横向三角形是向左的,大于10后,横向三角形变为向右显示。