功能介绍

OLED(Organic Light-Emitting Diode)显示屏是利用有机电自发光二极管制成的显示屏。由于同时具备自发光有机电激发光二极管,不需背光源、对比度高、厚度薄、视角广、反应速度快等优点。
0.96 OLED显示模块的显示尺寸是0.96寸,像素分辨率是128x64像素,可以用于显示数字、字母、汉字、图片等信息。0.96 OLED显示模块实物如图3.20.1所示。显示一个汉字的最小像素分辨率需要16x16像素,所以,128x64分辨率最多可以显示8x4个汉字。
image.pngimage.png
图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,在此默认就好,除非你知道如何设置显示屏上的地址选择跳线。
image.png
图3.20.2 OLED显示屏初始化程序模块
如图3.20.2所示,初始化模块下方还有一句语句“显示屏u8g2刷新显示页面page1”,这里的“page1”是我们实际需要显示的程序模块所在的地方,在展开的“显示屏”程序模块中,有一个紫色的程序块“page1”,如图3.20.3所示。默认程序块中有两条程序块,分别是设置显示的字体字号和显示的实际文本信息。在实际使用时,我们需要根据需要修改内部的程序实现我们所想要得显示效果,具体使用方法请参照参考程序。还有很多正对OLED显示屏的程序模块,比如汉字显示、图片显示、画圆、画线等基础的GUI程序模块,使用时可以根据需求自行选择。
image.png
图3.20.3 OLED显示程序模块

参考程序:

