QQ技术互动交流群:ESP8266&32 物联网开发 群号622368884,不喜勿喷

单片机菜鸟博哥CSDN

1.前言

SSD1306屏幕驱动库,最出名应该就是u8g2,读者可以参考 玩转u8g2 OLED库,一篇就够

但是u8g2有个弊端就是:一个超级庞大的第三方库,性能并不是非常好(但是基本上支持了市面上绝大部分的LED屏)。

我们这里深入学习 Adafruit_GFXAdafruit_SSD1306

那么,读者可能就有疑问了?Adafruit_SSD1306是什么鬼?

  • Adafruit_SSD1306 是针对 SSD1306这款OLED屏幕的显示图形库

那么,Adafruit_GFX又是什么鬼?它和Adafruit_SSD1306之间有什么关系呢?博哥直接翻阅了官网解析,读者可以点击查看 官网解析

博哥这里截取了最关键的解析:

  • Arduino的Adafruit_GFX库为我们所有的LCD和OLED显示器提供了通用语法和图形功能集,也就是说这是一个通用图形库,并不针对特定的显示器型号,它是父类
  • Adafruit_GFX库始终与每种特定显示类型唯一的附加库一起使用,子类库依赖父类库-例如,ST7735 1.8英寸彩色LCD需要安装Adafruit_GFX,Adafruit_ZeroDMA 和 Adafruit_ST7735库。以下库现在以这种方式运行:

    当然,博主也去查阅了Adafruit_SSD1306源码,也是证明了上面两点说明:

    Adafruit_GFX 定义了一系列的绘画方法(线,矩形,圆....),属于基础类,并且最重要的一点,drawPixel方法由子类来实现。

    Adafruit_SSD1306 定义了一系列跟SSD1306有关的方法,并且重写了drawPixel方法,属于扩展类。

综上两点,要想使用这个Adafruit_SSD1306库功能,必须同时安装 Adafruit_GFX 和 Adafruit_SSD1306

2.Arduino 安装 Adafruit_SSD1306

工欲善其事,必先利其器,我们首先安装库。

2.1 安装 Adafruit_GFX

  • Adafruit_GFX库可以使用安装Arduino的库管理。从Arduino的“草图”菜单中,选择“包含库”,然后选择“管理库…”
  • 在搜索字段中键入“ gfx”以快速找到它:

2.2 安装 Adafruit_SSD1306

  • 在搜索字段中键入“ ssd1306”以快速找到它:

    接下来,我们就可以深入学习该库了。

3.库方法

在讲解之前,博哥非常强调两个重要意识点:

  • 无论什么OLED屏幕,最终都可以抽象为像素点阵,想显示什么内容就把具体位置的像素点亮起来。比如SSD1306-12864就是一个128X64像素点阵。
  • 在坐标系中,左上角是原点,向右是X轴,向下是Y轴。

    接下来,开始方法讲解。

3.1 初始化方法

3.1.1 Adafruit_SSD1306—— 初始化构造器

SSD1306包括IIC和SPI总线版本,所以针对不同版本又有对应的构造器方法

3.1.1.1 IIC版本

函数1说明

  1. /*!
  2. @brief Constructor for I2C-interfaced SSD1306 displays.
  3. @param w
  4. Display width in pixels(屏幕宽度像素)
  5. @param h
  6. Display height in pixels(屏幕高度像素)
  7. @param twi(IIC总线实例)
  8. Pointer to an existing TwoWire instance (e.g. &Wire, the
  9. microcontroller's primary I2C bus).
  10. @param rst_pin
  11. Reset pin (using Arduino pin numbering), or -1 if not used
  12. (some displays might be wired to share the microcontroller's
  13. reset pin).
  14. @param clkDuring(SSD1306库调用期间的传输速率)
  15. Speed (in Hz) for Wire transmissions in SSD1306 library calls.
  16. Defaults to 400000 (400 KHz), a known 'safe' value for most
  17. microcontrollers, and meets the SSD1306 datasheet spec.
  18. Some systems can operate I2C faster (800 KHz for ESP32, 1 MHz
  19. for many other 32-bit MCUs), and some (perhaps not all)
  20. SSD1306's can work with this -- so it's optionally be specified
  21. here and is not a default behavior. (Ignored if using pre-1.5.7
  22. Arduino software, which operates I2C at a fixed 100 KHz.)
  23. @param clkAfter(SSD1306库非调用期间的传输速率,为了兼容IIC总线上的其他设备)
  24. Speed (in Hz) for Wire transmissions following SSD1306 library
  25. calls. Defaults to 100000 (100 KHz), the default Arduino Wire
  26. speed. This is done rather than leaving it at the 'during' speed
  27. because other devices on the I2C bus might not be compatible
  28. with the faster rate. (Ignored if using pre-1.5.7 Arduino
  29. software, which operates I2C at a fixed 100 KHz.)
  30. @return Adafruit_SSD1306 object.
  31. @note Call the object's begin() function before use -- buffer
  32. allocation is performed there!
  33. */
  34. Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi=&Wire, int8_t rst_pin=-1,
  35. uint32_t clkDuring=400000UL, uint32_t clkAfter=100000UL);

用法

  1. #include <SPI.h>
  2. #include <Wire.h>
  3. #include <Adafruit_GFX.h>
  4. #include <Adafruit_SSD1306.h>
  5. //屏幕分辨率
  6. #define SCREEN_WIDTH 128 // OLED display width, in pixels
  7. #define SCREEN_HEIGHT 64 // OLED display height, in pixels
  8. // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
  9. #define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
  10. Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
3.1.1.2 SPI版本

函数1说明

  1. /*!
  2. @brief Constructor for SPI SSD1306 displays, using software (bitbang)
  3. SPI.(软件SPI总线)
  4. @param w
  5. Display width in pixels
  6. @param h
  7. Display height in pixels
  8. @param mosi_pin
  9. MOSI (master out, slave in) pin (using Arduino pin numbering).
  10. This transfers serial data from microcontroller to display.
  11. @param sclk_pin
  12. SCLK (serial clock) pin (using Arduino pin numbering).
  13. This clocks each bit from MOSI.
  14. @param dc_pin
  15. Data/command pin (using Arduino pin numbering), selects whether
  16. display is receiving commands (low) or data (high).
  17. @param rst_pin
  18. Reset pin (using Arduino pin numbering), or -1 if not used
  19. (some displays might be wired to share the microcontroller's
  20. reset pin).
  21. @param cs_pin
  22. Chip-select pin (using Arduino pin numbering) for sharing the
  23. bus with other devices. Active low.
  24. @return Adafruit_SSD1306 object.
  25. @note Call the object's begin() function before use -- buffer
  26. allocation is performed there!
  27. */
  28. Adafruit_SSD1306(uint8_t w, uint8_t h, int8_t mosi_pin, int8_t sclk_pin,
  29. int8_t dc_pin, int8_t rst_pin, int8_t cs_pin);
  30. /*!
  31. @brief Constructor for SPI SSD1306 displays, using native hardware SPI.(硬件SPI总线)
  32. @param w
  33. Display width in pixels
  34. @param h
  35. Display height in pixels
  36. @param spi
  37. Pointer to an existing SPIClass instance (e.g. &SPI, the
  38. microcontroller's primary SPI bus).
  39. @param dc_pin
  40. Data/command pin (using Arduino pin numbering), selects whether
  41. display is receiving commands (low) or data (high).
  42. @param rst_pin
  43. Reset pin (using Arduino pin numbering), or -1 if not used
  44. (some displays might be wired to share the microcontroller's
  45. reset pin).
  46. @param cs_pin
  47. Chip-select pin (using Arduino pin numbering) for sharing the
  48. bus with other devices. Active low.
  49. @param bitrate
  50. SPI clock rate for transfers to this display. Default if
  51. unspecified is 8000000UL (8 MHz).
  52. @return Adafruit_SSD1306 object.
  53. @note Call the object's begin() function before use -- buffer
  54. allocation is performed there!
  55. */
  56. Adafruit_SSD1306(uint8_t w, uint8_t h, SPIClass *spi,
  57. int8_t dc_pin, int8_t rst_pin, int8_t cs_pin, uint32_t bitrate=8000000UL);

用法1:

  1. #include <SPI.h>
  2. #include <Wire.h>
  3. #include <Adafruit_GFX.h>
  4. #include <Adafruit_SSD1306.h>
  5. #define SCREEN_WIDTH 128 // OLED display width, in pixels
  6. #define SCREEN_HEIGHT 64 // OLED display height, in pixels
  7. // 软件SPI总线
  8. // Declaration for SSD1306 display connected using software SPI (default case):
  9. #define OLED_MOSI 9
  10. #define OLED_CLK 10
  11. #define OLED_DC 11
  12. #define OLED_CS 12
  13. #define OLED_RESET 13
  14. Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  15. OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

用法2

  1. //硬件spi总线
  2. #define OLED_DC 6
  3. #define OLED_CS 7
  4. #define OLED_RESET 8
  5. Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  6. &SPI, OLED_DC, OLED_RESET, OLED_CS);

3.1.2 OLED初始化方法

3.1.2.1 begin方法

