授人以魚不如授人以漁,目的不是爲了教會你具體項目開發,而是學會學習的能力。但願你們分享給你周邊須要的朋友或者同窗,說不定大神成長之路有博哥的奠定石。。。html
QQ技術互動交流羣:ESP8266&32 物聯網開發 羣號622368884,不喜勿噴git
1、基礎篇github
2、網絡篇web
- ESP8266開發之旅 網絡篇① 認識一下Arduino Core For ESP8266
- ESP8266開發之旅 網絡篇② ESP8266 工做模式與ESP8266WiFi庫
- ESP8266開發之旅 網絡篇③ Soft-AP——ESP8266WiFiAP庫的使用
- ESP8266開發之旅 網絡篇④ Station——ESP8266WiFiSTA庫的使用
- ESP8266開發之旅 網絡篇⑤ Scan WiFi——ESP8266WiFiScan庫的使用
- ESP8266開發之旅 網絡篇⑥ ESP8266WiFiGeneric——基礎庫
- ESP8266開發之旅 網絡篇⑦ TCP Server & TCP Client
- ESP8266開發之旅 網絡篇⑧ SmartConfig——一鍵配網
- ESP8266開發之旅 網絡篇⑨ HttpClient——ESP8266HTTPClient庫的使用
- ESP8266開發之旅 網絡篇⑩ UDP服務
- ESP8266開發之旅 網絡篇⑪ WebServer——ESP8266WebServer庫的使用
- ESP8266開發之旅 網絡篇⑫ 域名服務——ESP8266mDNS庫
- ESP8266開發之旅 網絡篇⑬ SPIFFS——ESP8266 Flash文件系統
- ESP8266開發之旅 網絡篇⑭ web配網
- ESP8266開發之旅 網絡篇⑮ 真正的域名服務——DNSServer
- ESP8266開發之旅 網絡篇⑯ 無線更新——OTA固件更新
3、應用篇設計模式
4、高級篇緩存
最近博主聽到QQ羣裏面問得比較多的問題:
「博哥,有玩過OLED嗎?」
「博哥,有試過在ESP8266上調成功過SSD1306嗎?」
「博哥,OLED上顯示天氣信息怎麼弄?」
........
諸如此類的問題,在博主看來,無非都是對OLED庫用法的不熟悉甚至不瞭解。Arduino OLED庫衆多,博主也曾經介紹過一款 《博哥OLED系列》- 玩轉SSD1306-12864 OLED Adafruit_GFX 和 Adafruit_SSD1306庫。可是,博主今天要介紹的是目前Arduino平臺上使用最普遍的OLED庫 —— U8G2庫,也是不少初學者容易懵逼的一個第三方庫。目前在github上超過1K star,1800次commit,能夠說維護熱度很高,讀者大可放心使用。
至於這個庫爲何這麼火爆,請讀者認真看完本博文自行評價,博主只能說功能真的很好很強大!!!!
那麼,博主首先立個flag,閱讀完本篇博文的最終效果——讀者之後在Arduino平臺上開發OLED項目的時候,能夠考慮U8G2庫,而且知道U8G2庫的具體用法,甚至能夠可以當作工具書來翻閱。
進入正文以前,博主要給讀者灌輸兩個個很是重要的知識點:網絡
OLED其實就是一個M x n 的像素點陣,想顯示什麼就得把具體位置的像素點亮起來。對於每個像素點,有多是1點亮,也有多是0點亮;
在座標系中,左上角是原點,向右是X軸,向下是Y軸。app
但願讀者能仔細理解這兩個知識點。函數
U8g2是嵌入式設備的單色圖形庫,一句話簡單明瞭。主要應用於嵌入式設備,包括咱們常見的單片機;工具
U8g2支持單色OLED和LCD,包括如下控制器:SSD1305,SSD1306,SSD1309,SSD1322,SSD1325,SSD1327,SSD1329,SSD1606,SSD1607,SH1106,SH1107,SH1108,SH1122,T6963,RA8835,LC7981,PCD8544,PCF8812,HX1230 ,UC1601,UC1604,UC1608,UC1610,UC1611,UC1701,ST7565,ST7567,ST7588,ST75256,NT7534,IST3020,ST7920,LD7032,KS0108,SED1520,SBN1661,IL3820,MAX7219(有關完整列表,請參見 此處)。
能夠說,基本上主流的顯示控制器都支持,好比咱們常見的SSD1306 12864,讀者在使用該庫以前請查閱本身的OLED顯示控制器是否處於支持列表中。
能夠說基本上全部Arduino API的主板都獲得U8g2的支持。包括:
因此說,讀者徹底不用擔憂兼容性問題,放心使用。
Arduino庫U8g2能夠從Arduino IDE的庫管理器安裝,讀者在庫管理器搜索「U8g2」關鍵字就能夠下載安裝:
下載完畢,測試一下庫是否安裝成功:
#include <U8g2lib.h> void setup() { // put your setup code here, to run once: } void loop() { // put your main code here, to run repeatedly: }
編譯成功,證實你本地已經加載了U8G2庫。
爲何要運用U8g2庫?也就是說U8g2庫能帶給咱們什麼樣的開發便利。在博主看來,主要考慮幾個方面:
如下是官方提供的一些U8G2庫測試圖,博主挑選了幾張常見的以及附上U8G2庫的配置(讀者能夠先不用理會配置,等看完博文再次閱讀就會了解含義):
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R2, /* clock=*/ 16, /* data=*/ 17, /* reset=*/ U8X8_PIN_NONE); // ESP32 Thing, pure SW emulated I2C U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R2, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 16, /* data=*/ 17); // ESP32 Thing, HW I2C with pin remapping
U8G2_MAX7219_32X8_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 11, /* data=*/ 12, /* cs=*/ 10, /* dc=*/ U8X8_PIN_NONE, /* reset=*/ U8X8_PIN_NONE);
U8G2_SSD1305_128X32_NONAME_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
U8X8_SSD1306_128X32_UNIVISION_SW_I2C u8x8(/* clock=A5*/ 19, /* data=A4*/ 18);
U8G2_PCD8544_84X48_1_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); // Nokia 5110 Display
U8G2_ST7920_128X64_1_8080 u8g2(U8G2_R0, 8, 9, 10, 11, 4, 5, 6, 7, /*enable=*/ 18 /* A4 */, /*cs=*/ U8X8_PIN_NONE, /*dc/rs=*/ 17 /* A3 */, /*reset=*/ 15 /* A1 */); // Remember to set R/W to 0
這只是一些常見的顯示器,能夠說,已經足夠覆蓋到咱們常見的範圍了。
老規則,先上一個圖:
方法能夠分爲四大類:
函數說明:
/** * 初始化U8g2庫 * @Note 關聯方法 initDisplay clearDisplay setPowerSave */ bool U8G2::begin(void)
源碼說明:
bool begin(void) { /* note: call to u8x8_utf8_init is not required here, this is done in the setup procedures before */ initDisplay(); //初始化顯示器 clearDisplay(); // 重置清屏 setPowerSave(0); //喚醒屏幕 return 1; }
函數說明:
/** * 簡單初始化U8g2庫 * @Note 關聯方法 beginSimple */ void U8G2::beginSimple(void);
源碼說明:
void beginSimple(void) { /* does not clear the display and does not wake up the display */ /* user is responsible for calling clearDisplay() and setPowerSave(0) */ initDisplay();//初始化顯示器 }
注意點:
函數說明:
/** * 初始化顯示控制器 */ void U8G2::initDisplay(void)
注意點:
函數說明:
/** * 清除屏幕 */ void U8G2::clearDisplay(void)
注意點:
函數說明:
/** * 清除顯示緩衝區 * @param is_enable * 1 表示啓用顯示器的省電模式,屏幕上看不到任何東西 * 0 表示禁用省電模式 */ void U8G2::setPowerSave(uint8_t is_enable)
注意點:
函數說明:
/** * 清除屏幕顯示,清除緩衝區,光標回到左上角原點位置(0,0) * @Note 關聯方法 home clearDisplay clearBuffer */ void U8G2::clear(void)
源碼說明:
void clear(void) { home(); //回到原點 clearDisplay(); //清除屏幕上的顯示 clearBuffer(); //清除緩衝區 }
函數說明:
/** * 清除內存中數據緩衝區 */ void U8G2::clearBuffer(void)
注意點:
void loop(void) { u8g2.clearBuffer(); // ... write something to the buffer u8g2.sendBuffer(); delay(1000); }
函數說明:
/** * 禁用Arduino平臺下支持輸出UTF8字符集,默認是開啓 */ void U8G2::disableUTF8Print(void)
函數說明:
/** * 開啓Arduino平臺下支持輸出UTF8字符集 */ void U8G2::enableUTF8Print(void)
注意點:
void setup(void) { u8g2.begin(); u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function } void loop(void) { u8g2.setFont(u8g2_font_unifont_t_chinese2); // use chinese2 for all the glyphs of "你好世界" u8g2.firstPage(); do { u8g2.setCursor(0, 40); u8g2.print("你好世界"); // Chinese "Hello World" } while ( u8g2.nextPage() ); delay(1000); }
函數說明:
/** * 重置顯示光標的位置,回到原點(0,0) * @Note 關聯方法 print clear */ void U8G2::home(void)
函數說明:
/** * 畫實心方形,左上角座標爲(x,y),寬度爲w,高度爲h * @param x 左上角的x座標 * @param y 左上角的y座標 * @param w 方形的寬度 * @param h 方形的高度 * @Note 關聯方法 drawFrame setDrawColor */ void U8G2::drawBox(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
注意點:
示例:
u8g2.drawBox(3,7,25,15);
函數說明:
/** * 畫空心圓,圓心座標爲(x0,y0),半徑爲rad * @param x0 圓點的x座標 * @param y0 圓點的y座標 * @param rad 圓形的半徑 * @param opt 圓形選項 * U8G_DRAW_ALL 整個圓 * U8G2_DRAW_UPPER_RIGHT 右上部分的圓弧 * U8G2_DRAW_UPPER_LEFT 左上部分的圓弧 * U8G2_DRAW_LOWER_LEFT 左下部分的圓弧 * U8G2_DRAW_LOWER_RIGHT 右下部分的圓弧 * 選項能夠經過 | 操做符來組合 * @Note 關聯方法 drawDisc setDrawColor */ void U8G2::drawCircle(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t opt = U8G2_DRAW_ALL)
注意點:
示例:
u8g2.drawCircle(20, 25, 10, U8G2_DRAW_ALL);
函數說明:
/** * 畫實心圓,圓心座標爲(x0,y0),半徑爲rad * @param x0 圓點的x座標 * @param y0 圓點的y座標 * @param rad 圓形的半徑 * @param opt 圓形選項 * U8G_DRAW_ALL 整個圓 * U8G2_DRAW_UPPER_RIGHT 右上部分的圓弧 * U8G2_DRAW_UPPER_LEFT 左上部分的圓弧 * U8G2_DRAW_LOWER_LEFT 左下部分的圓弧 * U8G2_DRAW_LOWER_RIGHT 右下部分的圓弧 * 選項能夠經過 | 操做符來組合 * @Note 關聯方法 drawCircle setDrawColor */ void U8G2::drawDisc(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t opt = U8G_DRAW_ALL)
注意點:
函數說明:
/** * 畫空心橢圓,圓心座標爲(x0,y0),半徑爲rad * @param x0 圓點的x座標 * @param y0 圓點的y座標 * @param rx 橢圓形水平x方向的半徑 * @param ry 橢圓形豎直y方向的半徑 * @param opt 圓形選項 * U8G_DRAW_ALL 整個橢圓 * U8G2_DRAW_UPPER_RIGHT 右上部分的圓弧 * U8G2_DRAW_UPPER_LEFT 左上部分的圓弧 * U8G2_DRAW_LOWER_LEFT 左下部分的圓弧 * U8G2_DRAW_LOWER_RIGHT 右下部分的圓弧 * 選項能夠經過 | 操做符來組合 * @Note 關聯方法 drawCircle */ void U8G2::drawEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t opt)
注意點:
示例:
u8g2.drawEllipse(20, 25, 15, 10, U8G2_DRAW_ALL);
函數說明:
/** * 畫實心橢圓,圓心座標爲(x0,y0),半徑爲rad * @param x0 圓點的x座標 * @param y0 圓點的y座標 * @param rx 橢圓形水平x方向的半徑 * @param ry 橢圓形豎直y方向的半徑 * @param opt 圓形選項 * U8G_DRAW_ALL 整個橢圓 * U8G2_DRAW_UPPER_RIGHT 右上部分的圓弧 * U8G2_DRAW_UPPER_LEFT 左上部分的圓弧 * U8G2_DRAW_LOWER_LEFT 左下部分的圓弧 * U8G2_DRAW_LOWER_RIGHT 右下部分的圓弧 * 選項能夠經過 | 操做符來組合 * @Note 關聯方法 drawCircle */ void U8G2::drawFilledEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t opt)
注意點:
函數說明:
/** * 畫空心方形,左上角座標爲(x,y),寬度爲w,高度爲h * @param x 左上角的x座標 * @param y 左上角的y座標 * @param w 方形的寬度 * @param h 方形的高度 * @Note 關聯方法 setDrawColor */ void U8G2::drawFrame(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h)
注意點:
示例:
u8g2.drawFrame(3,7,25,15);
函數說明:
/** * 繪製字體字集裏面定義的符號 * @param x 左上角的x座標 * @param y 左上角的y座標 * @param encoding 字符的unicode值 * @Note 關聯方法 setFont */ void U8G2::drawGlyph(u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding)
注意點:
函數說明:
/** * 繪製水平線 * @param x 左上角的x座標 * @param y 左上角的y座標 * @param w 水平線的長度 * @Note 關聯方法 setDrawColor */ void U8G2::drawHLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w)
注意點:
函數說明:
/** * 繪製線,從座標(x0,y0) 到(x1,y1) * @param x0 端點0的x座標 * @param y0 端點0的y座標 * @param x1 端點1的x座標 * @param y1 端點1的y座標 * @Note 關聯方法 setDrawColor */ void U8G2::drawLine(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t x1, u8g2_uint_t y1)
注意點:
示例:
u8g2.drawLine(20, 5, 5, 32);
函數說明:
/** * 繪製像素點,座標(x,y) * @param x 像素點的x座標 * @param y 像素點的y座標 * @Note 關聯方法 setDrawColor */ void U8G2::drawPixel(u8g2_uint_t x, u8g2_uint_t y)
注意點:
函數說明:
/** * 繪製圓角實心方形,左上角座標爲(x,y),寬度爲w,高度爲h,圓角半徑爲r * @param x 左上角的x座標 * @param y 左上角的y座標 * @param w 方形的寬度 * @param h 方形的高度 * @param r 圓角半徑 */ void U8G2::drawRBox(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)
注意點:
函數說明:
/** * 繪製圓角空心方形,左上角座標爲(x,y),寬度爲w,高度爲h,圓角半徑爲r * @param x 左上角的x座標 * @param y 左上角的y座標 * @param w 方形的寬度 * @param h 方形的高度 * @param r 圓角半徑 */ void U8G2::drawRFrame(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, u8g2_uint_t r)
注意點:
示例:
u8g2.drawRFrame(20,15,30,22,7);
函數說明:
/** * 繪製字符串 * @param x 左上角的x座標 * @param y 左上角的y座標 * @param s 繪製字符串內容 * @return 字符串的長度 */ u8g2_uint_t U8g2::drawStr(u8g2_uint_t x, u8g2_uint_t y, const char *s)
注意點:
示例:
u8g2.setFont(u8g2_font_ncenB14_tr); u8g2.drawStr(0,15,"Hello World!");
函數說明:
/** * 繪製實心三角形,定點座標分別爲(x0,y0),(x1,y1),(x2,y2) */ void U8G2::drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
示例:
u8g2.drawTriangle(20,5, 27,50, 5,32);
函數說明:
/** * 繪製UTF8編碼的字符串 * @param x 字符串在屏幕上的左下角x座標 * @param y 字符串在屏幕上的左下角y座標 * @param s 須要繪製的UTF-8編碼字符串 * @return 返回字符串的長度 */ u8g2_uint_t U8g2::drawUTF8(u8g2_uint_t x, u8g2_uint_t y, const char *s)
注意點:
示例:
u8g2.setFont(u8g2_font_unifont_t_symbols); u8g2.drawUTF8(5, 20, "Snowman: ☃");
函數說明:
/** * 繪製豎直線 * @param x 左上角座標x * @param y 左上角座標y * @param h 高度 */ void U8G2::drawVLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t h)
函數說明:
/** * 繪製圖像 * @param x 左上角座標x * @param y 左上角座標y * @param w 圖形寬度 * @param h 圖形高度 * @param bitmap 圖形內容 * @Note 關聯方法 setBitmapMode */ void U8G2::drawXBM(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap) void U8G2::drawXBMP(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
注意點:
函數說明:
/** * 繪製圖像 */ void U8G2::firstPage(void) uint8_t U8G2::nextPage(void)
注意點:
優點點:
示例:
u8g2.firstPage(); do { /* all graphics commands have to appear within the loop body. */ u8g2.setFont(u8g2_font_ncenB14_tr); u8g2.drawStr(0,20,"Hello World!"); } while ( u8g2.nextPage() );
庫源碼解析:
void u8g2_FirstPage(u8g2_t *u8g2) { if ( u8g2->is_auto_page_clear ) { //清除緩衝區 u8g2_ClearBuffer(u8g2); } //設置當前緩衝區的Tile Row 一個Tile等於8個像素點的高度 u8g2_SetBufferCurrTileRow(u8g2, 0); } uint8_t u8g2_NextPage(u8g2_t *u8g2) { uint8_t row; u8g2_send_buffer(u8g2); row = u8g2->tile_curr_row; row += u8g2->tile_buf_height; if ( row >= u8g2_GetU8x8(u8g2)->display_info->tile_height ) { //若是row已經到達最後一行,觸發refreshDisplay調用,表示整個頁面已經刷完了 u8x8_RefreshDisplay( u8g2_GetU8x8(u8g2) ); return 0; } if ( u8g2->is_auto_page_clear ) { //清除緩衝區 u8g2_ClearBuffer(u8g2); } //不斷更新TileRow 這是很是關鍵的一步 u8g2_SetBufferCurrTileRow(u8g2, row); return 1; }
函數說明:
/** * 繪製內容 * @Note 關聯方法 setFont setCursor enableUTF8Print */ void U8G2::print(...)
示例:
u8g2.setFont(u8g2_font_ncenB14_tr); u8g2.setCursor(0, 15); u8g2.print("Hello World!");
函數說明:
/** * 繪製緩衝區的內容 * @Note 關聯方法 clearBuffer */ void U8G2::sendBuffer(void)
注意點:
庫源碼解析:
void u8g2_SendBuffer(u8g2_t *u8g2) { u8g2_send_buffer(u8g2); u8x8_RefreshDisplay( u8g2_GetU8x8(u8g2) ); } static void u8g2_send_tile_row(u8g2_t *u8g2, uint8_t src_tile_row, uint8_t dest_tile_row) { uint8_t *ptr; uint16_t offset; uint8_t w; w = u8g2_GetU8x8(u8g2)->display_info->tile_width; offset = src_tile_row; ptr = u8g2->tile_buf_ptr; offset *= w; offset *= 8; ptr += offset; u8x8_DrawTile(u8g2_GetU8x8(u8g2), 0, dest_tile_row, w, ptr); } /* write the buffer to the display RAM. For most displays, this will make the content visible to the user. Some displays (like the SSD1606) require a u8x8_RefreshDisplay() */ static void u8g2_send_buffer(u8g2_t *u8g2) U8X8_NOINLINE; static void u8g2_send_buffer(u8g2_t *u8g2) { uint8_t src_row; uint8_t src_max; uint8_t dest_row; uint8_t dest_max; src_row = 0; src_max = u8g2->tile_buf_height; dest_row = u8g2->tile_curr_row; dest_max = u8g2_GetU8x8(u8g2)->display_info->tile_height; do { u8g2_send_tile_row(u8g2, src_row, dest_row); src_row++; dest_row++; } while( src_row < src_max && dest_row < dest_max ); }
示例:
void loop(void) { u8g2.clearBuffer(); // ... write something to the buffer u8g2.sendBuffer(); delay(1000);
函數說明:
/** * 獲取基準線以上的高度 * @return 返回高度值 * @Note 關聯方法 setFont getDescent setFontRefHeightAll */ int8_t U8G2::getAscent(void)
注意點:
示例:
下面例子,ascent是18
函數說明:
/** * 獲取基準線如下的高度 * @return 返回高度值 * @Note 關聯方法 setFont setFontRefHeightAll */ int8_t U8G2::getDescent(void)
注意點:
示例:
下面例子,descent是-5
函數說明:
/** * 獲取顯示器的高度 * @return 返回高度值 */ u8g2_uint_t getDisplayHeight(void)
函數說明:
/** * 獲取顯示器的寬度 * @return 返回寬度值 */ u8g2_uint_t getDisplayWidth(void)
函數說明:
/** * 獲取當前字體裏的最大字符的高度 * @return 返回高度值 * @Note 關聯方法 setFont */ u8g2_uint_t getMaxCharHeight(void)
注意點:
函數說明:
/** * 獲取當前字體裏的最大字符的寬度 * @return 返回寬度值 * @Note 關聯方法 setFont */ u8g2_uint_t getMaxCharWidth(void)
注意點:
函數說明:
/** * 獲取字符串的像素寬度 * @param s 繪製字符串 * @return 返回字符串的像素寬度值 * @Note 關聯方法 setFont drawStr */ u8g2_uint_t U8G2::getStrWidth(const char *s)
注意點:
函數說明:
/** * 獲取UTF-8字符串的像素寬度 * @param s 繪製字符串 * @return 返回字符串的像素寬度值 * @Note 關聯方法 setFont drawStr */ u8g2_uint_t U8G2::getUTF8Width(const char *s)
注意點:
函數說明:
/** * 是否自動清除緩衝區 * @param mode 0 表示關閉 * 1 表示開啓,默認是開啓 */ void U8G2::setAutoPageClear(uint8_t mode)
注意點:
函數說明:
/** * 設置位圖模式(定義drawXBM方法是否繪製背景顏色) * @param is_transparent * 0 繪製背景顏色,不透明,默認是該值 * 1 不繪製背景顏色,透明 * @Note 關聯方法 drawXBM */ void U8G2::setBitmapMode(uint8_t is_transparent)
示例:
u8g2.setDrawColor(1); u8g2.setBitmapMode(0); u8g2.drawXBM(4,3, u8g2_logo_97x51_width, u8g2_logo_97x51_height, u8g2_logo_97x51_bits); u8g2.drawXBM(12,11, u8g2_logo_97x51_width, u8g2_logo_97x51_height, u8g2_logo_97x51_bits);
u8g2.setDrawColor(1); u8g2.setBitmapMode(1); u8g2.drawXBM(4,3, u8g2_logo_97x51_width, u8g2_logo_97x51_height, u8g2_logo_97x51_bits); u8g2.drawXBM(12,11, u8g2_logo_97x51_width, u8g2_logo_97x51_height, u8g2_logo_97x51_bits);
函數說明:
/** * 設置總線時鐘(I2C SPI) * @param mode clock_speed 總線時鐘頻率(Hz) * @Note 關聯方法 begin */ void U8G2::setBusClock(uint32_t clock_speed);
注意點:
函數說明:
/** * 設置採集窗口,窗口範圍從左上角(x0,y0)到右下角(x1,y1) * 也就是咱們繪製的內容只能在規範範圍內顯示 * @param x0 左上角x座標 * @param y0 左上角y座標 * @param x1 右上角x座標 * @param y1 右上角y座標 * @Note 關聯方法 begin */ void U8G2::setClipWindow(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t x1, u8g2_uint_t y1 );
注意點:
void U8G2::setMaxClipWindow(void)
示例:
u8g2.setClipWindow(10, 10, 85, 30); u8g2.setDrawColor(1); u8g2.drawStr(3, 32, "U8g2");
函數說明:
/** * 設置繪製光標位置(x,y) * @Note 關聯方法 print */ void U8G2::setCursor(u8g2_uint_t x, u8g2_uint_t y)
示例:
u8g2.setFont(u8g2_font_ncenB14_tr); u8g2.setCursor(0, 15); u8g2.print("Hello World!");
函數說明:
/** * 設置顯示器的旋轉角度 * @param u8g2_cb 旋轉選項 * U8G2_R0 不作旋轉 水平 * U8G2_R1 旋轉90度 * U8G2_R2 旋轉180度 * U8G2_R3 旋轉270度 * U8G2_MIRROR 不作旋轉 水平,顯示內容是鏡像的,暫時不理解 */ void setDisplayRotation(const u8g2_cb_t *u8g2_cb)
函數說明:
/** * 設置繪製顏色(暫時尚未具體去了解用法) */ void U8G2::setDrawColor(uint8_t color)
這是一個很是重要的方法,很是重要!!!
函數說明:
/** * 設置字體集(字體集用於字符串繪製方法或者glyph繪製方法) * @param font 具體的字體集 * @Note 關聯方法 drawUTF8 drawStr drawGlyph print */ void U8G2::setFont(const uint8_t *font)
Font會根據像素點高度作了不少區分,具體font請參考 wiki。
若是咱們須要用到中文字符,能夠在wiki裏面搜索一下chinese,你就會發現不少中文font,好比:
//支持UTF-8或者GB2312編碼 u8g2_font_wqy15_t_chinese1 u8g2_font_wqy15_t_chinese2 u8g2_font_wqy15_t_chinese3 u8g2_font_wqy12_t_gb2312 u8g2_font_wqy12_t_gb2312a ......
注意點:
至於用哪個,看本身的需求了。
咱們看看Font的命名規則:
<prefix> '_' <name> '_' <purpose> <char set>
其中:
|
描述 |
---|---|
t | Transparent font, Do not use a background color. |
h | All glyphs have common height(全部的圖形有通用的高度). |
m | All glyphs have common height and width (monospace). |
8 | All glyphs fit into a 8x8 pixel box. |
|
描述 |
---|---|
f | The font includes up to 256 glyphs. |
r | Only glyphs on the range of the ASCII codes 32 to 127 are included in the font. |
u | Only glyphs on the range of the ASCII codes 32 to 95 (uppercase chars) are included in the font. |
n | Only numbers and extra glyphs for writing date and time strings are included in the font. |
... | Other custom character list. |
注意點:
示例:Fonts u8g2_font_5x7_tr and u8g2_font_pressstart2p_8u
函數說明:
/** * 定義字符串繪製或者圖形繪製的方向 * @param dir 方向 * @param 關聯方法 drawStr */ void U8G2::setFontDirection(uint8_t dir)
注意點:
Argument | String Rotation | Description |
---|---|---|
0 | 0 degree | Left to right |
1 | 90 degree | Top to down |
2 | 180 degree | Right to left |
3 | 270 degree | Down to top |
示例:
u8g2.setFont(u8g2_font_ncenB14_tf); u8g2.setFontDirection(0); u8g2.drawStr(15, 20, "Abc"); u8g2.setFontDirection(1); u8g2.drawStr(15, 20, "Abc");
緩存相關函數,通常不會去操做,瞭解便可;
函數說明
/** * 獲取緩存空間的地址 * @return 返回緩存空間起始地址 * @Note 關聯方法 getBufferTileHeight, getBufferTileWidth, clearBuffer */ uint8_t *U8G2::getBufferPtr(void)
注意點:
函數說明
/** * 獲取緩衝區的Tile高度 * @return 返回高度值 */ uint8_t U8G2::getBufferTileHeight(void)
注意點:
函數說明
/** * 獲取緩衝區的Tile寬度 * @return 返回寬度值 */ uint8_t U8G2::getBufferTileWidth(void)
注意點:
函數說明
/** * 獲取緩衝區的當前Tile row行數 * @return 返回當前的tilerow */ uint8_t U8G2::getBufferCurrTileRow(void)
注意點:
函數說明
/** * 設置緩衝區的當前Tile row * @param 當前的tilerow */ void U8G2::setBufferCurrTileRow(uint8_t row)
注意點:
示例:
u8g2.setBufferCurrTileRow(0); // let y=0 be the topmost row of the buffer u8g2.clearBuffer(); u8g2.setFont(u8g2_font_helvB08_tr); u8g2.drawStr(2, 8, "abcdefg"); u8g2.setBufferCurrTileRow(2); // write the buffer to tile row 2 (y=16) on the display u8g2.sendBuffer(); u8g2.setBufferCurrTileRow(4); // write the same buffer to tile row 4 (y=32) on the display u8g2.sendBuffer();
利用好該方法,咱們能夠實現部分更新;
前面博主介紹到U8G2適配了絕大部分的OLED,那麼咱們如何構建具體的OLED驅動呢?可分爲如下幾個順序步驟:
首先,你須要知道OLED顯示器的控制器型號以及屏幕大小。舉個例子,博主手上有一塊SSD1306 128X64的OLED,那麼它的控制器就是SSD1306,屏幕大小是128X64。
其次,你所選擇的OLED必須在U8g2庫所支持的OLED列表中,具體可參考 連接地址。
圖像信息是經過物理總線方式發給OLED顯示器。一般,咱們的總線包括:
具體的OLED使用什麼物理總線,咱們須要查閱各自的數據手冊。好比,博主的SSD1306就是IIC。
知道了物理連線模式以後,咱們通常都是把OLED鏈接到Arduino Board的輸出引腳,也就是軟件模擬具體總線協議。固然,若是有現成的物理總線端口那就更好了。
經歷以上三步以後,咱們就能夠開始初始化出具體的OLED驅動了。好比,博主的IIC SSD1306 128X64 的OLED,就能夠用如下初始化構造器(Builder設計模式,有空能夠去了解一下):
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // All Boards without Reset of the Display
固然SSD1306還有其餘構造器(具體能夠參考 wiki):
Controller "ssd1306", Display "128x64_noname" | Descirption |
---|---|
U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI(rotation, clock, data, cs, dc [, reset]) | page buffer, size = 128 bytes |
U8G2_SSD1306_128X64_NONAME_2_4W_SW_SPI(rotation, clock, data, cs, dc [, reset]) | page buffer, size = 256 bytes |
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI(rotation, clock, data, cs, dc [, reset]) | full framebuffer, size = 1024 bytes |
U8G2_SSD1306_128X64_NONAME_1_4W_HW_SPI(rotation, cs, dc [, reset]) | page buffer, size = 128 bytes |
那麼,咱們這裏就須要重點講述一下構造器的規則。
構造器的名字包括如下幾方面:
No | Description | Example |
---|---|---|
1 | Prefix | U8G2 |
2 | Display Controller | SSD1306 |
3 | Display Name | 128X64_NONAME |
4 | Buffer Size | 1, 2 or F (full frame buffer) |
5 | Communication | 4W_SW_SPI |
它們之間使用"_"鏈接起來。其中:
BufferSize | Description |
---|---|
1 | 保持一頁的緩衝區,用於firstPage/nextPage的PageMode. |
2 | 保持兩頁的緩衝區,用於firstPage/nextPage的PageMode.. |
F | 獲取整個屏幕的緩衝區,ram消耗大,通常用在ram空間比較大的arduino板子. |
Communication | Description |
---|---|
4W_SW_SPI | 4-wire (clock, data, cs and dc) software emulated SPI |
4W_HW_SPI | 4-wire (clock, data, cs and dc) hardware SPI (based on Arduino SPI library) |
2ND_4W_HW_SPI | If supported, second 4-wire hardware SPI (based on Arduino SPI library) |
3W_SW_SPI | 3-wire (clock, data and cs) software emulated SPI |
SW_I2C | Software emulated I2C/TWI |
HW_I2C | Hardware I2C based on the Arduino Wire library |
2ND_HW_I2C | If supported, use second hardware I2C (Arduino Wire lib) |
6800 | 8-bit parallel interface, 6800 protocol |
8080 | 8-bit parallel interface, 8080 protocol |
Rotation/Mirror | Description |
---|---|
U8G2_R0 | No rotation, landscape |
U8G2_R1 | 90 degree clockwise rotation |
U8G2_R2 | 180 degree clockwise rotation |
U8G2_R3 | 270 degree clockwise rotation |
U8G2_MIRROR | No rotation, landscape, display content is mirrored (v2.6.x) |
因此,一個完整的例子爲:
#include <Arduino.h> #include <U8g2lib.h> #include <SPI.h> #include <Wire.h> U8G2_ST7920_128X64_1_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8); void setup(void) { u8g2.begin(); } void loop(void) { u8g2.firstPage(); do { u8g2.setFont(u8g2_font_ncenB14_tr); u8g2.drawStr(0,24,"Hello World!"); } while ( u8g2.nextPage() ); }
那麼,咱們來看看到底構造器裏面作了什麼操做?仍是以博主使用的SSD1306 128X64爲例子:
/** * SSD1306 4線軟件模擬SPI */ U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI(.....)
類定義:
/** * SSD1306構造器,繼承U8G2 */ class U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI : public U8G2 { public: U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI(const u8g2_cb_t *rotation, uint8_t clock, uint8_t data, uint8_t cs, uint8_t dc, uint8_t reset = U8X8_PIN_NONE) : U8G2() { //配置SSD1306 u8g2_Setup_ssd1306_128x64_noname_1(&u8g2, rotation, u8x8_byte_arduino_4wire_sw_spi, u8x8_gpio_and_delay_arduino); //設置通訊協議 u8x8_SetPin_4Wire_SW_SPI(getU8x8(), clock, data, cs, dc, reset); } };
從上面代碼看出,默認調用了父類U8G2的構造函數,咱們看看它裏面作了什麼:
class U8G2 : public Print { protected: u8g2_t u8g2; u8x8_char_cb cpp_next_cb; /* the cpp interface has its own decoding function for the Arduino print command */ public: u8g2_uint_t tx, ty; U8G2(void) { //設置Arduino print函數的解碼方法,這裏是ASCII,固然也有UTF-8 cpp_next_cb = u8x8_ascii_next; //屏幕初始化 home(); } .......
而後咱們看看,u8g2_Setup_ssd1306_128x64_noname_1作了什麼:
void u8g2_Setup_ssd1306_128x64_noname_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb) { uint8_t tile_buf_height; //定義好緩存空間 記住 這裏是 1 page mode uint8_t *buf; //配置屏幕 u8g2_SetupDisplay(u8g2, u8x8_d_ssd1306_128x64_noname, u8x8_cad_001, byte_cb, gpio_and_delay_cb); //生成buf 這裏是128 bytes buf = u8g2_m_16_8_1(&tile_buf_height); //初始化buf u8g2_SetupBuffer(u8g2, buf, tile_buf_height, u8g2_ll_hvline_vertical_top_lsb, rotation); } /*============================================*/ /* This procedure is called after setting up the display (u8x8 structure). --> This is the central init procedure for u8g2 object */ void u8g2_SetupBuffer(u8g2_t *u8g2, uint8_t *buf, uint8_t tile_buf_height, u8g2_draw_ll_hvline_cb ll_hvline_cb, const u8g2_cb_t *u8g2_cb) { u8g2->font = NULL; //u8g2->kerning = NULL; //u8g2->get_kerning_cb = u8g2_GetNullKerning; //u8g2->ll_hvline = u8g2_ll_hvline_vertical_top_lsb; u8g2->ll_hvline = ll_hvline_cb; u8g2->tile_buf_ptr = buf; u8g2->tile_buf_height = tile_buf_height; u8g2->tile_curr_row = 0;//頁碼 這是一個很重要的參數 u8g2->font_decode.is_transparent = 0; /* issue 443 */ u8g2->bitmap_transparency = 0; u8g2->draw_color = 1; u8g2->is_auto_page_clear = 1;//自動清除 u8g2->cb = u8g2_cb; u8g2->cb->update_dimension(u8g2); #ifdef U8G2_WITH_CLIP_WINDOW_SUPPORT u8g2_SetMaxClipWindow(u8g2); /* assign a clip window and call the update() procedure */ #else u8g2->cb->update_page_win(u8g2); #endif u8g2_SetFontPosBaseline(u8g2); /* issue 195 */ #ifdef U8G2_WITH_FONT_ROTATION u8g2->font_decode.dir = 0; #endif }
能夠總結幾點:
注意點:
U8g2支持三種繪製模式:
特色:
構造器:
U8G2_ST7920_128X64_F_SW_SPI(rotation, clock, data, cs [, reset])
用法:
示例代碼:
void setup(void) { u8g2.begin(); } void loop(void) { u8g2.clearBuffer(); u8g2.setFont(u8g2_font_ncenB14_tr); u8g2.drawStr(0,20,"Hello World!"); u8g2.sendBuffer(); }
特色:
構造器:
U8G2_ST7920_128X64_ 1 _SW_SPI(rotation, clock, data, cs [, reset])
用法:
示例代碼:
void setup(void) { u8g2.begin(); } void loop(void) { u8g2.firstPage(); do { u8g2.setFont(u8g2_font_ncenB14_tr); u8g2.drawStr(0,24,"Hello World!"); } while ( u8g2.nextPage() ); }
特色:
構造器:
U8X8_ST7565_EA_DOGM128_4W_SW_SPI(clock, data, cs, dc [, reset])
用法:
示例代碼:
void setup(void) { u8x8.begin(); } void loop(void) { u8x8.setFont(u8x8_font_chroma48medium8_r); u8x8.drawString(0,1,"Hello World!"); }