Arduino IDE参考程序

  1. /**************************************************************************
  2. *@mainpage Arduino库,用于基于SSD1306驱动程序的单色OLED。
  3. ------> http://www.adafruit.com/category/63_98
  4. 是一个基于SSD1306驱动程序的单色OLED示例
  5. **************************************************************************/
  6. #include <SPI.h>
  7. #include <Wire.h>
  8. #include <Adafruit_GFX.h>
  9. #include <Adafruit_SSD1306.h>
  10. #define SCREEN_WIDTH 128 // OLED 显示屏横向(宽)的像素点数量
  11. #define SCREEN_HEIGHT 64 // OLED 显示屏纵向(高)的像素点数量
  12. // 创建一个IIC接口的一个OLED对象,名称是display
  13. #define OLED_RESET 4 // Reset 引脚,默认就好
  14. Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  15. #define NUMFLAKES 10 // 动画示例中雪花的数量
  16. #define LOGO_HEIGHT 16
  17. #define LOGO_WIDTH 16
  18. static const unsigned char PROGMEM logo_bmp[] =
  19. { B00000000, B11000000,
  20. B00000001, B11000000,
  21. B00000001, B11000000,
  22. B00000011, B11100000,
  23. B11110011, B11100000,
  24. B11111110, B11111000,
  25. B01111110, B11111111,
  26. B00110011, B10011111,
  27. B00011111, B11111100,
  28. B00001101, B01110000,
  29. B00011011, B10100000,
  30. B00111111, B11100000,
  31. B00111111, B11110000,
  32. B01111100, B11110000,
  33. B01110000, B01110000,
  34. B00000000, B00110000 };
  35. void setup() {
  36. Serial.begin(9600);
  37. // 显示屏采用内部3.3V电压,IIC地址是0x3c
  38. if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) {
  39. Serial.println(F("SSD1306 allocation failed"));
  40. for(;;); // 如果失败,则一直循环,不会进入继续向下
  41. }
  42. // 显示缓冲区内的内容
  43. display.display();
  44. delay(2000);
  45. //清除缓冲区内容
  46. display.clearDisplay();
  47. //点亮两个像素点,白色(100,10)(101,10)
  48. display.drawPixel(100, 10, SSD1306_WHITE);
  49. display.drawPixel(101, 10, SSD1306_WHITE);
  50. // 显示缓冲区内容,需要调用display.display();
  51. display.display();
  52. delay(2000);
  53. testdrawline(); // 画线,很多线
  54. testdrawrect(); // 绘制矩形轮廓
  55. testfillrect(); // 绘制矩形(填充)
  56. testdrawcircle(); // 画圆(轮廓)
  57. testfillcircle(); // 画圆(填充)
  58. testdrawroundrect(); // 绘制圆角矩形(轮廓)
  59. testfillroundrect(); // 绘制圆角矩形(填充)
  60. testdrawtriangle(); // 绘制三角形(轮廓)
  61. testfilltriangle(); // 绘制三角形(填充)
  62. testdrawchar(); // 绘制默认字体的字符 ASICC码表显示
  63. testdrawstyles(); // 绘制“样例”字符
  64. testscrolltext(); // 显示滚动文本
  65. testdrawbitmap(); // 画一个小位图图像
  66. // 反转并恢复显示,中间暂停
  67. display.invertDisplay(true);
  68. delay(1000);
  69. display.invertDisplay(false);
  70. delay(1000);
  71. testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); //设置位图动画,内部已经循环
  72. }
  73. void loop() {
  74. }
  75. //############################
  76. // 画线,很多线
  77. //############################
  78. void testdrawline() {
  79. int16_t i;
  80. display.clearDisplay(); // 清除显示缓冲区
  81. for(i=0; i<display.width(); i+=4) {
  82. display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
  83. display.display(); // 更新显示
  84. delay(1);
  85. }
  86. for(i=0; i<display.height(); i+=4) {
  87. display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
  88. display.display();
  89. delay(1);
  90. }
  91. delay(250);
  92. display.clearDisplay();
  93. for(i=0; i<display.width(); i+=4) {
  94. display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
  95. display.display();
  96. delay(1);
  97. }
  98. for(i=display.height()-1; i>=0; i-=4) {
  99. display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
  100. display.display();
  101. delay(1);
  102. }
  103. delay(250);
  104. display.clearDisplay();
  105. for(i=display.width()-1; i>=0; i-=4) {
  106. display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
  107. display.display();
  108. delay(1);
  109. }
  110. for(i=display.height()-1; i>=0; i-=4) {
  111. display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
  112. display.display();
  113. delay(1);
  114. }
  115. delay(250);
  116. display.clearDisplay();
  117. for(i=0; i<display.height(); i+=4) {
  118. display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
  119. display.display();
  120. delay(1);
  121. }
  122. for(i=0; i<display.width(); i+=4) {
  123. display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
  124. display.display();
  125. delay(1);
  126. }
  127. delay(2000); // Pause for 2 seconds
  128. }
  129. //###########################
  130. // 绘制矩形轮廓testdrawrect();
  131. //###########################
  132. void testdrawrect(void) {
  133. display.clearDisplay();
  134. for(int16_t i=0; i<display.height()/2; i+=2) {
  135. display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
  136. display.display(); // Update screen with each newly-drawn rectangle
  137. delay(1);
  138. }
  139. delay(2000);
  140. }
  141. //###########################
  142. // testfillrect(); // 绘制矩形(填充)
  143. //###########################
  144. void testfillrect(void) {
  145. display.clearDisplay();
  146. for(int16_t i=0; i<display.height()/2; i+=3) {
  147. // 使用反向颜色,使矩形交替为白色/黑色
  148. display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
  149. display.display();
  150. delay(1);
  151. }
  152. delay(2000);
  153. }
  154. //############################
  155. // 画圆(轮廓) testdrawcircle();
  156. //############################
  157. void testdrawcircle(void) {
  158. display.clearDisplay();
  159. for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
  160. display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
  161. display.display();
  162. delay(1);
  163. }
  164. delay(2000);
  165. }
  166. //############################
  167. // 画圆(填充) testfillcircle();
  168. //############################
  169. void testfillcircle(void) {
  170. display.clearDisplay();
  171. for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
  172. // 反转色,实现黑白显示
  173. display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
  174. display.display();
  175. delay(1);
  176. }
  177. delay(2000);
  178. }
  179. //############################
  180. // 绘制圆角矩形(轮廓) testdrawroundrect();
  181. //############################
  182. void testdrawroundrect(void) {
  183. display.clearDisplay();
  184. for(int16_t i=0; i<display.height()/2-2; i+=2) {
  185. display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
  186. display.height()/4, SSD1306_WHITE);
  187. display.display();
  188. delay(1);
  189. }
  190. delay(2000);
  191. }
  192. //############################
  193. // 绘制圆角矩形(填充)testfillroundrect();
  194. //############################
  195. void testfillroundrect(void) {
  196. display.clearDisplay();
  197. for(int16_t i=0; i<display.height()/2-2; i+=2) {
  198. // 使用反向颜色,黑白交替显示
  199. display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
  200. display.height()/4, SSD1306_INVERSE);
  201. display.display();
  202. delay(1);
  203. }
  204. delay(2000);
  205. }
  206. //############################
  207. // 绘制三角形(轮廓) testdrawtriangle();
  208. //############################
  209. void testdrawtriangle(void) {
  210. display.clearDisplay();
  211. for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
  212. display.drawTriangle(
  213. display.width()/2 , display.height()/2-i,
  214. display.width()/2-i, display.height()/2+i,
  215. display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
  216. display.display();
  217. delay(1);
  218. }
  219. delay(2000);
  220. }
  221. //############################
  222. // 绘制三角形(填充) testfilltriangle();
  223. //############################
  224. void testfilltriangle(void) {
  225. display.clearDisplay();
  226. for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
  227. // 使用反向颜色,使三角形交替为白色/黑色
  228. display.fillTriangle(
  229. display.width()/2 , display.height()/2-i,
  230. display.width()/2-i, display.height()/2+i,
  231. display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
  232. display.display();
  233. delay(1);
  234. }
  235. delay(2000);
  236. }
  237. //############################
  238. // 绘制默认字体的字符 ASICC码表显示 testdrawchar();
  239. //############################
  240. void testdrawchar(void) {
  241. display.clearDisplay();
  242. display.setTextSize(1); // 显示字号1
  243. display.setTextColor(SSD1306_WHITE); // 白色显示
  244. display.setCursor(0, 0); // 初始坐标
  245. display.cp437(true); // 使用完整的256字符“代码页437”字体
  246. // Not all the characters will fit on the display. This is normal.
  247. // Library will draw what it can and the rest will be clipped.
  248. for(int16_t i=0; i<256; i++) {
  249. if(i == '\n') display.write(' ');
  250. else display.write(i);
  251. }
  252. display.display();
  253. delay(2000);
  254. }
  255. //############################
  256. // 显示ASICC字符 testdrawstyles();
  257. //############################
  258. void testdrawstyles(void) {
  259. display.clearDisplay();
  260. display.setTextSize(1); // 显示字号1
  261. display.setTextColor(SSD1306_WHITE); // 白色显示
  262. display.setCursor(0,0); // 显示起始坐标
  263. display.println(F("Hello, world!"));
  264. display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // 显示反向文本
  265. display.println(3.141592,7);//显示3.14,7个有效数字
  266. display.setTextSize(2); // 显示字号2
  267. display.setTextColor(SSD1306_WHITE);
  268. //显示十六进制数
  269. display.print(F("0x"));
  270. display.println(0xDEADBEEF, HEX);
  271. display.display();
  272. delay(2000);
  273. }
  274. //############################
  275. // 显示滚动文本 testscrolltext();
  276. //############################
  277. void testscrolltext(void) {
  278. display.clearDisplay();
  279. display.setTextSize(2); // 显示字号为2
  280. display.setTextColor(SSD1306_WHITE);
  281. display.setCursor(0, 0);//起始显示坐标
  282. display.println(F("Arduino"));
  283. display.display(); // Show initial text
  284. delay(100);
  285. // 滚动显示
  286. display.startscrollright(0x00, 0x0f);
  287. delay(2000);
  288. display.stopscroll();
  289. delay(1000);
  290. display.startscrollleft(0x00, 0x0f);
  291. delay(2000);
  292. display.stopscroll();
  293. delay(1000);
  294. display.startscrolldiagright(0x00, 0x07);
  295. delay(2000);
  296. display.startscrolldiagleft(0x00, 0x07);
  297. delay(2000);
  298. display.stopscroll();
  299. delay(1000);
  300. }
  301. //############################
  302. // 画一个小位图图像 testdrawbitmap();
  303. //############################
  304. void testdrawbitmap(void) {
  305. display.clearDisplay();
  306. display.drawBitmap(
  307. (display.width() - LOGO_WIDTH ) / 2,
  308. (display.height() - LOGO_HEIGHT) / 2,
  309. logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  310. display.display();
  311. delay(1000);
  312. }
  313. #define XPOS 0
  314. #define YPOS 1
  315. #define DELTAY 2
  316. //############################
  317. //设置位图动画 testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT);
  318. //############################
  319. void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  320. int8_t f, icons[NUMFLAKES][3];
  321. // 初始化雪花片的位置
  322. for(f=0; f< NUMFLAKES; f++) {
  323. icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
  324. icons[f][YPOS] = -LOGO_HEIGHT;
  325. icons[f][DELTAY] = random(1, 6);
  326. Serial.print(F("x: "));
  327. Serial.print(icons[f][XPOS], DEC);
  328. Serial.print(F(" y: "));
  329. Serial.print(icons[f][YPOS], DEC);
  330. Serial.print(F(" dy: "));
  331. Serial.println(icons[f][DELTAY], DEC);
  332. }
  333. for(;;) { // 死循环
  334. display.clearDisplay(); // 清除显示
  335. // 绘制每个雪花
  336. for(f=0; f< NUMFLAKES; f++) {
  337. display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
  338. }
  339. display.display(); // Show the display buffer on the screen
  340. delay(200); // Pause for 1/10 second
  341. // 更新每个雪花的坐标
  342. for(f=0; f< NUMFLAKES; f++) {
  343. icons[f][YPOS] += icons[f][DELTAY];
  344. // 雪花落到底部
  345. if (icons[f][YPOS] >= display.height()) {
  346. // Reinitialize to a random position, just off the top
  347. icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
  348. icons[f][YPOS] = -LOGO_HEIGHT;
  349. icons[f][DELTAY] = random(1, 6);
  350. }
  351. }
  352. }
  353. }

本例程是库文件中的示例程序,实现显示LOGO图片,完成画线,画圆,画矩形等图形的绘制,最后循环显示多片雪花下落的动画。

Mixly参考程序

image.png
此例程实现了再OLED显示屏上显示一个横向的三角符号,并在坐标位(40,30)处显示了一个变量的值,此变量将会每500ms自动加一。在显示过程中,当变量值小于等于10的时候,显示的横向三角形是向左的,大于10后,横向三角形变为向右显示。