函数说明

  1. // ALLOCATE & INIT DISPLAY -------------------------------------------------
  2. // 分配内存和初始化屏幕
  3. /*!
  4. @brief Allocate RAM for image buffer, initialize peripherals and pins.
  5. @param vcs
  6. VCC selection. Pass SSD1306_SWITCHCAPVCC to generate the display
  7. voltage (step up) from the 3.3V source, or SSD1306_EXTERNALVCC
  8. otherwise. Most situations with Adafruit SSD1306 breakouts will
  9. want SSD1306_SWITCHCAPVCC.
  10. @param addr
  11. I2C address of corresponding SSD1306 display (or pass 0 to use
  12. default of 0x3C for 128x32 display, 0x3D for all others).
  13. SPI displays (hardware or software) do not use addresses, but
  14. this argument is still required (pass 0 or any value really,
  15. it will simply be ignored). Default if unspecified is 0.
  16. @param reset
  17. If true, and if the reset pin passed to the constructor is
  18. valid, a hard reset will be performed before initializing the
  19. display. If using multiple SSD1306 displays on the same bus, and
  20. if they all share the same reset pin, you should only pass true
  21. on the first display being initialized, false on all others,
  22. else the already-initialized displays would be reset. Default if
  23. unspecified is true.
  24. @param periphBegin
  25. If true, and if a hardware peripheral is being used (I2C or SPI,
  26. but not software SPI), call that peripheral's begin() function,
  27. else (false) it has already been done in one's sketch code.
  28. Cases where false might be used include multiple displays or
  29. other devices sharing a common bus, or situations on some
  30. platforms where a nonstandard begin() function is available
  31. (e.g. a TwoWire interface on non-default pins, as can be done
  32. on the ESP8266 and perhaps others).
  33. @return true on successful allocation/init, false otherwise.
  34. Well-behaved code should check the return value before
  35. proceeding.
  36. @note MUST call this function before any drawing or updates!
  37. */
  38. boolean Adafruit_SSD1306::begin(uint8_t switchvcc=SSD1306_SWITCHCAPVCC,
  39. uint8_t i2caddr=0, boolean reset=true,
  40. boolean periphBegin=true) {
  41. // 分配内存空间 空间大小为 WIDTH * ((HEIGHT + 7) / 8),这里做了一个向上取8的倍数
  42. if((!buffer) && !(buffer = (uint8_t *)malloc(WIDTH * ((HEIGHT + 7) / 8))))
  43. return false;
  44. //把Buffer清零,其实就是把OLED对应的缓存(缓存对应点阵数据)清掉
  45. clearDisplay();
  46. // 显示一个启动图形....
  47. if(HEIGHT > 32) {
  48. drawBitmap((WIDTH - splash1_width) / 2, (HEIGHT - splash1_height) / 2,
  49. splash1_data, splash1_width, splash1_height, 1);
  50. } else {
  51. drawBitmap((WIDTH - splash2_width) / 2, (HEIGHT - splash2_height) / 2,
  52. splash2_data, splash2_width, splash2_height, 1);
  53. }
  54. vccstate = vcs;
  55. // Setup pin directions 配置引脚
  56. // I2C总线
  57. if(wire) { // Using I2C
  58. // If I2C address is unspecified, use default
  59. // (0x3C for 32-pixel-tall displays, 0x3D for all others).
  60. i2caddr = addr ? addr : ((HEIGHT == 32) ? 0x3C : 0x3D);
  61. // TwoWire begin() function might be already performed by the calling
  62. // function if it has unusual circumstances (e.g. TWI variants that
  63. // can accept different SDA/SCL pins, or if two SSD1306 instances
  64. // with different addresses -- only a single begin() is needed).
  65. if(periphBegin) wire->begin();
  66. } else { // Using one of the SPI modes, either soft or hardware
  67. // SPI总线
  68. pinMode(dcPin, OUTPUT); // Set data/command pin as output
  69. pinMode(csPin, OUTPUT); // Same for chip select
  70. #ifdef HAVE_PORTREG
  71. dcPort = (PortReg *)portOutputRegister(digitalPinToPort(dcPin));
  72. dcPinMask = digitalPinToBitMask(dcPin);
  73. csPort = (PortReg *)portOutputRegister(digitalPinToPort(csPin));
  74. csPinMask = digitalPinToBitMask(csPin);
  75. #endif
  76. // #define SSD1306_SELECT *csPort &= ~csPinMask; ///< Device select
  77. // #define SSD1306_SELECT digitalWrite(csPin, LOW); ///< Device select
  78. SSD1306_DESELECT
  79. if(spi) { // Hardware SPI 硬件spi
  80. // SPI peripheral begin same as wire check above.
  81. if(periphBegin) spi->begin();
  82. } else { // Soft SPI 软件spi
  83. pinMode(mosiPin, OUTPUT); // MOSI and SCLK outputs
  84. pinMode(clkPin , OUTPUT);
  85. #ifdef HAVE_PORTREG
  86. mosiPort = (PortReg *)portOutputRegister(digitalPinToPort(mosiPin));
  87. mosiPinMask = digitalPinToBitMask(mosiPin);
  88. clkPort = (PortReg *)portOutputRegister(digitalPinToPort(clkPin));
  89. clkPinMask = digitalPinToBitMask(clkPin);
  90. *clkPort &= ~clkPinMask; // Clock low
  91. #else
  92. digitalWrite(clkPin, LOW); // Clock low
  93. #endif
  94. }
  95. }
  96. // Reset SSD1306 if requested and reset pin specified in constructor
  97. if(reset && (rstPin >= 0)) {
  98. pinMode( rstPin, OUTPUT);
  99. digitalWrite(rstPin, HIGH);
  100. delay(1); // VDD goes high at start, pause for 1 ms
  101. digitalWrite(rstPin, LOW); // Bring reset low
  102. delay(10); // Wait 10 ms
  103. digitalWrite(rstPin, HIGH); // Bring out of reset
  104. }
  105. // 开启事务操作
  106. // #define SPI_TRANSACTION_START spi->beginTransaction(spiSettings) ///< Pre-SPI
  107. TRANSACTION_START
  108. // 以下一系列是一系列控制命令
  109. // Init sequence
  110. static const uint8_t PROGMEM init1[] = {
  111. SSD1306_DISPLAYOFF, // 0xAE 关显示
  112. SSD1306_SETDISPLAYCLOCKDIV, // 0xD5 设置显示时钟分频率、振荡器频率
  113. 0x80, // the suggested ratio 0x80 A[3:0]:分频频率1到16,A[7:4]频率
  114. SSD1306_SETMULTIPLEX }; // 0xA8 duty设置
  115. ssd1306_commandList(init1, sizeof(init1));
  116. ssd1306_command1(HEIGHT - 1);
  117. static const uint8_t PROGMEM init2[] = {
  118. SSD1306_SETDISPLAYOFFSET, // 0xD3 显示偏移
  119. 0x0, // no offset 不偏移
  120. SSD1306_SETSTARTLINE | 0x0, // line #0 起始行 40~7F
  121. SSD1306_CHARGEPUMP }; // 0x8D 升压允许
  122. ssd1306_commandList(init2, sizeof(init2));
  123. ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0x14);
  124. static const uint8_t PROGMEM init3[] = {
  125. SSD1306_MEMORYMODE, // 0x20 设置内存地址模式
  126. 0x00, // 0x0 act like ks0108 00水平地址模式,01垂直模式,02页地址模式
  127. SSD1306_SEGREMAP | 0x1, //列扫描顺序:从左到右a1
  128. SSD1306_COMSCANDEC };//行扫描顺序:从上到下c8
  129. ssd1306_commandList(init3, sizeof(init3));
  130. // 这里可以看到 支持 128X32 128X64 96X16 这三款SSD1306
  131. if((WIDTH == 128) && (HEIGHT == 32)) {
  132. static const uint8_t PROGMEM init4a[] = {
  133. SSD1306_SETCOMPINS, // 0xDA
  134. 0x02,
  135. SSD1306_SETCONTRAST, // 0x81
  136. 0x8F };
  137. ssd1306_commandList(init4a, sizeof(init4a));
  138. } else if((WIDTH == 128) && (HEIGHT == 64)) {
  139. static const uint8_t PROGMEM init4b[] = {
  140. SSD1306_SETCOMPINS, // 0xDA
  141. 0x12,
  142. SSD1306_SETCONTRAST }; // 0x81
  143. ssd1306_commandList(init4b, sizeof(init4b));
  144. ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF);
  145. } else if((WIDTH == 96) && (HEIGHT == 16)) {
  146. static const uint8_t PROGMEM init4c[] = {
  147. SSD1306_SETCOMPINS, // 0xDA
  148. 0x2, // ada x12
  149. SSD1306_SETCONTRAST }; // 0x81
  150. ssd1306_commandList(init4c, sizeof(init4c));
  151. ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0xAF);
  152. } else {
  153. // Other screen varieties -- TBD
  154. }
  155. ssd1306_command1(SSD1306_SETPRECHARGE); // 0xd9 Set Pre-Charge Period
  156. ssd1306_command1((vccstate == SSD1306_EXTERNALVCC) ? 0x22 : 0xF1);
  157. static const uint8_t PROGMEM init5[] = {
  158. SSD1306_SETVCOMDETECT, // 0xDB //Set VCOMH Deselect Level
  159. 0x40,
  160. SSD1306_DISPLAYALLON_RESUME, // 0xA4
  161. SSD1306_NORMALDISPLAY, // 0xA6
  162. SSD1306_DEACTIVATE_SCROLL,
  163. SSD1306_DISPLAYON }; // Main screen turn on //开显示
  164. ssd1306_commandList(init5, sizeof(init5));
  165. // 事务结束 执行这个过程中的操作 基本上都是SSD1306寄存器命令操作
  166. TRANSACTION_END
  167. return true; // Success
  168. }

注意点

  • 这里的buffer对应的是arduino上的RAM,并非SSD1306上显示的RAM,需要严格区分;
  • 仅仅支持 128X32 128X64 96X16 这三款SSD1306;
  • 此方法必须成功,否则表示整个模块无法使用,无法使用可能就需要检测硬件模块;

3.2 显示类方法

3.2.1 clearDisplay——清除显示

函数说明

  1. /*!
  2. @brief Clear contents of display buffer (set all pixels to off).
  3. @return None (void).
  4. @note Changes buffer contents only, no immediate effect on display.
  5. Follow up with a call to display(), or with other graphics
  6. commands as needed by one's own application.
  7. */
  8. void Adafruit_SSD1306::clearDisplay(void) {
  9. memset(buffer, 0, WIDTH * ((HEIGHT + 7) / 8));
  10. }

注意点

  • 此方法仅仅是清除Arduino缓存,不会立即显示在display上,可以通过调用display来立即清除;

    3.2.2 display——显示内容

    函数说明

  1. /*!
  2. @brief Push data currently in RAM to SSD1306 display.
  3. @return None (void).
  4. @note Drawing operations are not visible until this function is
  5. called. Call after each graphics command, or after a whole set
  6. of graphics commands, as best needed by one's own application.
  7. */
  8. void Adafruit_SSD1306::display(void) {
  9. TRANSACTION_START
  10. // 以下是一堆页面操作
  11. static const uint8_t PROGMEM dlist1[] = {
  12. SSD1306_PAGEADDR,
  13. 0, // Page start address
  14. 0xFF, // Page end (not really, but works here)
  15. SSD1306_COLUMNADDR,
  16. 0 }; // Column start address
  17. ssd1306_commandList(dlist1, sizeof(dlist1));
  18. ssd1306_command1(WIDTH - 1); // Column end address
  19. // 这里针对8266做了处理 也就是 8266可以用了哈哈哈
  20. #if defined(ESP8266)
  21. // ESP8266 needs a periodic yield() call to avoid watchdog reset.
  22. // With the limited size of SSD1306 displays, and the fast bitrate
  23. // being used (1 MHz or more), I think one yield() immediately before
  24. // a screen write and one immediately after should cover it. But if
  25. // not, if this becomes a problem, yields() might be added in the
  26. // 32-byte transfer condition below.
  27. yield();
  28. #endif
  29. // 往ssd1306 ram写数据
  30. uint16_t count = WIDTH * ((HEIGHT + 7) / 8);
  31. uint8_t *ptr = buffer;
  32. if(wire) { // I2C
  33. wire->beginTransmission(i2caddr);
  34. WIRE_WRITE((uint8_t)0x40);
  35. uint8_t bytesOut = 1;
  36. while(count--) {
  37. if(bytesOut >= WIRE_MAX) {
  38. wire->endTransmission();
  39. wire->beginTransmission(i2caddr);
  40. WIRE_WRITE((uint8_t)0x40);
  41. bytesOut = 1;
  42. }
  43. WIRE_WRITE(*ptr++);
  44. bytesOut++;
  45. }
  46. wire->endTransmission();
  47. } else { // SPI
  48. SSD1306_MODE_DATA
  49. while(count--) SPIwrite(*ptr++);
  50. }
  51. TRANSACTION_END
  52. #if defined(ESP8266)
  53. yield();
  54. #endif
  55. }

注意点

  • 这个方法才是真正把绘制内容画在display上(非常重要)

3.3 绘制类方法

上面介绍了显示类方法,那么到底要显示什么内容呢?接下来就是构造显示内容,这些都是绘制类方法的控制范围了。绘制类方法,博哥理解为影响绘制过程的一系列操作。

绘制类方法分为父类绘制方法(Adafruit_GFX内部实现,子类不需要重写,直接调用)以及子类绘制方法(Adafruit_SSD1306实现)。

Adafruit_GFX 绘制类方法包括:

  • drawCircle——绘制空心圆
  • fillCircle——绘制实心圆
  • drawTriangle——绘制空心三角形
  • fillTriangle——绘制实心三角形
  • drawRoundRect——绘制空心圆角方形
  • fillRoundRect——绘制实心圆角方形
  • drawBitmap——绘制图片
  • drawXBitmap
  • drawGrayscaleBitmap
  • drawRGBBitmap
  • drawChar——绘制字符
  • getTextBounds
  • setTextSize
  • setFont
  • setCursor
  • setTextColor
  • setTextWrap

Adafruit_SSD1306绘制类方法包括:

  • drawPixel——绘制像素点
  • drawFastHLine——绘制水平线
  • drawFastVLine——绘制垂直线
  • startscrollright
  • startscrollleft
  • startscrolldiagright
  • startscrolldiagleft
  • stopscroll

3.3.1 drawPixel —— 绘制像素点

函数说明

  1. /*!
  2. @brief Set(设置)/clear(清除)/invert(反转) a single pixel. This is also invoked by the
  3. Adafruit_GFX library in generating many higher-level graphics
  4. primitives.
  5. @param x(x坐标,列坐标)
  6. Column of display -- 0 at left to (screen width - 1) at right.
  7. @param y(y坐标,行坐标)
  8. Row of display -- 0 at top to (screen height -1) at bottom.
  9. @param color(绘制颜色)
  10. Pixel color, one of: SSD1306_BLACK, SSD1306_WHITE or SSD1306_INVERT.
  11. @return None (void).
  12. @note Changes buffer contents only, no immediate effect on display.
  13. Follow up with a call to display(), or with other graphics
  14. commands as needed by one's own application.
  15. */
  16. void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) {
  17. if((x >= 0) && (x < width()) && (y >= 0) && (y < height())) {
  18. // Pixel is in-bounds. Rotate coordinates if needed.
  19. // 判断旋转角度
  20. switch(getRotation()) {
  21. case 1:
  22. ssd1306_swap(x, y);
  23. x = WIDTH - x - 1;
  24. break;
  25. case 2:
  26. x = WIDTH - x - 1;
  27. y = HEIGHT - y - 1;
  28. break;
  29. case 3:
  30. ssd1306_swap(x, y);
  31. y = HEIGHT - y - 1;
  32. break;
  33. }
  34. switch(color) {
  35. //修改对应的buffer
  36. case SSD1306_WHITE: buffer[x + (y/8)*WIDTH] |= (1 << (y&7)); break;
  37. case SSD1306_BLACK: buffer[x + (y/8)*WIDTH] &= ~(1 << (y&7)); break;
  38. case SSD1306_INVERSE: buffer[x + (y/8)*WIDTH] ^= (1 << (y&7)); break;
  39. }
  40. }
  41. }

注意点

  • 此方法只是改变arduino上的buffer缓存,并不会显示在display上面;

3.3.2 drawFastHLine —— 绘制水平线

函数说明

  1. /*!
  2. 绘制一条水平线,x,y为出发点,w为长度,color为颜色
  3. @brief Draw a horizontal line. This is also invoked by the Adafruit_GFX
  4. library in generating many higher-level graphics primitives.
  5. @param x
  6. Leftmost column -- 0 at left to (screen width - 1) at right.
  7. @param y
  8. Row of display -- 0 at top to (screen height -1) at bottom.
  9. @param w
  10. Width of line, in pixels.
  11. @param color
  12. Line color, one of: SSD1306_BLACK, SSD1306_WHITE or SSD1306_INVERT.
  13. @return None (void).
  14. @note Changes buffer contents only, no immediate effect on display.
  15. Follow up with a call to display(), or with other graphics
  16. commands as needed by one's own application.
  17. */
  18. void Adafruit_SSD1306::drawFastHLine(
  19. int16_t x, int16_t y, int16_t w, uint16_t color) {
  20. boolean bSwap = false;
  21. switch(rotation) {
  22. case 1:
  23. // 90 degree rotation, swap x & y for rotation, then invert x
  24. bSwap = true;
  25. ssd1306_swap(x, y);
  26. x = WIDTH - x - 1;
  27. break;
  28. case 2:
  29. // 180 degree rotation, invert x and y, then shift y around for height.
  30. x = WIDTH - x - 1;
  31. y = HEIGHT - y - 1;
  32. x -= (w-1);
  33. break;
  34. case 3:
  35. // 270 degree rotation, swap x & y for rotation,
  36. // then invert y and adjust y for w (not to become h)
  37. bSwap = true;
  38. ssd1306_swap(x, y);
  39. y = HEIGHT - y - 1;
  40. y -= (w-1);
  41. break;
  42. }
  43. // 这里才是真正的绘制方法 因为涉及到旋转角度,如果旋转了90度意味着变成了竖直线
  44. if(bSwap) drawFastVLineInternal(x, y, w, color);
  45. else drawFastHLineInternal(x, y, w, color);
  46. }
  47. /**
  48. * 绘制水平线
  49. */
  50. void Adafruit_SSD1306::drawFastHLineInternal(
  51. int16_t x, int16_t y, int16_t w, uint16_t color) {
  52. //判断y是不是在有效范围
  53. if((y >= 0) && (y < HEIGHT)) { // Y coord in bounds?
  54. //裁剪左边,重新计算宽度
  55. if(x < 0) { // Clip left
  56. w += x;
  57. x = 0;
  58. }
  59. //裁剪右边 重新计算宽度
  60. if((x + w) > WIDTH) { // Clip right
  61. w = (WIDTH - x);
  62. }
  63. // 处理buffer缓冲区数据
  64. if(w > 0) { // Proceed only if width is positive
  65. uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x],
  66. mask = 1 << (y & 7);
  67. switch(color) {
  68. case SSD1306_WHITE: while(w--) { *pBuf++ |= mask; }; break;
  69. case SSD1306_BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break;
  70. case SSD1306_INVERSE: while(w--) { *pBuf++ ^= mask; }; break;
  71. }
  72. }
  73. }
  74. }

3.3.3 drawFastVLine—— 绘制竖直线

函数说明

  1. /*!
  2. 绘制一条竖直线,x,y表示起点,h表示高度,color表示颜色
  3. @brief Draw a vertical line. This is also invoked by the Adafruit_GFX
  4. library in generating many higher-level graphics primitives.
  5. @param x
  6. Column of display -- 0 at left to (screen width -1) at right.
  7. @param y
  8. Topmost row -- 0 at top to (screen height - 1) at bottom.
  9. @param h
  10. Height of line, in pixels.
  11. @param color
  12. Line color, one of: SSD1306_BLACK, SSD1306_WHITE or SSD1306_INVERT.
  13. @return None (void).
  14. @note Changes buffer contents only, no immediate effect on display.
  15. Follow up with a call to display(), or with other graphics
  16. commands as needed by one's own application.
  17. */
  18. void Adafruit_SSD1306::drawFastVLine(
  19. int16_t x, int16_t y, int16_t h, uint16_t color) {
  20. boolean bSwap = false;
  21. switch(rotation) {
  22. case 1:
  23. // 90 degree rotation, swap x & y for rotation,
  24. // then invert x and adjust x for h (now to become w)
  25. bSwap = true;
  26. ssd1306_swap(x, y);
  27. x = WIDTH - x - 1;
  28. x -= (h-1);
  29. break;
  30. case 2:
  31. // 180 degree rotation, invert x and y, then shift y around for height.
  32. x = WIDTH - x - 1;
  33. y = HEIGHT - y - 1;
  34. y -= (h-1);
  35. break;
  36. case 3:
  37. // 270 degree rotation, swap x & y for rotation, then invert y
  38. bSwap = true;
  39. ssd1306_swap(x, y);
  40. y = HEIGHT - y - 1;
  41. break;
  42. }
  43. //判断是否有旋转角度 旋转90或者270度表示变成水平线了
  44. if(bSwap) drawFastHLineInternal(x, y, h, color);
  45. else drawFastVLineInternal(x, y, h, color);
  46. }
  47. /**
  48. * 绘制竖直线
  49. */
  50. void Adafruit_SSD1306::drawFastVLineInternal(
  51. int16_t x, int16_t __y, int16_t __h, uint16_t color) {
  52. //判断x点的有效位置
  53. if((x >= 0) && (x < WIDTH)) { // X coord in bounds?
  54. //裁剪顶部 计算高度
  55. if(__y < 0) { // Clip top
  56. __h += __y;
  57. __y = 0;
  58. }
  59. //裁剪底部 计算高度
  60. if((__y + __h) > HEIGHT) { // Clip bottom
  61. __h = (HEIGHT - __y);
  62. }
  63. if(__h > 0) { // Proceed only if height is now positive
  64. // this display doesn't need ints for coordinates,
  65. // use local byte registers for faster juggling
  66. uint8_t y = __y, h = __h;
  67. uint8_t *pBuf = &buffer[(y / 8) * WIDTH + x];
  68. // do the first partial byte, if necessary - this requires some masking
  69. uint8_t mod = (y & 7);
  70. if(mod) {
  71. // mask off the high n bits we want to set
  72. mod = 8 - mod;
  73. // note - lookup table results in a nearly 10% performance
  74. // improvement in fill* functions
  75. // uint8_t mask = ~(0xFF >> mod);
  76. static const uint8_t PROGMEM premask[8] =
  77. { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE };
  78. uint8_t mask = pgm_read_byte(&premask[mod]);
  79. // adjust the mask if we're not going to reach the end of this byte
  80. if(h < mod) mask &= (0XFF >> (mod - h));
  81. switch(color) {
  82. case SSD1306_WHITE: *pBuf |= mask; break;
  83. case SSD1306_BLACK: *pBuf &= ~mask; break;
  84. case SSD1306_INVERSE: *pBuf ^= mask; break;
  85. }
  86. pBuf += WIDTH;
  87. }
  88. if(h >= mod) { // More to go?
  89. h -= mod;
  90. // Write solid bytes while we can - effectively 8 rows at a time
  91. if(h >= 8) {
  92. if(color == SSD1306_INVERSE) {
  93. // separate copy of the code so we don't impact performance of
  94. // black/white write version with an extra comparison per loop
  95. do {
  96. *pBuf ^= 0xFF; // Invert byte
  97. pBuf += WIDTH; // Advance pointer 8 rows
  98. h -= 8; // Subtract 8 rows from height
  99. } while(h >= 8);
  100. } else {
  101. // store a local value to work with
  102. uint8_t val = (color != SSD1306_BLACK) ? 255 : 0;
  103. do {
  104. *pBuf = val; // Set byte
  105. pBuf += WIDTH; // Advance pointer 8 rows
  106. h -= 8; // Subtract 8 rows from height
  107. } while(h >= 8);
  108. }
  109. }
  110. if(h) { // Do the final partial byte, if necessary
  111. mod = h & 7;
  112. // this time we want to mask the low bits of the byte,
  113. // vs the high bits we did above
  114. // uint8_t mask = (1 << mod) - 1;
  115. // note - lookup table results in a nearly 10% performance
  116. // improvement in fill* functions
  117. static const uint8_t PROGMEM postmask[8] =
  118. { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
  119. uint8_t mask = pgm_read_byte(&postmask[mod]);
  120. switch(color) {
  121. case SSD1306_WHITE: *pBuf |= mask; break;
  122. case SSD1306_BLACK: *pBuf &= ~mask; break;
  123. case SSD1306_INVERSE: *pBuf ^= mask; break;
  124. }
  125. }
  126. }
  127. } // endif positive height
  128. } // endif x in bounds
  129. }

3.3.4 drawLine—— 绘制线

函数说明

  1. /**************************************************************************/
  2. /*!
  3. @brief Draw a line(绘制一条线)
  4. @param x0 Start point x coordinate
  5. @param y0 Start point y coordinate
  6. @param x1 End point x coordinate
  7. @param y1 End point y coordinate
  8. @param color 16-bit 5-6-5 Color to draw with
  9. */
  10. /**************************************************************************/
  11. void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
  12. uint16_t color) {
  13. // Update in subclasses if desired!
  14. if(x0 == x1){
  15. //竖直线
  16. // 交换数据 尽可能从上到下画
  17. if(y0 > y1) _swap_int16_t(y0, y1);
  18. drawFastVLine(x0, y0, y1 - y0 + 1, color);
  19. } else if(y0 == y1){
  20. //水平线
  21. // 交换数据 尽可能从左到右画
  22. if(x0 > x1) _swap_int16_t(x0, x1);
  23. drawFastHLine(x0, y0, x1 - x0 + 1, color);
  24. } else {
  25. //随意两点成线
  26. startWrite();
  27. writeLine(x0, y0, x1, y1, color);
  28. endWrite();
  29. }
  30. }
  31. /**************************************************************************/
  32. /*!
  33. 核心绘制线方法,核心在于线路算法
  34. @brief Write a line. Bresenham's algorithm - thx wikpedia
  35. @param x0 Start point x coordinate
  36. @param y0 Start point y coordinate
  37. @param x1 End point x coordinate
  38. @param y1 End point y coordinate
  39. @param color 16-bit 5-6-5 Color to draw with
  40. */
  41. /**************************************************************************/
  42. void Adafruit_GFX::writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
  43. uint16_t color) {
  44. #if defined(ESP8266)
  45. yield();
  46. #endif
  47. // 判断线的角度,看看是不是偏y轴
  48. int16_t steep = abs(y1 - y0) > abs(x1 - x0);
  49. if (steep) {
  50. _swap_int16_t(x0, y0);
  51. _swap_int16_t(x1, y1);
  52. }
  53. if (x0 > x1) {
  54. _swap_int16_t(x0, x1);
  55. _swap_int16_t(y0, y1);
  56. }
  57. int16_t dx, dy;
  58. dx = x1 - x0;
  59. dy = abs(y1 - y0);
  60. int16_t err = dx / 2;
  61. int16_t ystep;
  62. //因为考虑到像素点 不可能做到真的是一条直线
  63. if (y0 < y1) {
  64. ystep = 1;
  65. } else {
  66. ystep = -1;
  67. }
  68. for (; x0<=x1; x0++) {
  69. if (steep) {
  70. //最终都要调用到核心方法 writePixel
  71. writePixel(y0, x0, color);
  72. } else {
  73. writePixel(x0, y0, color);
  74. }
  75. err -= dy;
  76. if (err < 0) {
  77. y0 += ystep;
  78. err += dx;
  79. }
  80. }
  81. }
  82. /**************************************************************************/
  83. /*!
  84. 绘制点核心方法,由子类实现
  85. @brief Write a pixel, overwrite in subclasses if startWrite is defined!
  86. @param x x coordinate
  87. @param y y coordinate
  88. @param color 16-bit 5-6-5 Color to fill with
  89. */
  90. /**************************************************************************/
  91. void Adafruit_GFX::writePixel(int16_t x, int16_t y, uint16_t color){
  92. drawPixel(x, y, color);
  93. }

3.3.5 drawRect—— 绘制空心方形

函数说明

  1. /**************************************************************************/
  2. /*!
  3. 方形主要由四条边组成
  4. @brief Draw a rectangle with no fill color
  5. @param x Top left corner x coordinate
  6. @param y Top left corner y coordinate
  7. @param w Width in pixels
  8. @param h Height in pixels
  9. @param color 16-bit 5-6-5 Color to draw with
  10. */
  11. /**************************************************************************/
  12. void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h,
  13. uint16_t color) {
  14. startWrite();
  15. writeFastHLine(x, y, w, color);
  16. writeFastHLine(x, y+h-1, w, color);
  17. writeFastVLine(x, y, h, color);
  18. writeFastVLine(x+w-1, y, h, color);
  19. endWrite();
  20. }

注意点

  • 主要应用了绘制线方法 writeFastHLine 和 writeFastVLine;

3.3.6 fillRect—— 绘制实心方形

函数说明

  1. /**************************************************************************/
  2. /*!
  3. 绘制实心方形,代码非常巧妙,一行行调用 writeFastVLine即可
  4. @brief Fill a rectangle completely with one color. Update in subclasses if desired!
  5. @param x Top left corner x coordinate
  6. @param y Top left corner y coordinate
  7. @param w Width in pixels
  8. @param h Height in pixels
  9. @param color 16-bit 5-6-5 Color to fill with
  10. */
  11. /**************************************************************************/
  12. void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
  13. uint16_t color) {
  14. startWrite();
  15. for (int16_t i=x; i<x+w; i++) {
  16. writeFastVLine(i, y, h, color);
  17. }
  18. endWrite();
  19. }

3.3.7 fillScreen—— 绘制填充整个屏幕

函数说明

  1. /**************************************************************************/
  2. /*!
  3. 填充屏幕
  4. @brief Fill the screen completely with one color. Update in subclasses if desired!
  5. @param color 16-bit 5-6-5 Color to fill with
  6. */
  7. /**************************************************************************/
  8. void Adafruit_GFX::fillScreen(uint16_t color) {
  9. //其实就是调用fillRect 一行行去填充 最终全部填充
  10. fillRect(0, 0, _width, _height, color);
  11. }

3.3.8 drawCircle—— 绘制空心圆

函数说明

  1. /**************************************************************************/
  2. /*!
  3. 绘制空心圆,x0,y0为圆点,r为半径
  4. @brief Draw a circle outline
  5. @param x0 Center-point x coordinate
  6. @param y0 Center-point y coordinate
  7. @param r Radius of circle
  8. @param color 16-bit 5-6-5 Color to draw with
  9. */
  10. /**************************************************************************/
  11. void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
  12. uint16_t color) {
  13. #if defined(ESP8266)
  14. yield();
  15. #endif
  16. int16_t f = 1 - r;
  17. int16_t ddF_x = 1;
  18. int16_t ddF_y = -2 * r;
  19. int16_t x = 0;
  20. int16_t y = r;
  21. startWrite();
  22. // 先画好圆的四个关键点 上下左右
  23. writePixel(x0 , y0+r, color);
  24. writePixel(x0 , y0-r, color);
  25. writePixel(x0+r, y0 , color);
  26. writePixel(x0-r, y0 , color);
  27. // 以下算法没看懂 应该数学公式走起。。。。
  28. while (x<y) {
  29. if (f >= 0) {
  30. y--;
  31. ddF_y += 2;
  32. f += ddF_y;
  33. }
  34. x++;
  35. ddF_x += 2;
  36. f += ddF_x;
  37. writePixel(x0 + x, y0 + y, color);
  38. writePixel(x0 - x, y0 + y, color);
  39. writePixel(x0 + x, y0 - y, color);
  40. writePixel(x0 - x, y0 - y, color);
  41. writePixel(x0 + y, y0 + x, color);
  42. writePixel(x0 - y, y0 + x, color);
  43. writePixel(x0 + y, y0 - x, color);
  44. writePixel(x0 - y, y0 - x, color);
  45. }
  46. endWrite();
  47. }

3.3.9 fillCircle—— 绘制实心圆

函数说明

  1. /**************************************************************************/
  2. /*!
  3. @brief Draw a circle with filled color
  4. @param x0 Center-point x coordinate
  5. @param y0 Center-point y coordinate
  6. @param r Radius of circle
  7. @param color 16-bit 5-6-5 Color to fill with
  8. */
  9. /**************************************************************************/
  10. void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
  11. uint16_t color) {
  12. startWrite();
  13. writeFastVLine(x0, y0-r, 2*r+1, color);
  14. fillCircleHelper(x0, y0, r, 3, 0, color);
  15. endWrite();
  16. }

3.3.10 drawTriangle—— 绘制空心三角形

函数说明

  1. /**************************************************************************/
  2. /*!
  3. @brief Draw a triangle with no fill color
  4. @param x0 Vertex #0 x coordinate
  5. @param y0 Vertex #0 y coordinate
  6. @param x1 Vertex #1 x coordinate
  7. @param y1 Vertex #1 y coordinate
  8. @param x2 Vertex #2 x coordinate
  9. @param y2 Vertex #2 y coordinate
  10. @param color 16-bit 5-6-5 Color to draw with
  11. */
  12. /**************************************************************************/
  13. void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0,
  14. int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
  15. //两两顶点连成一条线,就是空心三角形
  16. drawLine(x0, y0, x1, y1, color);
  17. drawLine(x1, y1, x2, y2, color);
  18. drawLine(x2, y2, x0, y0, color);
  19. }

3.3.11 fillTriangle—— 绘制实心三角形

函数说明

  1. /**************************************************************************/
  2. /*!
  3. @brief Draw a triangle with color-fill
  4. @param x0 Vertex #0 x coordinate
  5. @param y0 Vertex #0 y coordinate
  6. @param x1 Vertex #1 x coordinate
  7. @param y1 Vertex #1 y coordinate
  8. @param x2 Vertex #2 x coordinate
  9. @param y2 Vertex #2 y coordinate
  10. @param color 16-bit 5-6-5 Color to fill/draw with
  11. */
  12. /**************************************************************************/
  13. void Adafruit_GFX::fillTriangle(int16_t x0, int16_t y0,
  14. int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color) {
  15. int16_t a, b, y, last;
  16. // Sort coordinates by Y order (y2 >= y1 >= y0)
  17. if (y0 > y1) {
  18. _swap_int16_t(y0, y1); _swap_int16_t(x0, x1);
  19. }
  20. if (y1 > y2) {
  21. _swap_int16_t(y2, y1); _swap_int16_t(x2, x1);
  22. }
  23. if (y0 > y1) {
  24. _swap_int16_t(y0, y1); _swap_int16_t(x0, x1);
  25. }
  26. startWrite();
  27. if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
  28. a = b = x0;
  29. if(x1 < a) a = x1;
  30. else if(x1 > b) b = x1;
  31. if(x2 < a) a = x2;
  32. else if(x2 > b) b = x2;
  33. writeFastHLine(a, y0, b-a+1, color);
  34. endWrite();
  35. return;
  36. }
  37. int16_t
  38. dx01 = x1 - x0,
  39. dy01 = y1 - y0,
  40. dx02 = x2 - x0,
  41. dy02 = y2 - y0,
  42. dx12 = x2 - x1,
  43. dy12 = y2 - y1;
  44. int32_t
  45. sa = 0,
  46. sb = 0;
  47. // For upper part of triangle, find scanline crossings for segments
  48. // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
  49. // is included here (and second loop will be skipped, avoiding a /0
  50. // error there), otherwise scanline y1 is skipped here and handled
  51. // in the second loop...which also avoids a /0 error here if y0=y1
  52. // (flat-topped triangle).
  53. if(y1 == y2) last = y1; // Include y1 scanline
  54. else last = y1-1; // Skip it
  55. for(y=y0; y<=last; y++) {
  56. a = x0 + sa / dy01;
  57. b = x0 + sb / dy02;
  58. sa += dx01;
  59. sb += dx02;
  60. /* longhand:
  61. a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
  62. b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
  63. */
  64. if(a > b) _swap_int16_t(a,b);
  65. writeFastHLine(a, y, b-a+1, color);
  66. }
  67. // For lower part of triangle, find scanline crossings for segments
  68. // 0-2 and 1-2. This loop is skipped if y1=y2.
  69. sa = (int32_t)dx12 * (y - y1);
  70. sb = (int32_t)dx02 * (y - y0);
  71. for(; y<=y2; y++) {
  72. a = x1 + sa / dy12;
  73. b = x0 + sb / dy02;
  74. sa += dx12;
  75. sb += dx02;
  76. /* longhand:
  77. a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
  78. b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
  79. */
  80. if(a > b) _swap_int16_t(a,b);
  81. writeFastHLine(a, y, b-a+1, color);
  82. }
  83. endWrite();
  84. }

3.3.12 drawRoundRect—— 绘制空心圆角矩形

函数说明

  1. /*!
  2. @brief Draw a rounded rectangle with no fill color
  3. @param x Top left corner x coordinate
  4. @param y Top left corner y coordinate
  5. @param w Width in pixels
  6. @param h Height in pixels
  7. @param r Radius of corner rounding
  8. @param color 16-bit 5-6-5 Color to draw with
  9. */
  10. /**************************************************************************/
  11. void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
  12. int16_t h, int16_t r, uint16_t color) {
  13. int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis
  14. if(r > max_radius) r = max_radius;
  15. // smarter version
  16. // 绘制四条线
  17. startWrite();
  18. writeFastHLine(x+r , y , w-2*r, color); // Top
  19. writeFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
  20. writeFastVLine(x , y+r , h-2*r, color); // Left
  21. writeFastVLine(x+w-1, y+r , h-2*r, color); // Right
  22. // draw four corners
  23. // 绘制四个圆角边
  24. drawCircleHelper(x+r , y+r , r, 1, color);
  25. drawCircleHelper(x+w-r-1, y+r , r, 2, color);
  26. drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
  27. drawCircleHelper(x+r , y+h-r-1, r, 8, color);
  28. endWrite();
  29. }

3.3.12 fillRoundRect—— 绘制实心圆角矩形

函数说明

  1. /*!
  2. @brief Draw a rounded rectangle with fill color
  3. @param x Top left corner x coordinate
  4. @param y Top left corner y coordinate
  5. @param w Width in pixels
  6. @param h Height in pixels
  7. @param r Radius of corner rounding
  8. @param color 16-bit 5-6-5 Color to draw/fill with
  9. */
  10. /**************************************************************************/
  11. void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
  12. int16_t h, int16_t r, uint16_t color) {
  13. int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis
  14. if(r > max_radius) r = max_radius;
  15. // smarter version
  16. startWrite();
  17. writeFillRect(x+r, y, w-2*r, h, color);
  18. // draw four corners
  19. fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
  20. fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
  21. endWrite();
  22. }

3.3.13 drawBitmap—— 绘制Bitmap图形

函数说明

  1. /*!
  2. 绘制一个图形 图形内容从 PROGMEM区来
  3. @brief Draw a PROGMEM-resident 1-bit image at the specified (x,y) position, using the specified foreground color (unset bits are transparent).
  4. @param x Top left corner x coordinate(左上顶点x坐标)
  5. @param y Top left corner y coordinate(右上顶点x坐标)
  6. @param bitmap byte array with monochrome bitmap(图形数组)
  7. @param w Width of bitmap in pixels(图形宽度像素点)
  8. @param h Height of bitmap in pixels(图形高度像素点)
  9. @param color 16-bit 5-6-5 Color to draw with(如果支持多颜色,设置绘制颜色)
  10. */
  11. drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[],
  12. int16_t w, int16_t h, uint16_t color)
  13. /*!
  14. 绘制一个图形 图形内容从 PROGMEM区来
  15. @brief Draw a PROGMEM-resident 1-bit image at the specified (x,y) position, using the specified foreground (for set bits) and background (unset bits) colors.
  16. @param x Top left corner x coordinate(左上顶点x坐标)
  17. @param y Top left corner y coordinate(右上顶点x坐标)
  18. @param bitmap byte array with monochrome bitmap(图形数组)
  19. @param w Width of bitmap in pixels(图形宽度像素点)
  20. @param h Height of bitmap in pixels(图形高度像素点)
  21. @param color 16-bit 5-6-5 Color to draw pixels with(如果支持多颜色,设置绘制颜色)
  22. @param bg 16-bit 5-6-5 Color to draw background with(如果支持,设置图形背景颜色)
  23. */
  24. drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[],
  25. int16_t w, int16_t h, uint16_t color, uint16_t bg)
  26. /*!
  27. 绘制图形,图形内容从ram区来
  28. @brief Draw a RAM-resident 1-bit image at the specified (x,y) position, using the specified foreground color (unset bits are transparent).
  29. @param x Top left corner x coordinate
  30. @param y Top left corner y coordinate
  31. @param bitmap byte array with monochrome bitmap
  32. @param w Width of bitmap in pixels
  33. @param h Height of bitmap in pixels
  34. @param color 16-bit 5-6-5 Color to draw with
  35. */
  36. drawBitmap(int16_t x, int16_t y, uint8_t *bitmap,
  37. int16_t w, int16_t h, uint16_t color)
  38. /*!
  39. 绘制图形,图形内容从ram区来
  40. @brief Draw a PROGMEM-resident 1-bit image at the specified (x,y) position, using the specified foreground (for set bits) and background (unset bits) colors.
  41. @param x Top left corner x coordinate(左上顶点x坐标)
  42. @param y Top left corner y coordinate(右上顶点x坐标)
  43. @param bitmap byte array with monochrome bitmap(图形数组)
  44. @param w Width of bitmap in pixels(图形宽度像素点)
  45. @param h Height of bitmap in pixels(图形高度像素点)
  46. @param color 16-bit 5-6-5 Color to draw pixels with(如果支持多颜色,设置绘制颜色)
  47. @param bg 16-bit 5-6-5 Color to draw background with(如果支持,设置图形背景颜色)
  48. */
  49. drawBitmap(int16_t x, int16_t y, uint8_t *bitmap,
  50. int16_t w, int16_t h, uint16_t color, uint16_t bg),

注意点

  • 需要区分 PROGMEM 和 RAM(PROGMEM 区意味着需要使用 pgm_read_byte方法来读取)

3.3.14 drawXBitmap—— 绘制XBitmap图形

函数说明

  1. /**************************************************************************/
  2. /*!
  3. 绘制XBitmap图形,可以类比 drawBitmap,*.xbm的图形文件,博主也没有用过
  4. @brief Draw PROGMEM-resident XBitMap Files (*.xbm), exported from GIMP.
  5. Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor.
  6. C Array can be directly used with this function.
  7. There is no RAM-resident version of this function; if generating bitmaps
  8. in RAM, use the format defined by drawBitmap() and call that instead.
  9. @param x Top left corner x coordinate(左上顶点x坐标)
  10. @param y Top left corner y coordinate(右上顶点x坐标)
  11. @param bitmap byte array with monochrome bitmap(图形数组)
  12. @param w Width of bitmap in pixels(图形宽度像素点)
  13. @param h Height of bitmap in pixels(图形高度像素点)
  14. @param color 16-bit 5-6-5 Color to draw pixels with
  15. */
  16. /**************************************************************************/
  17. void Adafruit_GFX::drawXBitmap(int16_t x, int16_t y,
  18. const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color) {
  19. int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
  20. uint8_t byte = 0;
  21. startWrite();
  22. for(int16_t j=0; j<h; j++, y++) {
  23. for(int16_t i=0; i<w; i++ ) {
  24. if(i & 7) byte >>= 1;
  25. else byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
  26. // Nearly identical to drawBitmap(), only the bit order
  27. // is reversed here (left-to-right = LSB to MSB):
  28. if(byte & 0x01) writePixel(x+i, y, color);
  29. }
  30. }
  31. endWrite();
  32. }

注意点

  • 只有PROGMEM版本

3.3.15 drawChar—— 绘制单个字母

函数说明

  1. // Draw a character
  2. /**************************************************************************/
  3. /*!
  4. @brief Draw a single character
  5. @param x Bottom left corner x coordinate(字母左下角X坐标)
  6. @param y Bottom left corner y coordinate(字母左下角Y坐标)
  7. @param c The 8-bit font-indexed character (likely ascii)(绘制字母)
  8. @param color 16-bit 5-6-5 Color to draw chraracter with(绘制颜色)
  9. @param bg 16-bit 5-6-5 Color to fill background with (if same as color, no background)(绘制底色)
  10. @param size Font magnification level, 1 is 'original' size)(绘制倍数)
  11. */
  12. /**************************************************************************/
  13. void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
  14. uint16_t color, uint16_t bg, uint8_t size) {
  15. drawChar(x, y, c, color, bg, size, size);
  16. }
  17. // Draw a character
  18. /**************************************************************************/
  19. /*!
  20. @brief Draw a single character
  21. @param x Bottom left corner x coordinate(字母左下角X坐标)
  22. @param y Bottom left corner y coordinate(字母左下角Y坐标)
  23. @param c The 8-bit font-indexed character (likely ascii)(绘制字母)
  24. @param color 16-bit 5-6-5 Color to draw chraracter with(绘制颜色)
  25. @param bg 16-bit 5-6-5 Color to fill background with (if same as color, no background)(绘制底色)
  26. @param size_x Font magnification level in X-axis, 1 is 'original' size
  27. @param size_y Font magnification level in Y-axis, 1 is 'original' size
  28. */
  29. /**************************************************************************/
  30. void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
  31. uint16_t color, uint16_t bg, uint8_t size_x, uint8_t size_y) {
  32. // 判断有没有设置自定义字体,默认是NULL,也就是标准字体
  33. if(!gfxFont) { // 'Classic' built-in font
  34. if((x >= _width) || // Clip right
  35. (y >= _height) || // Clip bottom
  36. ((x + 6 * size_x - 1) < 0) || // Clip left
  37. ((y + 8 * size_y - 1) < 0)) // Clip top
  38. return;
  39. if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior
  40. startWrite();
  41. for(int8_t i=0; i<5; i++ ) { // Char bitmap = 5 columns
  42. uint8_t line = pgm_read_byte(&font[c * 5 + i]);
  43. for(int8_t j=0; j<8; j++, line >>= 1) {
  44. if(line & 1) {
  45. if(size_x == 1 && size_y == 1)
  46. writePixel(x+i, y+j, color);
  47. else
  48. writeFillRect(x+i*size_x, y+j*size_y, size_x, size_y, color);
  49. } else if(bg != color) {
  50. if(size_x == 1 && size_y == 1)
  51. writePixel(x+i, y+j, bg);
  52. else
  53. writeFillRect(x+i*size_x, y+j*size_y, size_x, size_y, bg);
  54. }
  55. }
  56. }
  57. if(bg != color) { // If opaque, draw vertical line for last column
  58. if(size_x == 1 && size_y == 1) writeFastVLine(x+5, y, 8, bg);
  59. else writeFillRect(x+5*size_x, y, size_x, 8*size_y, bg);
  60. }
  61. endWrite();
  62. } else { // Custom font 以下是自定义字体
  63. // Character is assumed previously filtered by write() to eliminate
  64. // newlines, returns, non-printable characters, etc. Calling
  65. // drawChar() directly with 'bad' characters of font may cause mayhem!
  66. c -= (uint8_t)pgm_read_byte(&gfxFont->first);
  67. GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c);
  68. uint8_t *bitmap = pgm_read_bitmap_ptr(gfxFont);
  69. uint16_t bo = pgm_read_word(&glyph->bitmapOffset);
  70. uint8_t w = pgm_read_byte(&glyph->width),
  71. h = pgm_read_byte(&glyph->height);
  72. int8_t xo = pgm_read_byte(&glyph->xOffset),
  73. yo = pgm_read_byte(&glyph->yOffset);
  74. uint8_t xx, yy, bits = 0, bit = 0;
  75. int16_t xo16 = 0, yo16 = 0;
  76. if(size_x > 1 || size_y > 1) {
  77. xo16 = xo;
  78. yo16 = yo;
  79. }
  80. // Todo: Add character clipping here
  81. // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS.
  82. // THIS IS ON PURPOSE AND BY DESIGN. The background color feature
  83. // has typically been used with the 'classic' font to overwrite old
  84. // screen contents with new data. This ONLY works because the
  85. // characters are a uniform size; it's not a sensible thing to do with
  86. // proportionally-spaced fonts with glyphs of varying sizes (and that
  87. // may overlap). To replace previously-drawn text when using a custom
  88. // font, use the getTextBounds() function to determine the smallest
  89. // rectangle encompassing a string, erase the area with fillRect(),
  90. // then draw new text. This WILL infortunately 'blink' the text, but
  91. // is unavoidable. Drawing 'background' pixels will NOT fix this,
  92. // only creates a new set of problems. Have an idea to work around
  93. // this (a canvas object type for MCUs that can afford the RAM and
  94. // displays supporting setAddrWindow() and pushColors()), but haven't
  95. // implemented this yet.
  96. startWrite();
  97. for(yy=0; yy<h; yy++) {
  98. for(xx=0; xx<w; xx++) {
  99. if(!(bit++ & 7)) {
  100. bits = pgm_read_byte(&bitmap[bo++]);
  101. }
  102. if(bits & 0x80) {
  103. if(size_x == 1 && size_y == 1) {
  104. writePixel(x+xo+xx, y+yo+yy, color);
  105. } else {
  106. writeFillRect(x+(xo16+xx)*size_x, y+(yo16+yy)*size_y,
  107. size_x, size_y, color);
  108. }
  109. }
  110. bits <<= 1;
  111. }
  112. }
  113. endWrite();
  114. } // End classic vs custom font
  115. }

注意点

  • 目前支持的字体全在这里:

    具体什么效果,得一个个去试试了。

3.3.16 getTextBounds—— 绘制单个字母

函数说明

  1. /**************************************************************************/
  2. /*!
  3. 计算字符串在当前字体大小下的像素大小,返回左上角坐标以及宽度高度像素值
  4. @brief Helper to determine size of a string with current font/size. Pass string and a cursor position, returns UL corner and W,H.
  5. @param str The ascii string to measure (as an arduino String() class)
  6. @param x The current cursor X
  7. @param y The current cursor Y
  8. @param x1 The boundary X coordinate, set by function
  9. @param y1 The boundary Y coordinate, set by function
  10. @param w The boundary width, set by function
  11. @param h The boundary height, set by function
  12. */
  13. /**************************************************************************/
  14. void Adafruit_GFX::getTextBounds(const String &str, int16_t x, int16_t y,
  15. int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)
  16. /**************************************************************************/
  17. /*!
  18. 计算字符串在当前字体大小下的像素大小,返回左上角坐标以及宽度高度像素值,针对PROGMEM 字符串
  19. @brief Helper to determine size of a PROGMEM string with current font/size. Pass string and a cursor position, returns UL corner and W,H.
  20. @param str The flash-memory ascii string to measure
  21. @param x The current cursor X
  22. @param y The current cursor Y
  23. @param x1 The boundary X coordinate, set by function
  24. @param y1 The boundary Y coordinate, set by function
  25. @param w The boundary width, set by function
  26. @param h The boundary height, set by function
  27. */
  28. /**************************************************************************/
  29. void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str,
  30. int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h)

3.3.17 setTextSize—— 设置字体大小

函数说明

  1. /**************************************************************************/
  2. /*!
  3. @brief Set text 'magnification' size. Each increase in s makes 1 pixel that much bigger.
  4. @param s Desired text size. 1 is default 6x8, 2 is 12x16, 3 is 18x24, etc
  5. */
  6. /**************************************************************************/
  7. void Adafruit_GFX::setTextSize(uint8_t s) {
  8. setTextSize(s, s);
  9. }
  10. /**************************************************************************/
  11. /*!
  12. @brief Set text 'magnification' size. Each increase in s makes 1 pixel that much bigger.
  13. @param s_x Desired text width magnification level in X-axis. 1 is default
  14. @param s_y Desired text width magnification level in Y-axis. 1 is default
  15. */
  16. /**************************************************************************/
  17. void Adafruit_GFX::setTextSize(uint8_t s_x, uint8_t s_y) {
  18. textsize_x = (s_x > 0) ? s_x : 1;
  19. textsize_y = (s_y > 0) ? s_y : 1;
  20. }

3.3.18 setFont—— 设置字体

函数说明

  1. /**************************************************************************/
  2. /*!
  3. @brief Set the font to display when print()ing, either custom or default
  4. @param f The GFXfont object, if NULL use built in 6x8 font
  5. */
  6. /**************************************************************************/
  7. void Adafruit_GFX::setFont(const GFXfont *f) {
  8. if(f) { // Font struct pointer passed in?
  9. if(!gfxFont) { // And no current font struct?
  10. // Switching from classic to new font behavior.
  11. // Move cursor pos down 6 pixels so it's on baseline.
  12. cursor_y += 6;
  13. }
  14. } else if(gfxFont) { // NULL passed. Current font struct defined?
  15. // Switching from new to classic font behavior.
  16. // Move cursor pos up 6 pixels so it's at top-left of char.
  17. cursor_y -= 6;
  18. }
  19. gfxFont = (GFXfont *)f;
  20. }

3.3.19 setCursor—— 设置光标位置

函数说明

  1. /**********************************************************************/
  2. /*!
  3. @brief Set text cursor location
  4. @param x X coordinate in pixels
  5. @param y Y coordinate in pixels
  6. */
  7. /**********************************************************************/
  8. void setCursor(int16_t x, int16_t y) { cursor_x = x; cursor_y = y; }

3.3.20 setTextColor—— 设置字体颜色

函数说明

  1. /**********************************************************************/
  2. /*!
  3. @brief Set text font color with transparant background
  4. @param c 16-bit 5-6-5 Color to draw text with(字体绘制颜色)
  5. @note For 'transparent' background, background and foreground
  6. are set to same color rather than using a separate flag.
  7. */
  8. /**********************************************************************/
  9. void setTextColor(uint16_t c) { textcolor = textbgcolor = c; }
  10. /**********************************************************************/
  11. /*!
  12. @brief Set text font color with custom background color
  13. @param c 16-bit 5-6-5 Color to draw text with
  14. @param bg 16-bit 5-6-5 Color to draw background/fill with(字体背景颜色)
  15. */
  16. /**********************************************************************/
  17. void setTextColor(uint16_t c, uint16_t bg) {
  18. textcolor = c;
  19. textbgcolor = bg;
  20. }

3.3.21 setTextWrap—— 设置是否自动换行

函数说明

  1. /**********************************************************************/
  2. //当字符串太长以致一行无法显示,是否自动换行
  3. /*!
  4. @brief Set whether text that is too long for the screen width should
  5. automatically wrap around to the next line (else clip right).
  6. @param w true for wrapping, false for clipping
  7. */
  8. /**********************************************************************/
  9. void setTextWrap(boolean w) { wrap = w; }

3.4 屏幕参数类方法

3.4.1 width——获取屏幕宽度

函数说明

  1. /************************************************************************/
  2. /*!
  3. @brief Get width of the display, accounting for current rotation
  4. @returns Width in pixels
  5. */
  6. /************************************************************************/
  7. int16_t width(void) const { return _width; };

注意点

  • WIDTH、HEIGHT是屏幕的原始宽高度,_width、_height跟屏幕当前旋转角度有关。

3.4.2 height——获取屏幕高度

函数说明

  1. /************************************************************************/
  2. /*!
  3. @brief Get height of the display, accounting for current rotation
  4. @returns Height in pixels
  5. */
  6. /************************************************************************/
  7. int16_t height(void) const { return _height; }

3.4.3 getRotation——获取屏幕旋转角度

函数说明

  1. /************************************************************************/
  2. /*!
  3. @brief Get rotation setting for display
  4. @returns 0 thru 3 corresponding to 4 cardinal rotations
  5. */
  6. /************************************************************************/
  7. uint8_t getRotation(void) const { return rotation; }

3.4.4 getCursorX——获取text光标X坐标

函数说明

  1. // get current cursor position (get rotation safe maximum values,
  2. // using: width() for x, height() for y)
  3. /************************************************************************/
  4. /*!
  5. @brief Get text cursor X location
  6. @returns X coordinate in pixels
  7. */
  8. /************************************************************************/
  9. int16_t getCursorX(void) const { return cursor_x; }

3.4.5 getCursorY——获取text光标Y坐标

函数说明

  1. /************************************************************************/
  2. /*!
  3. @brief Get text cursor Y location
  4. @returns Y coordinate in pixels
  5. */
  6. /************************************************************************/
  7. int16_t getCursorY(void) const { return cursor_y; };

3.5 滚动类方法

3.5.1 startscrollright —— 滚动到右边

函数说明

  1. /*!
  2. 触发一个滚动部分或者整个屏幕内容到右边
  3. @brief Activate a right-handed scroll for all or part of the display.
  4. @param start(设置滚动的第一行)
  5. First row.
  6. @param stop(设置滚动的最后一行)
  7. Last row.
  8. @return None (void).
  9. */
  10. // To scroll the whole display, run: display.startscrollright(0x00, 0x0F)
  11. void Adafruit_SSD1306::startscrollright(uint8_t start, uint8_t stop) {
  12. TRANSACTION_START
  13. static const uint8_t PROGMEM scrollList1a[] = {
  14. SSD1306_RIGHT_HORIZONTAL_SCROLL,
  15. 0X00 };
  16. ssd1306_commandList(scrollList1a, sizeof(scrollList1a));
  17. ssd1306_command1(start);
  18. ssd1306_command1(0X00);
  19. ssd1306_command1(stop);
  20. static const uint8_t PROGMEM scrollList1b[] = {
  21. 0X00,
  22. 0XFF,
  23. SSD1306_ACTIVATE_SCROLL };
  24. ssd1306_commandList(scrollList1b, sizeof(scrollList1b));
  25. TRANSACTION_END
  26. }

3.5.2 startscrollleft—— 滚动到左边

函数说明

  1. /*!
  2. 触发一个滚动部分或者整个屏幕内容到左边
  3. @brief Activate a right-handed scroll for all or part of the display.
  4. @param start(设置滚动的第一行)
  5. First row.
  6. @param stop(设置滚动的最后一行)
  7. Last row.
  8. @return None (void).
  9. */
  10. // To scroll the whole display, run: display.startscrollleft(0x00, 0x0F)
  11. void Adafruit_SSD1306::startscrollleft(uint8_t start, uint8_t stop) {
  12. TRANSACTION_START
  13. static const uint8_t PROGMEM scrollList2a[] = {
  14. SSD1306_LEFT_HORIZONTAL_SCROLL,
  15. 0X00 };
  16. ssd1306_commandList(scrollList2a, sizeof(scrollList2a));
  17. ssd1306_command1(start);
  18. ssd1306_command1(0X00);
  19. ssd1306_command1(stop);
  20. static const uint8_t PROGMEM scrollList2b[] = {
  21. 0X00,
  22. 0XFF,
  23. SSD1306_ACTIVATE_SCROLL };
  24. ssd1306_commandList(scrollList2b, sizeof(scrollList2b));
  25. TRANSACTION_END
  26. }

3.5.3 startscrolldiagright—— 沿着对角线滚动到右边

函数说明

  1. /*!
  2. 触发一个对角线滚动部分或者整个屏幕内容到右边
  3. @brief Activate a diagonal scroll for all or part of the display.
  4. @param start(设置滚动的第一行)
  5. First row.
  6. @param stop(设置滚动的最后一行)
  7. Last row.
  8. @return None (void).
  9. */
  10. // display.startscrolldiagright(0x00, 0x0F)
  11. void Adafruit_SSD1306::startscrolldiagright(uint8_t start, uint8_t stop) {
  12. TRANSACTION_START
  13. static const uint8_t PROGMEM scrollList3a[] = {
  14. SSD1306_SET_VERTICAL_SCROLL_AREA,
  15. 0X00 };
  16. ssd1306_commandList(scrollList3a, sizeof(scrollList3a));
  17. ssd1306_command1(HEIGHT);
  18. static const uint8_t PROGMEM scrollList3b[] = {
  19. SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL,
  20. 0X00 };
  21. ssd1306_commandList(scrollList3b, sizeof(scrollList3b));
  22. ssd1306_command1(start);
  23. ssd1306_command1(0X00);
  24. ssd1306_command1(stop);
  25. static const uint8_t PROGMEM scrollList3c[] = {
  26. 0X01,
  27. SSD1306_ACTIVATE_SCROLL };
  28. ssd1306_commandList(scrollList3c, sizeof(scrollList3c));
  29. TRANSACTION_END
  30. }

3.5.4 startscrolldiagleft—— 沿着对角线滚动到左边

函数说明

  1. /*!
  2. 触发一个对角线滚动部分或者整个屏幕内容到左边
  3. @brief Activate alternate diagonal scroll for all or part of the display.
  4. @param start(设置滚动的第一行)
  5. First row.
  6. @param stop(设置滚动的最后一行)
  7. Last row.
  8. @return None (void).
  9. */
  10. // To scroll the whole display, run: display.startscrolldiagleft(0x00, 0x0F)
  11. void Adafruit_SSD1306::startscrolldiagleft(uint8_t start, uint8_t stop) {
  12. TRANSACTION_START
  13. static const uint8_t PROGMEM scrollList4a[] = {
  14. SSD1306_SET_VERTICAL_SCROLL_AREA,
  15. 0X00 };
  16. ssd1306_commandList(scrollList4a, sizeof(scrollList4a));
  17. ssd1306_command1(HEIGHT);
  18. static const uint8_t PROGMEM scrollList4b[] = {
  19. SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL,
  20. 0X00 };
  21. ssd1306_commandList(scrollList4b, sizeof(scrollList4b));
  22. ssd1306_command1(start);
  23. ssd1306_command1(0X00);
  24. ssd1306_command1(stop);
  25. static const uint8_t PROGMEM scrollList4c[] = {
  26. 0X01,
  27. SSD1306_ACTIVATE_SCROLL };
  28. ssd1306_commandList(scrollList4c, sizeof(scrollList4c));
  29. TRANSACTION_END
  30. }

3.5.5 stopscroll—— 停止滚动

函数说明

  1. /*!
  2. @brief Cease a previously-begun scrolling action.
  3. @return None (void).
  4. */
  5. void Adafruit_SSD1306::stopscroll(void) {
  6. TRANSACTION_START
  7. ssd1306_command1(SSD1306_DEACTIVATE_SCROLL);
  8. TRANSACTION_END
  9. }

4.实例操作

使用Adafruit_SSD1306库分为三个步骤:

  • 初始化OLED —— 调用构造函数、调用begin
  • 初始化成功后,调用绘制类函数,当然可以设置颜色、字体等
  • 绘制完毕,调用显示类函数display

4.1 实例一——官方测试用例

具体代码

  1. /**************************************************************************
  2. This is an example for our Monochrome OLEDs based on SSD1306 drivers
  3. Pick one up today in the adafruit shop!
  4. ------> http://www.adafruit.com/category/63_98
  5. This example is for a 128x32 pixel display using I2C to communicate
  6. 3 pins are required to interface (two I2C and one reset).
  7. Adafruit invests time and resources providing this open
  8. source code, please support Adafruit and open-source
  9. hardware by purchasing products from Adafruit!
  10. Written by Limor Fried/Ladyada for Adafruit Industries,
  11. with contributions from the open source community.
  12. BSD license, check license.txt for more information
  13. All text above, and the splash screen below must be
  14. included in any redistribution.
  15. **************************************************************************/
  16. #include <SPI.h>
  17. #include <Wire.h>
  18. #include <Adafruit_GFX.h>
  19. #include <Adafruit_SSD1306.h>
  20. // 这里的屏幕是128X64 SSD1306
  21. #define SCREEN_WIDTH 128 // OLED display width, in pixels
  22. #define SCREEN_HEIGHT 64 // OLED display height, in pixels
  23. // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
  24. #define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
  25. // 构造类函数 IIC版本
  26. Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  27. #define NUMFLAKES 10 // Number of snowflakes in the animation example
  28. // drawBitmap
  29. #define LOGO_HEIGHT 16
  30. #define LOGO_WIDTH 16
  31. static const unsigned char PROGMEM logo_bmp[] =
  32. { B00000000, B11000000,
  33. B00000001, B11000000,
  34. B00000001, B11000000,
  35. B00000011, B11100000,
  36. B11110011, B11100000,
  37. B11111110, B11111000,
  38. B01111110, B11111111,
  39. B00110011, B10011111,
  40. B00011111, B11111100,
  41. B00001101, B01110000,
  42. B00011011, B10100000,
  43. B00111111, B11100000,
  44. B00111111, B11110000,
  45. B01111100, B11110000,
  46. B01110000, B01110000,
  47. B00000000, B00110000 };
  48. void setup() {
  49. Serial.begin(9600);
  50. // 第一个步骤 begin启动函数 创建buffer缓存
  51. // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  52. if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
  53. Serial.println(F("SSD1306 allocation failed"));
  54. for(;;); // Don't proceed, loop forever
  55. }
  56. // Show initial display buffer contents on the screen --
  57. // the library initializes this with an Adafruit splash screen.
  58. // 显示内容 默认显示 Adafruit 启动页面
  59. display.display();
  60. delay(2000); // Pause for 2 seconds
  61. // Clear the buffer 清理缓存
  62. display.clearDisplay();
  63. // Draw a single pixel in white 绘制类函数(单一像素点)
  64. display.drawPixel(10, 10, SSD1306_WHITE);
  65. // Show the display buffer on the screen. You MUST call display() after
  66. // drawing commands to make them visible on screen!
  67. // 执行显示类函数
  68. display.display();
  69. delay(2000);
  70. // display.display() is NOT necessary after every single drawing command,
  71. // unless that's what you want...rather, you can batch up a bunch of
  72. // drawing operations and then update the screen all at once by calling
  73. // display.display(). These examples demonstrate both approaches...
  74. // 测试绘制线方法
  75. testdrawline(); // Draw many lines
  76. // 测试绘制空心矩形方法
  77. testdrawrect(); // Draw rectangles (outlines)
  78. // 测试绘制实心矩形方法
  79. testfillrect(); // Draw rectangles (filled)
  80. // 测试绘制空心圆方法
  81. testdrawcircle(); // Draw circles (outlines)
  82. // 测试绘制实心圆方法
  83. testfillcircle(); // Draw circles (filled)
  84. // 测试绘制空心圆角矩形方法
  85. testdrawroundrect(); // Draw rounded rectangles (outlines)
  86. // 测试绘制实心圆角矩形方法
  87. testfillroundrect(); // Draw rounded rectangles (filled)
  88. // 测试绘制空心三角形方法
  89. testdrawtriangle(); // Draw triangles (outlines)
  90. // 测试绘制实心三角形方法
  91. testfilltriangle(); // Draw triangles (filled)
  92. // 测试绘制字符方法
  93. testdrawchar(); // Draw characters of the default font
  94. testdrawstyles(); // Draw 'stylized' characters
  95. // 测试滚动方法
  96. testscrolltext(); // Draw scrolling text
  97. // 测试绘制图片方法
  98. testdrawbitmap(); // Draw a small bitmap image
  99. // Invert and restore display, pausing in-between
  100. display.invertDisplay(true);
  101. delay(1000);
  102. display.invertDisplay(false);
  103. delay(1000);
  104. testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
  105. }
  106. void loop() {
  107. }
  108. void testdrawline() {
  109. int16_t i;
  110. // 清理缓存
  111. display.clearDisplay(); // Clear display buffer
  112. for(i=0; i<display.width(); i+=4) {
  113. display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
  114. display.display(); // Update screen with each newly-drawn line
  115. delay(1);
  116. }
  117. for(i=0; i<display.height(); i+=4) {
  118. display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
  119. display.display();
  120. delay(1);
  121. }
  122. delay(250);
  123. display.clearDisplay();
  124. for(i=0; i<display.width(); i+=4) {
  125. display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
  126. display.display();
  127. delay(1);
  128. }
  129. for(i=display.height()-1; i>=0; i-=4) {
  130. display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
  131. display.display();
  132. delay(1);
  133. }
  134. delay(250);
  135. display.clearDisplay();
  136. for(i=display.width()-1; i>=0; i-=4) {
  137. display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
  138. display.display();
  139. delay(1);
  140. }
  141. for(i=display.height()-1; i>=0; i-=4) {
  142. display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
  143. display.display();
  144. delay(1);
  145. }
  146. delay(250);
  147. display.clearDisplay();
  148. for(i=0; i<display.height(); i+=4) {
  149. display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
  150. display.display();
  151. delay(1);
  152. }
  153. for(i=0; i<display.width(); i+=4) {
  154. display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
  155. display.display();
  156. delay(1);
  157. }
  158. delay(2000); // Pause for 2 seconds
  159. }
  160. void testdrawrect(void) {
  161. display.clearDisplay();
  162. for(int16_t i=0; i<display.height()/2; i+=2) {
  163. display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
  164. display.display(); // Update screen with each newly-drawn rectangle
  165. delay(1);
  166. }
  167. delay(2000);
  168. }
  169. void testfillrect(void) {
  170. display.clearDisplay();
  171. for(int16_t i=0; i<display.height()/2; i+=3) {
  172. // The INVERSE color is used so rectangles alternate white/black
  173. display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
  174. display.display(); // Update screen with each newly-drawn rectangle
  175. delay(1);
  176. }
  177. delay(2000);
  178. }
  179. void testdrawcircle(void) {
  180. display.clearDisplay();
  181. for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
  182. display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
  183. display.display();
  184. delay(1);
  185. }
  186. delay(2000);
  187. }
  188. void testfillcircle(void) {
  189. display.clearDisplay();
  190. for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
  191. // The INVERSE color is used so circles alternate white/black
  192. display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
  193. display.display(); // Update screen with each newly-drawn circle
  194. delay(1);
  195. }
  196. delay(2000);
  197. }
  198. void testdrawroundrect(void) {
  199. display.clearDisplay();
  200. for(int16_t i=0; i<display.height()/2-2; i+=2) {
  201. display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
  202. display.height()/4, SSD1306_WHITE);
  203. display.display();
  204. delay(1);
  205. }
  206. delay(2000);
  207. }
  208. void testfillroundrect(void) {
  209. display.clearDisplay();
  210. for(int16_t i=0; i<display.height()/2-2; i+=2) {
  211. // The INVERSE color is used so round-rects alternate white/black
  212. display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
  213. display.height()/4, SSD1306_INVERSE);
  214. display.display();
  215. delay(1);
  216. }
  217. delay(2000);
  218. }
  219. void testdrawtriangle(void) {
  220. display.clearDisplay();
  221. for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
  222. display.drawTriangle(
  223. display.width()/2 , display.height()/2-i,
  224. display.width()/2-i, display.height()/2+i,
  225. display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
  226. display.display();
  227. delay(1);
  228. }
  229. delay(2000);
  230. }
  231. void testfilltriangle(void) {
  232. display.clearDisplay();
  233. for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
  234. // The INVERSE color is used so triangles alternate white/black
  235. display.fillTriangle(
  236. display.width()/2 , display.height()/2-i,
  237. display.width()/2-i, display.height()/2+i,
  238. display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
  239. display.display();
  240. delay(1);
  241. }
  242. delay(2000);
  243. }
  244. void testdrawchar(void) {
  245. display.clearDisplay();
  246. display.setTextSize(1); // Normal 1:1 pixel scale
  247. display.setTextColor(SSD1306_WHITE); // Draw white text
  248. display.setCursor(0, 0); // Start at top-left corner
  249. display.cp437(true); // Use full 256 char 'Code Page 437' font
  250. // Not all the characters will fit on the display. This is normal.
  251. // Library will draw what it can and the rest will be clipped.
  252. for(int16_t i=0; i<256; i++) {
  253. if(i == '\n') display.write(' ');
  254. else display.write(i);
  255. }
  256. display.display();
  257. delay(2000);
  258. }
  259. void testdrawstyles(void) {
  260. display.clearDisplay();
  261. display.setTextSize(1); // Normal 1:1 pixel scale
  262. display.setTextColor(SSD1306_WHITE); // Draw white text
  263. display.setCursor(0,0); // Start at top-left corner
  264. display.println(F("Hello, world!"));
  265. display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
  266. display.println(3.141592);
  267. display.setTextSize(2); // Draw 2X-scale text
  268. display.setTextColor(SSD1306_WHITE);
  269. display.print(F("0x")); display.println(0xDEADBEEF, HEX);
  270. display.display();
  271. delay(2000);
  272. }
  273. void testscrolltext(void) {
  274. display.clearDisplay();
  275. display.setTextSize(2); // Draw 2X-scale text
  276. display.setTextColor(SSD1306_WHITE);
  277. display.setCursor(10, 0);
  278. display.println(F("scroll"));
  279. display.display(); // Show initial text
  280. delay(100);
  281. // Scroll in various directions, pausing in-between:
  282. display.startscrollright(0x00, 0x0F);
  283. delay(2000);
  284. display.stopscroll();
  285. delay(1000);
  286. display.startscrollleft(0x00, 0x0F);
  287. delay(2000);
  288. display.stopscroll();
  289. delay(1000);
  290. display.startscrolldiagright(0x00, 0x07);
  291. delay(2000);
  292. display.startscrolldiagleft(0x00, 0x07);
  293. delay(2000);
  294. display.stopscroll();
  295. delay(1000);
  296. }
  297. void testdrawbitmap(void) {
  298. display.clearDisplay();
  299. display.drawBitmap(
  300. (display.width() - LOGO_WIDTH ) / 2,
  301. (display.height() - LOGO_HEIGHT) / 2,
  302. logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  303. display.display();
  304. delay(1000);
  305. }
  306. #define XPOS 0 // Indexes into the 'icons' array in function below
  307. #define YPOS 1
  308. #define DELTAY 2
  309. void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  310. int8_t f, icons[NUMFLAKES][3];
  311. // Initialize 'snowflake' positions
  312. for(f=0; f< NUMFLAKES; f++) {
  313. icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
  314. icons[f][YPOS] = -LOGO_HEIGHT;
  315. icons[f][DELTAY] = random(1, 6);
  316. Serial.print(F("x: "));
  317. Serial.print(icons[f][XPOS], DEC);
  318. Serial.print(F(" y: "));
  319. Serial.print(icons[f][YPOS], DEC);
  320. Serial.print(F(" dy: "));
  321. Serial.println(icons[f][DELTAY], DEC);
  322. }
  323. for(;;) { // Loop forever...
  324. display.clearDisplay(); // Clear the display buffer
  325. // Draw each snowflake:
  326. for(f=0; f< NUMFLAKES; f++) {
  327. display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
  328. }
  329. display.display(); // Show the display buffer on the screen
  330. delay(200); // Pause for 1/10 second
  331. // Then update coordinates of each flake...
  332. for(f=0; f< NUMFLAKES; f++) {
  333. icons[f][YPOS] += icons[f][DELTAY];
  334. // If snowflake is off the bottom of the screen...
  335. if (icons[f][YPOS] >= display.height()) {
  336. // Reinitialize to a random position, just off the top
  337. icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
  338. icons[f][YPOS] = -LOGO_HEIGHT;
  339. icons[f][DELTAY] = random(1, 6);
  340. }
  341. }
  342. }
  343. }

重点

  • 记住绘制三部曲 clearDisplay->绘制类方法->display真正显示

4.2 实例二—— 博哥自定义测试 + 显示16X16中文字

具体代码

  1. /**
  2. * 日期:2017/09/24
  3. * 功能:OLED12864 SSD1306测试
  4. * 作者:单片机菜鸟
  5. * 16X16点阵显示 取模方式 阴码+逐行式+顺向
  6. **/
  7. #include <Wire.h>
  8. #include <Adafruit_GFX.h>
  9. #include <Adafruit_SSD1306.h>
  10. #define OLED_RESET 4
  11. Adafruit_SSD1306 display(OLED_RESET);
  12. #define NUMFLAKES 10
  13. #define XPOS 0
  14. #define YPOS 1
  15. #define DELTAY 2
  16. #define LOGO16_GLCD_HEIGHT 16
  17. #define LOGO16_GLCD_WIDTH 16
  18. #if (SSD1306_LCDHEIGHT != 64)
  19. #error("Height incorrect, please fix Adafruit_SSD1306.h!");
  20. #endif
  21. //显示一个心形
  22. static const uint8_t PROGMEM Heart_16x16[] = {
  23. 0x00,0x00,0x18,0x18,0x3C,0x3C,0x7E,0x7E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  24. 0xFF,0xFF,0x7F,0xFE,0x3F,0xFC,0x1F,0xF8,0x0F,0xF0,0x07,0xE0,0x03,0xC0,0x00,0x00//未命名文件0
  25. };
  26. //"猛"
  27. static const uint8_t PROGMEM Strong_16x16[] = {
  28. 0x00,0x00,0x45,0xFC,0x28,0x08,0x10,0x10,0x28,0x20,0x4B,0xFE,0x88,0x20,0x08,0xA0,
  29. 0x18,0x40,0x29,0xFC,0x49,0x54,0x89,0x54,0x09,0x54,0x09,0x54,0x57,0xFE,0x20,0x00//猛0
  30. };
  31. static const uint8_t PROGMEM Welcome_16x16[] ={
  32. 0x00,0x80,0x00,0x80,0xFC,0x80,0x04,0xFC,0x05,0x04,0x49,0x08,0x2A,0x40,0x14,0x40,
  33. 0x10,0x40,0x28,0xA0,0x24,0xA0,0x45,0x10,0x81,0x10,0x02,0x08,0x04,0x04,0x08,0x02,//欢0
  34. 0x00,0x00,0x20,0x80,0x13,0x3C,0x12,0x24,0x02,0x24,0x02,0x24,0xF2,0x24,0x12,0x24,
  35. 0x12,0x24,0x12,0xB4,0x13,0x28,0x12,0x20,0x10,0x20,0x28,0x20,0x47,0xFE,0x00,0x00,//迎1
  36. 0x01,0x00,0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x11,0x10,0x09,0x10,0x09,0x20,
  37. 0xFF,0xFE,0x03,0x80,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00,0x01,0x00,//来2
  38. 0x00,0x04,0xFF,0x84,0x08,0x04,0x10,0x24,0x22,0x24,0x41,0x24,0xFF,0xA4,0x08,0xA4,
  39. 0x08,0x24,0x08,0x24,0x7F,0x24,0x08,0x24,0x08,0x04,0x0F,0x84,0xF8,0x14,0x40,0x08,//到3
  40. 0x00,0x00,0x7F,0xFC,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xF8,
  41. 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00,//王4
  42. 0x02,0x00,0x02,0x08,0x3F,0xD0,0x02,0x20,0x02,0x40,0xFF,0xFE,0x01,0x00,0x02,0x00,
  43. 0x0F,0xF0,0x18,0x10,0x28,0x10,0x4F,0xF0,0x88,0x10,0x08,0x10,0x0F,0xF0,0x08,0x10,//者5
  44. 0x08,0x20,0x08,0x20,0xFF,0xFE,0x08,0x20,0x00,0x00,0x7F,0xFE,0x40,0x02,0x81,0x04,
  45. 0x01,0x00,0x7F,0xFC,0x03,0x80,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00,//荣6
  46. 0x10,0x00,0x11,0xDC,0x90,0x44,0x55,0x54,0x58,0xCC,0x11,0x54,0xFC,0x00,0x28,0x48,
  47. 0x28,0xFE,0x29,0x90,0x2A,0xFC,0x28,0x90,0x2A,0xFC,0x4C,0x90,0x48,0xFE,0x80,0x80//耀7
  48. };
  49. static const uint8_t PROGMEM Author_16x16[] ={
  50. 0x10,0x10,0x08,0x20,0x04,0x40,0x3F,0xF8,0x21,0x08,0x21,0x08,0x3F,0xF8,0x21,0x08,
  51. 0x21,0x08,0x3F,0xF8,0x01,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,//单0
  52. 0x00,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x1F,0xFC,0x10,0x00,0x10,0x00,
  53. 0x10,0x00,0x1F,0xE0,0x10,0x20,0x10,0x20,0x10,0x20,0x20,0x20,0x20,0x20,0x40,0x20,//片1
  54. 0x10,0x00,0x11,0xF0,0x11,0x10,0x11,0x10,0xFD,0x10,0x11,0x10,0x31,0x10,0x39,0x10,
  55. 0x55,0x10,0x55,0x10,0x91,0x10,0x11,0x12,0x11,0x12,0x12,0x12,0x12,0x0E,0x14,0x00,//机2
  56. 0x08,0x20,0x08,0x20,0xFF,0xFE,0x08,0x20,0x00,0x10,0x00,0xF8,0x3F,0x00,0x11,0x10,
  57. 0x08,0x20,0x01,0x00,0x7F,0xFC,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00,//菜3
  58. 0x01,0x00,0x02,0x00,0x1F,0xF0,0x10,0x10,0x12,0x10,0x11,0x10,0x11,0x50,0x10,0x20,
  59. 0x10,0x00,0x1F,0xFC,0x00,0x04,0x00,0x04,0x7F,0xE4,0x00,0x04,0x00,0x28,0x00,0x10,//鸟4
  60. };
  61. void setup() {
  62. Serial.begin(115200);
  63. delay(500);
  64. // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  65. display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
  66. }
  67. void loop() {
  68. test_SSD1306();
  69. }
  70. void test_SSD1306(void){
  71. //1.检测全屏显示(看看有没有大面积坏点)
  72. display.fillScreen(WHITE);
  73. display.display();
  74. delay(2000);
  75. //2.画点 点坐标(10,10)
  76. display.clearDisplay(); // clears the screen and buffer
  77. display.drawPixel(10, 10, WHITE);
  78. display.display();
  79. delay(2000);
  80. //3. 画线 从(0,0)到(50,50)
  81. display.clearDisplay(); // clears the screen and buffer
  82. display.drawLine(0, 0,50,50, WHITE);
  83. display.display();
  84. delay(2000);
  85. //4.画空心矩形 左上角坐标(x0,y0) 右下角坐标(x1,y1)
  86. display.clearDisplay(); // clears the screen and buffer
  87. display.drawRect(0,0,128,64,WHITE);
  88. display.display();
  89. delay(2000);
  90. //5.来画个实心矩形
  91. display.clearDisplay(); // clears the screen and buffer
  92. display.fillRect(0,0,64,64,WHITE);
  93. display.display();
  94. delay(2000);
  95. //6.画空心圆
  96. display.clearDisplay(); // clears the screen and buffer
  97. display.drawCircle(20,20,20,WHITE);
  98. display.display();
  99. delay(2000);
  100. //7.画实心圆
  101. display.clearDisplay(); // clears the screen and buffer
  102. display.fillCircle(20,20,20,WHITE);
  103. display.display();
  104. delay(2000);
  105. //8.画空心三角形
  106. display.clearDisplay(); // clears the screen and buffer
  107. display.drawTriangle(20,0,0,20,40,20,WHITE);
  108. display.display();
  109. delay(2000);
  110. //9.画实心三角形
  111. display.clearDisplay(); // clears the screen and buffer
  112. display.fillTriangle(20,0,0,20,40,20,WHITE);
  113. display.display();
  114. delay(2000);
  115. //10.画空心圆角矩形
  116. display.clearDisplay(); // clears the screen and buffer
  117. display.drawRoundRect(0,0,40,40,5,WHITE);
  118. display.display();
  119. delay(2000);
  120. //11.画实心圆角矩形
  121. display.clearDisplay(); // clears the screen and buffer
  122. display.fillRoundRect(0,0,40,40,5,WHITE);
  123. display.display();
  124. delay(2000);
  125. //12.画心形(楼主自己用取模软件画的)
  126. display.clearDisplay(); // clears the screen and buffer
  127. display.drawBitmap(16,16,Heart_16x16,16,16,WHITE);
  128. display.display();
  129. delay(2000);
  130. //13.显示英文 数字
  131. display.clearDisplay(); // clears the screen and buffer
  132. display.setTextSize(1);
  133. display.setTextColor(WHITE);
  134. display.setCursor(0,0);
  135. display.println("Hello, Arduino!");
  136. display.setTextColor(BLACK, WHITE); // 'inverted' text
  137. display.println(3.141592);
  138. display.setTextSize(2);
  139. display.setTextColor(WHITE);
  140. display.print("0x"); display.println(0xDEADBEEF, HEX);
  141. display.display();
  142. delay(2000);
  143. //14.显示单个文字 有木有发现就是调用drawBitmap
  144. display.clearDisplay(); // clears the screen and buffer
  145. display.drawBitmap(16,16,Strong_16x16,16,16,WHITE);
  146. display.display();
  147. delay(2000);
  148. //15.显示多个文字(楼主在库里面加入一个ShowCN_16方法 就是为了同时显示多个中文 16X16 ,不然的话 就得一个一个drawBitmap)
  149. display.clearDisplay(); // clears the screen and buffer
  150. display.ShowCN_16(0,0, Welcome_16x16,sizeof(Welcome_16x16)/32,WHITE);
  151. display.ShowCN_16(48,16, Author_16x16,sizeof(Author_16x16)/32,WHITE);
  152. display.display();
  153. delay(2000);
  154. }

注意点

  • 原生库中并没有ShowCN_16这个方法,是博哥后面在库中添加的。由于博客没有可以上传文件的地方,需要改进库的同学可以在这里下载

具体显示效果














注意点

  • 这里用到了字体取模软件(取模方式(阴码+逐行式+顺向),我也上传到了个人技术群)

    到此,基本上理论解答完毕。

5.总结

  • Adafruit_SSD1306 是针对 SSD1306这款OLED屏幕的显示图形库。
  • 性能上会比U8G2库更好,毕竟专人做专门的事情。
  • 博主这里只是抛砖引玉,希望读者在理解基础上去发掘更好的玩法。
  • 欢迎关注点赞博主,给予精神支持。

深入学习 OLED Adafruit_SSD1306库(8266+arduino)的更多相关文章

  1. OLED液晶屏幕(1)OLED液晶屏幕ssd1306驱动芯片 arduino运行 ESP8266-07可以 12f不可以

    OLED屏幕有各种形状和尺寸,但目前有两种非常受欢迎的屏幕尺寸. 1)0.96“ 2)1.3“ 他们也有2种常见的颜色 1)蓝色 2)白色 驱动OLED的芯片常用的有两种.这两种芯片有许多非常相似的设 ...

  2. 怎样学习使用libiconv库

    怎样学习使用libiconv库 - My Study My Study About My Learn or Study etc. 怎样学习使用libiconv库 By Cnangel on Febru ...

  3. ZhuSuan 是建立在Tensorflow上的贝叶斯深层学习的 python 库

    ZhuSuan 是建立在Tensorflow上的贝叶斯深层学习的 python 库. 与现有的主要针对监督任务设计的深度学习库不同,ZhuSuan 的特点是深入到贝叶斯推理中,从而支持各种生成模式:传 ...

  4. Python学习day45-数据库(总结)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  5. Python学习day44-数据库(单表及多表查询)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  6. Python学习day43-数据库(多表关系)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  7. Python学习day42-数据库的基本操作(1)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  8. Python学习day41-数据库(1)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  9. JavaWeb学习----JSTL标签库

    一.JSTL简介: JSTL全名为JavaServer Pages Standard Tag Library,中文名称为JSP标准标签函数库,目前最新的版本为1.2.JSTL是由JCP(Java Co ...

随机推荐

  1. springboot使用dubbo和zookeeper

    2019-11-17 yls 创建服务接口模块 接口工程只提供接口,不提供实现,在后面的提供者和消费者中使用 在使用接口的模块中只需要写具体实现类,避免了在每个模块中重复编写接口 在接口中引入依赖包 ...

  2. window中php的交互模式

    1.配置php的环境变量: 测试: cmd >> php --version 2.在cmd下编写测试脚本 1)  php -r  + php测试代码: 2) php -a + Enter  ...

  3. nyoj 63-小猴子下落 (模拟)

    63-小猴子下落 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:2 submit:5 题目描述: 有一颗二叉树,最大深度为D,且所有叶子的深度都相同 ...

  4. 【并发编程】synchronized的使用场景和原理简介

    1. synchronized使用 1.1 synchronized介绍 在多线程并发编程中synchronized一直是元老级角色,很多人都会称呼它为重量级锁.但是,随着Java SE 1.6对sy ...

  5. 页面加载和图片加载loading

    准备放假了!也是闲着了 ,就来整理之前学到或用到的一下知识点和使用内容,这次记录的是关于加载的友好性loading!!!这里记录一下两种加载方法 1.页面加载的方法,它需要用到js里面两个方法 doc ...

  6. 继上篇-jquery ajax提交 本篇用ajax提交的数据去数据库查询

    上篇讲到如何用jquery ajax提交数据至后台,后台接收并返回给ajax.https://www.cnblogs.com/tiezhuxiong/p/11943328.html 今天我们把数据传到 ...

  7. 几行代码轻松搞定python的sqlite3的存取

    很简单: 存数据: 1.加载sqlite3驱动(只需一行代码) 2.用驱动执行查询语句(只需一行代码) 取数据: 1.加载sqlite3驱动(只需一行代码) 2.用驱动执行查询语句(只需一行代码) 乍 ...

  8. 【02】对象的Getter and Setter

    java和C#非常相似,它们大部分的语法是一样的,但尽管如此,也有一些地方是不同的. 为了更好地学习java或C#,有必要分清它们两者到底在哪里不同. 我们这次要来探讨对象的Getter and Se ...

  9. 阿里云上万个 Kubernetes 集群大规模管理实践

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 汤志敏,阿里 ...

  10. day20191113笔记

    默写:程序=数据结构+操作系统. 一.文件上传 1.导入commons-fileupload.jar commons-io.jar 2.配置 <bean id="multipartRe ...