2022年2月13日 星期日

常用微控制板接腳圖 (Pin Layout)

Arduino UNO
Arduino Leonardo
Arduino NANO
Arduino Pro mini
Arduino Pro micro
ESP8266 GPIO
NodeMCU 1.0 (ESP8266)
WeMos D1 mini (ESP8266)
NodeOLED (ESP8266)
ESP-01 (ESP8266)
ESP32 DevBoard (ESP32)
Node ESP-32S (ESP32)
Ai-Thinker ESP12K (ESP32-S2)
Mediatek Linkit 7697 Nano
Mediatek Linkit 7697 Nano Board
Mediatek Linkit 7697 Bit
Microbit

2022年2月11日 星期五

自訂 Linux 的 Bash Shell 命令提示字串 Prompt

如何在 Linux 或 Unix 操作系統下更改 shell 提示的顏色?如何在 Linux、macOS 或類 Unix 系統上自定義和著色我的 Bash 提示符 PS1

我們可以更改 shell 提示符的顏色,或者在命令提示符下讓工作變得更輕鬆。BASH shell 是 Linux 和 Apple OS X 下的預設的設置。現在讓我們看看在 Linux 或 Unix 系統上使用 bash 時如何更改 shell 提示的顏色。

基本設定方法

Linux 的" Bash Shell 命令提示字串可以透過 PS1 這個環境變數來設定,通常他都是寫在 ~/.bashrc 或是 ~/.bash_profile 這些 Bash 的設定檔中,通常預設的設定會類似這樣:

PS1="\u@\h \W$ "

PS1 的設定中,若以反斜線加上一個特定字母,都有一些特殊意義:

  • \u:表使用者的帳號名稱。
  • \h:主機名稱。
  • \W:目前的工作目錄名稱。

顯示出來的結果會像這樣:

通常剛裝好的 Linux 系統,命令提示字串大概就是像這樣,沒有什麼特別,但是其實它的功能很強大,可以有很多的變化,以下是一些常用的功能介紹。

顯示時間

PS1 環境變數中,您可以使用 $(linux_command) 的方式,直接執行任何的 Linux 指令,下面是一個執行 $(date) 來顯示目前時間的例子。

PS1="\u@\h [$(date +%k:%M:%S)]> "

結果會像這樣:

另一種方式是直接使用 \t,則可以顯示 hh:mm:ss 格式的時間,例如:

PS1="[\t] \u@$(pwd)> "

而 \@ 則是可以顯示 12 小時制的時間:

PS1="[\@] \u@$(pwd)> "

任意指令輸出

如果您對於 shell 的程式設計很熟悉的話,可以在 PS1 插入任何的指令輸出或是變數:

kernel_version=$(uname -r)
PS1="\!|\h|$kernel_version|$? > "

文字顏色

命令提示字串也可以使用彩色的文字:

PS1="\e[0;34m\u@\h \w\e[0m > "

這裡文字的色彩是靠 ANSI escape code 來指定的,\e[0;34m 是顏色指定的開始控制碼,結束是 \e[0m,而在放這中間的所有文字都會是有顏色的,而文字的顏色則是由開始控制碼中的數值來決定:

  • 0 與 1:0 代表正常亮度,1 代表高亮度。
  • 30 與 37:30 + x 所得到的數值可指定前景顏色(x 值與顏色的對應請參考下面的對應表)。
  • 40 與 47:40 + x 所得到的數值可指定背景顏色(x 值與顏色的對應請參考下面的對應表)。
  • 多個數值之間以分號(;)隔開,像這裡的 \e[0;34m 就是指定正常亮度(0),顏色為藍色(34 = 30 + 4),結果會像這樣:

    這是使用高亮度(1)的狀況:

    PS1="\e[1;34m\u@\h \w\e[0m > "

    加上背景的顏色:

    PS1="\e[0;34;47m\u@\h \w\e[0m > "

    使用多種顏色:

    PS1='\e[1;37m\t\e[0m\n\e[1;32m\u\e[1;33m@\e[1;32m\h\e[33m:\e[1;36m$(pwd)\e[1;33m\$\e[0m '

    PS1 特殊字元

    以下這些是在 PS1 中可以使用的特殊字元,您可以用運這些設計自己的命令提示字串。

    • \a:ASCII bell 字元(07)。
    • \d:格式為 Weekday Month Date 的日期(例如 Tue May 26)。
    • \D{format}:將 format 傳給 strftime(3),然後將輸出的結果放進命令提示字串中,如果 format 是空字串,就會使用目前語系的預設的格式,其中的大括號不可以省略。
    • \e:ASCII 跳脫字元(escape character,033)。
    • \h:機器的簡短主機名稱(hostname),只顯示到第一個句點之前。
    • \H:機器的完整主機名稱(hostname)。
    • \j:目前的 shell 所掌控的 jobs 數量。
    • \l:the basename of the shell’s terminal device name。
    • \n:換行。
    • \r:carriage return。
    • \s:the name of the shell, the basename of $0 (the portion following the final slash)。
    • \t:現在時間,24 小時制(HH:MM:SS)。
    • \T:現在時間,12 小時制(HH:MM:SS)。
    • \@:現在時間,12 小時制(HH:MM AM/PM)。
    • \A:現在時間,24 小時制(HH:MM)。
    • \u:目前使用者的使用者名稱(username)。
    • \v:目前的 bash shell 版本(如 2.00)。
    • \V:目前的 bash shell 詳細版本(如 2.00.0)。
    • \w:目前的工作目錄完整路徑,若在 $HOME 中,則以 ~ 顯示。
    • \W:目前的工作目錄名稱,若在 $HOME 中,則以 ~ 顯示。
    • \!:目前指令的歷史紀錄編號。
    • \#:目前指令的編號。
    • \$:如果是 root 管理者,則顯示 #,否則顯示 $。
    • \n:以八進位表示字元,例如 33。the character corresponding to the octal number nnn。
    • \\:反斜線。
    • [ 與 ]:當 PS1 參雜一些無法顯示的字元時,就要用這兩個特殊字元包起來,這樣顯示才會正常,例如所有控制顏色或是格式的控制碼,都要加上這兩個特殊字元,這樣可以避免 bash 在計算提示字元長度時出錯。

    只要善用這些特殊字元,其實就可以讓自己的命令提示字串有許多的變化。

    2022年2月4日 星期五

    讓 U8G2 OLED 函式庫在 Arduino 中活用

    快速連結

    什麼是 u8g2?

    大家也知道,OLED 規格相當多,常見的就有 SSD1306 和 SH1106,LCD 更不用說了,如果為了這些不同的顯示器去找對映的函式庫,有時還真的蠻累人的,而且還有 ESP8266 或 ESP32 支援的問題。

    u8g2是嵌入式設備的單色圖形庫,一句話簡單明瞭。

    還好有 u8g2 函式庫,它算是 u8glib 的新版本,它對顯示器的支援超強大的!舉凡常見的 OLED,像是 SSD1306 和 SH1106,或是其它各種 TFT LCD,都在它的支援範圍,真的是學一招就無敵了!

    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。
    有關完整列表,請參見連結

    安裝、測試 u8g2 函式庫

    先安裝 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 的顯示效果與宣告語法:

    ESP32 and SSD1306 OLED

    SW I2C and HW I2C with pin-remapping will work:

    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
    MAX7219 32x8 LED Matrix

    The MAX7219 is a LED driver for one 8x8 LED matrix. Multiple 8x8 blocks can be connected together. Here added support for a 32x8 LED matrix.

    U8x8 API is not supported, but the U8x8 fonts are also available for U8g2. The MAX7219 does not require a dc input signal, it has to be set to U8X8_PIN_NONE. The LOAD input line of the MAX7219 has to be connected as cs.

    U8G2_MAX7219_32X8_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 11, /* data=*/ 12, /* cs=*/ 10, /* dc=*/ U8X8_PIN_NONE, /* reset=*/ U8X8_PIN_NONE);
    WEMOS D1 (ESP8266) OLED Shield

    The 64x48 OLED Shield for the WEMOS ESP8266 boards. It features a SSD1306 driver and works with no special modification using the I2C bus (hardware or software):

    U8G2_SSD1306_64X48_ER_F_HW_I2C u8g2(U8G2_R0); // hardware
    U8G2_SSD1306_64X48_ER_F_SW_I2C u8g2(U8G2_R0, D1, D2); // software

    u8g2 庫函數

    u8g2 庫函數可以分爲四大類:

    • 基本函數
    • 繪製相關函數
    • 顯示配置相關函數
    • 緩存相關函數

    基本函數

    u8g2.begin() —— 建構 u8g2

    /**
    * 初始化 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.beginSimple() —— 建構 u8g2

    /**
    * 初始化 u8g2 庫
    * @Note 關聯方法 initDisplay clearDisplay setPowerSave
    */
    bool U8G2::beginSimple(void)
    
    bool beginSimple(void) {
        /* does not clear the display and does not wake up the display */
        /* user is responsible for calling clearDisplay() and setPowerSave(0) */
        initDisplay();   //初始化顯示器
    }

    註:
    可以看到和 begin() 函數的區別,需要用戶自行控制初始化過程,給了一定的自由度,不過建議還是直接用 begin 函數吧。

    u8g2.clearDisplay() —— 清除屏幕內容

    /**
    * 清除屏幕內容
    */
    void U8G2::clearDisplay(void)

    註:
    ① 這個方法不需要我們單獨調用,會在 begin 函數主動調用一次,我們主要理解即可。
    ② 不要在 firstPage 和 nextPage 函數之間調用該方法。

    u8g2.setPowerSave() —— 是否開啓省電模式

    /**
    * 清除顯示緩衝區
    * @param is_enable
    *        1 表示啓用顯示器的省電模式,屏幕上看不到任何東西
    *        0 表示禁用省電模式
    */
    void U8G2::setPowerSave(uint8_t is_enable)

    註:
    ① 不管是啓用還是禁用,顯示器需要的內存消耗是不會變的,說到底就是爲了關閉屏幕,做到省電。
    ② 所以這裏就可以理解爲什麼初始化需要 setPowerSave(0); 。

    u8g2.clear() —— 清除操作

    /**
    * 清除屏幕顯示,清除緩衝區,光標回到左上角原點位置(0,0)
    * @Note 關聯方法 home clearDisplay clearBuffer
    */
    void U8G2::clear(void)
    
    void clear(void) { 
        home();         //回到原點
        clearDisplay(); //清除屏幕上的顯示
        clearBuffer();  //清除緩衝區
    }

    u8g2.clearBuffer() —— 清除緩衝區

    /**
    * 清除內存中數據緩衝區
    */
    void U8G2::clearBuffer(void)

    註:
    一般這個函數是與 sendBuffer 函數配對使用,通常用法如下:

    void loop(void) {
        u8g2.clearBuffer();
        // ... write something to the buffer 
        u8g2.sendBuffer();
        delay(1000);
    }

    u8g2.disableUTF8Print() —— 禁用 UTF8 字型顯示

    /**
    * 禁用 Arduino 平臺下輸出 UTF8 字符集,默認是開啓
    */
    void U8G2::disableUTF8Print(void)

    u8g2.enableUTF8Print() —— 啟用 UTF8 字型顯示

    /**
    * 開啟 Arduino 平臺下輸出 UTF8 字符集
    */
    void U8G2::enableUTF8Print(void)

    註:
    我們的中文字符就是 UTF8。常見範例如下:

    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); 
        u8g2.firstPage();
        do {
            u8g2.setCursor(0, 40);
            u8g2.print("你好世界");
        } while ( u8g2.nextPage() );
        delay(1000);
    }

    u8g2.home() —— 重置顯示游標的位置

    /**
    * 重置顯示游標的位置,回到原點(0,0)
    * @Note 關聯方法 print clear
    */
    void U8G2::home(void)
    繪製相關函數

    u8g2.drawBox() —— 畫實心方形

    /**
    * 畫實心方形,左上角座標爲 (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)

    註:
    如果支援繪製顏色(也就是不是單色顯示器),那麼由 setDrawColor 設置,請看下例:

    u8g2.drawBox(3,7,25,15);

    u8g2.drawCircle() —— 畫空心圓

    /**
    * 畫空心圓,圓心座標爲 (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)

    註:
    ① 如果支持繪製顏色(也就是不是單色顯示器),那麼由 setDrawColor 設置。
    ② 直徑等於 2 × rad + 1,範例如下:

    u8g2.drawCircle(20, 25, 10, U8G2_DRAW_ALL);

    u8g2.drawDisc() —— 畫實心圓

    /**
    * 畫空心圓,圓心座標爲 (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::drawDisc(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rad, uint8_t opt = U8G2_DRAW_ALL)

    u8g2.drawEllipse() —— 畫空心橢圓

    /**
    * 畫空心圓,圓心座標爲 (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 關聯方法 drawDisc setDrawColor
    */
    void U8G2::drawEllipse()(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t opt = U8G2_DRAW_ALL)

    註:
    ① rx × ry 在 8 位模式的 u8g2 必須小於 512(目前暫沒有理解為什麼)。
    ② 範例如下:

    u8g2.drawEllipse(20, 25, 15, 10, U8G2_DRAW_ALL);

    u8g2.drawFrame() —— 畫空心方形

    /**
    * 畫實心方形,左上角座標爲 (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)

    註:
    如果支援繪製顏色(也就是不是單色顯示器),那麼由 setDrawColor 設置,請看下例:

    u8g2.drawFrame(3,7,25,15);

    u8g2.drawGlyph() —— 繪製字體字集的符號

    /**
    * 繪製字體字集裏面定義的符號
    * @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)

    註:
    ① u8g2 支持 16 位以內的 unicode 字符集,也就是說 encoding 的範圍爲 0-65535,drawGlyph 方法只能
      繪製存在於所使用的字體字集中的 unicode 值。
    ② 這個繪製方法依賴於當前的字體模式和繪製顏色。

    u8g2.drawHLine() —— 繪製水平線

    /**
    * 繪製水平線
    * @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)

    註:
    如果支持繪製顏色(也就是不是單色顯示器),那麼由 setDrawColor 設置。

    u8g2.drawLine() —— 兩點之間繪製線

    /**
    * 繪製線,從座標 (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)

    註:
    如果支持繪製顏色(也就是不是單色顯示器),那麼由 setDrawColor 設置。請見範例:

    u8g2.drawLine(20, 5, 5, 32);

    u8g2.drawPixel() —— 繪製像素點

    /**
    * 繪製像素點,座標 (x,y)
    * @param x 像素點的 x 座標
    * @param y 像素點的 y 座標
    * @Note 關聯方法 setDrawColor
    */
    void U8G2::drawPixel(u8g2_uint_t x, u8g2_uint_t y)

    註:
    ① 如果支持繪製顏色(也就是不是單色顯示器),那麼由 setDrawColor 設置。
    ② 你會發現很多繪製方法的底層都是調用drawPixel,畢竟像素屬於最小顆粒度。
    ③ 我們可以利用這個繪製方法自定義自己的圖形顯示。

    u8g2.drawRBox() —— 繪製圓角實心方形

    /**
    * 繪製圓角實心方形,左上角座標爲 (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)

    註:
    ① 如果支持繪製顏色(也就是不是單色顯示器),那麼由 setDrawColor 設置。
    ② 要求,w >= 2 × (r+1) 並且 h >= 2 × (r+1),這是顯而易見的限制。

    u8g2.drawRFrame() —— 繪製圓角空心方形

    /**
    * 繪製圓角實心方形,左上角座標爲 (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)

    註:
    ① 如果支持繪製顏色(也就是不是單色顯示器),那麼由 setDrawColor 設置。
    ② 要求,w >= 2 × (r+1) 並且 h >= 2 × (r+1),這是顯而易見的限制。請見以下範例:

    u8g2.drawRFrame(20,15,30,22,7);

    u8g2.drawStr() —— 繪製字符串

    /**
    * 繪製字符串
    * @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) 

    註:
    ① 需要先設置字體,調用 setFont 方法。
    ② 這個方法不能繪製 encoding 超過 256 的,超過 256 需要用 drawUTF8 或者 drawGlyph;說白了就是一般
      用來顯示英文字符。
    ③ x,y 屬於字符串左下角的座標。請見範例:

    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawStr(0,15,"Hello World!");

    u8g2.drawTriangle() —— 繪製實心三角形

    /**
    * 繪製實心三角形,定點座標分別爲 (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);

    u8g2.drawUTF8() —— 繪製UTF8編碼的字符

    /**
    * 繪製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)

    註:
    ① 使用該方法,有兩個前提。首先是你的編譯器需要支持 UTF-8 編碼,對於絕大部分 Arduino 板子已經支持。
    ② 其次,顯示的字符串需要存爲 “UTF-8” 編碼,Arduino IDE 上默認支援。
    ③ 該方法需要依賴於 fontMode(setFont)以及 drawing Color,也就是說如果你傳進來的字符串編碼必須
      在 font 定義裏面。請見範例:

    u8g2.setFont(u8g2_font_unifont_t_symbols);
    u8g2.drawUTF8(5, 20, "Snowman: ☃");

    u8g2.drawVLine() —— 繪製豎直線

    /**
    * 繪製豎直線
    * @param x 左上角座標 x
    * @param y 左上角座標 y
    * @param h 高度
    */
    void U8G2::drawVLine(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t h)

    u8g2.drawXBM()/drawXBMP() —— 繪製圖像

    /**
    * 繪製圖像
    * @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)

    註:
    drawXBM 和 drawXBMP 區別在於 XBMP 支持 PROGMEM。

    u8g2.firstPage() / nextPage() —— 繪製命令

    /**
    * 繪製圖像
    */
    void U8G2::firstPage(void)
    uint8_t U8G2::nextPage(void)

    註:
    ① firstPage 方法會把當前頁碼位置變成 0。
    ② 修改內容處於 firstPage 和 nextPage 之間,每次都是重新渲染所有內容。
    ③ 該方法消耗的 ram 空間,比 sendBuffer 消耗的 ram 空間要少。請見範例:

    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;
    }

    u8g2.print() —— 繪製內容

    /**
    * 繪製內容
    * @Note 關聯方法  setFont setCursor enableUTF8Print
    */
    void U8G2::print(...)

    請見範例:

    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.setCursor(0, 15);
    u8g2.print("Hello World!");

    u8g2.sendBuffer() —— 繪製緩衝區的內容

    /**
    * 繪製緩衝區的內容
    * @Note 關聯方法  clearBuffer
    */
    void U8G2::sendBuffer(void)

    註:
    ① sendBuffer 的 RAM 佔用空間大,需要結合構造器的 buffer 選項(請繼續往下看,先有個概念)使用。
    ② 不管是 fistPage、nextPage 還是 sendBuffer,都涉及到一個叫做 current page position 的概念。
    ③ 程式碼解析:

    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);
    }
    顯示配置相關函數

    u8g2.getAscent() —— 獲取基準線以上的高度

    /**
    * 獲取基準線以上的高度
    * @return 返回高度值
    * @Note 關聯方法  setFont getDescent setFontRefHeightAll
    */
    int8_t U8G2::getAscent(void)

    註:
    ① 跟字體有關(setFont)。
    ② 請看範例,下面例子,ascent 是 18:

    u8g2.getDescent() —— 獲取基準線以下的高度

    /**
    * 獲取基準線以上的高度
    * @return 返回高度值
    * @Note 關聯方法  setFont getDescent setFontRefHeightAll
    */
    int8_t U8G2::getDescent(void)

    註:
    ① 跟字體有關(setFont)。
    ② 請看範例,下面例子,descent 是 -5:

    u8g2.getDisplayHeight() —— 獲取顯示器的高度

    /**
    * 獲取顯示器的高度
    * @return 返回高度值
    */
    u8g2_uint_t getDisplayHeight(void)

    u8g2.getDisplayWidth() —— 獲取顯示器的寬度

    /**
    * 獲取顯示器的寬度
    * @return 返回寬度值
    */
    u8g2_uint_t getDisplayWidth(void)

    u8g2.getMaxCharHeight() —— 獲取當前字體裏的最大字符的高度

    /**
    * 獲取當前字體裏的最大字符的高度
    * @return 返回高度值
    * @Note 關聯方法 setFont
    */
    u8g2_uint_t getMaxCharHeight(void)

    註:
    每一個字符在 font 字集中都是一個位圖,位圖有高度和寬度。

    u8g2.getMaxCharWidth() —— 獲取當前字體裏的最大字符的寬度

    /**
    * 獲取當前字體裏的最大字符的寬度
    * @return 返回寬度值
    * @Note 關聯方法 setFont
    */
    u8g2_uint_t getMaxCharWidth(void)

    註:
    每一個字符在 font 字集中都是一個位圖,位圖有高度和寬度。

    u8g2.getStrWidth() —— 獲取字符串的像素寬度

    /**
    * 獲取字符串的像素寬度
    * @param s 繪製字符串
    * @return 返回字符串的像素寬度值
    * @Note 關聯方法 setFont drawStr
    */
    u8g2_uint_t U8G2::getStrWidth(const char *s)

    註:
    像素寬度和當前 font 字體有關。

    u8g2.getUTF8Width() —— 獲取 UTF-8 字符串的像素寬度

    /**
    * 獲取 UTF-8 字符串的像素寬度
    * @param s 繪製字符串
    * @return 返回字符串的像素寬度值
    * @Note 關聯方法 setFont drawStr
    */
    u8g2_uint_t U8G2::getUTF8Width(const char *s)

    註:
    像素寬度和當前 font 字體有關。

    u8g2.setAutoPageClear() —— 設置自動清除緩衝區

    /**
    * 是否自動清除緩衝區
    * @param mode 0 表示關閉
    *             1 表示開啓,默認是開啓
    */
    void U8G2::setAutoPageClear(uint8_t mode)

    註:
    ① 用於 firstPage 和 nextPage(看上面的程式碼解析)。
    ② 建議方法保持默認就好,如果用戶禁止了,那麼需要自己維護緩衝區的狀態或者手動調用 clearBuffer。

    u8g2.setBitmapMode() —— 設置位圖模式

    /**
    * 設置位圖模式(定義 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);

    u8g2.setBusClock() —— 設置 I2C、SPI 頻率 (clock speed in HZ)

    /**
    * 設置總線時鐘 (I2C、SPI)
    * @param mode clock_speed 總線時鐘頻率(Hz)
    * @Note 關聯方法 begin
    */
    void U8G2::setBusClock(uint32_t clock_speed);

    註:
    ① 僅僅 Arduino 平臺支援。
    ② 必須在 u8g2.begin() 或者 u8g2.initDisplay() 之前呼叫。

    u8g2.setClipWindow() —— 設置顯示窗口大小

    /**
    * 設置顯示窗口,窗口範圍從左上角 (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 );

    註:
    可以通過 setMaxClipWindow 去掉該限制。

    void U8G2::setMaxClipWindow(void)

    請看範例:

    u8g2.setClipWindow(10, 10, 85, 30);
    u8g2.setDrawColor(1);
    u8g2.drawStr(3, 32, "U8g2");

    u8g2.setCursor() —— 設置繪製游標位置

    /**
    * 設置繪製游標位置 (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!");

    u8g2.setDisplayRotation() —— 設置顯示器的旋轉角度

    /**
    * 設置顯示器的旋轉角度
    * @param u8g2_cb 旋轉選項
    *        U8G2_R0 不做旋轉 水平
    *        U8G2_R1 旋轉 90 度
    *        U8G2_R2 旋轉 180 度
    *        U8G2_R3 旋轉 270 度
    *        U8G2_MIRROR 不做旋轉 水平,顯示內容是鏡像的,暫時不理解
    */
    void setDisplayRotation(const u8g2_cb_t *u8g2_cb)

    u8g2.setDrawColor() —— 設置繪製顏色

    /**
    * 設置繪製顏色(暫時還沒有具體去了解用法)
    */
    void U8G2::setDrawColor(uint8_t color)

    u8g2.setFont() —— 設置使用字體

    /**
    * 設置字體集(字體集用於字符串繪製方法或者 glyph 繪製方法)
    * @param font 具體的字體集
    * @Note 關聯方法  drawUTF8 drawStr drawGlyph print
    */
    void U8G2::setFont(const uint8_t *font)

    Font 會根據像素點高度做了很多區分,具體 font 請參考:連結

    如果我們需要用到中文字符,可以在上面的連結裏面搜索一下 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
    ......

    註:
    中文字符集消耗記憶體大,請謹慎使用,可以用在 Arduino 101 等 RAM 空間比較大的板子上。

    我們看看 Font 的命名規則:

    <prefix> '_font_' <name> '_' <purpose> <char set>

    例如:

    u8g2.setFont( u8g2_font_5x7_tr );
    u8ge.setFont( u8g2_font_pressstart2p_8u );

    其中:

    • prefix 基本上都是 u8g2
    • name 一般會掛鉤上字符像素使用量,比如 5X7
    • purpose
      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.
    • char set
      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
         hars) 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.

    註:
    u8g2 庫提供的 font 非常多,各位也暫時消化不了太多。如果我們使用中文的話,就去看看中文 font 就好。

    u8g2.setFontDirection() —— 設置字體方向

    /**
    * 定義字符串繪製或者圖形繪製的方向
    * @param dir 方向
    * @param 關聯方法 drawStr
    */
    void U8G2::setFontDirection(uint8_t dir)

    dir 的參數說明

    ArgumentString RotationDescription
    00 degree Left to right
    190 degreeTop to down
    2180 degreeRight to left
    3270 degreeDown to top

    請看範例:

    u8g2.setFont(u8g2_font_ncenB14_tfå);
    u8g2.setFontDirection(0);
    u8g2.drawStr(15, 20, "Abc");
    u8g2.setFontDirection(1);
    u8g2.drawStr(15, 20, "Abc");
    緩存相關函數

    緩存相關函數,一般不會去操作,瞭解即可。

    u8g2.getBufferPtr() —— 獲取緩存空間的地址

    /**
    * 獲取緩存空間的地址
    * @return 返回緩存空間起始地址
    * @Note 關聯方法 getBufferTileHeight, getBufferTileWidth, clearBuffer
    */
    uint8_t *U8G2::getBufferPtr(void)

    註:
    緩存大小等於 8 × u8g2.getBufferTileHeight() × u8g2.getBufferTileWidth()。

    u8g2.getBufferTileHeight() —— 獲取緩衝區的 Tile 高度

    /**
    * 獲取緩衝區的 Tile 高度
    * @return 返回高度值
    */
    uint8_t U8G2::getBufferTileHeight(void)

    註:
    一個 tile 等於 8 個像素點。

    u8g2.getBufferTileWidth() —— 獲取緩衝區的 Tile 寬度

    /**
    * 獲取緩衝區的 Tile 寬度
    * @return 返回寬度值
    */
    uint8_t U8G2::getBufferTileWidth(void)

    註:
    一個 tile 等於 8 個像素點。

    u8g2.getBufferCurrTileRow() —— 獲取緩衝區的當前 Tile row

    /**
    * 獲取緩衝區的當前 Tile row 行數
    * @return 返回當前的 tilerow
    */
    uint8_t U8G2::getBufferCurrTileRow(void)

    註:
    這個方法跟我們上面說到的 page position 相關。

    u8g2.setBufferCurrTileRow() —— 設置緩衝區的當前 Tile row

    /**
    * 設置緩衝區的當前 Tile row
    * @param 當前的 Tile row
    */
    uint8_t U8G2::setBufferCurrTileRow(uint8_t row)

    註:
    在 firstPage/nextPage 循環時,由於底層調用了 setBufferCurrTileRow,所以儘量不要自己手動調用該方法。
    請看範例:

    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 函式庫

    前面介紹到 u8g2 適配了絕大部分的 OLED,那麼我們如何構建具體的 OLED 驅動呢?可分爲以下幾個順序步驟:

    1. 區分顯示器:

      首先,你需要知道 OLED 顯示器的控制器型號以及屏幕大小。舉個例子,我手上有一塊 SSD1306 128×64 的 OLED,那麼它的控制器就是 SSD1306,螢幕大小是 128×64。

      其次,你所選擇的 OLED 必須在 u8g2 庫所支持的 OLED 列表中,具體可參考:這個網址

    2. 確認物理連線介面:

      圖像信息是通過物理連接線傳送給 OLED 顯示器。通常,我們的連謝種類包括:

      • 3SPI,3-wire SPI:串行外圍接口,依靠三個控制信號,Clock、Data、CS
      • 4SPI, 4-Wire SPI:跟 3SPI 一樣,只是多了一條數據命令線,經常叫做 D/C
      • I2C, IIC or TWI:SCL、SDA
      • 8080:A 8-Bit bus which requires 8 data lines
      • 6800:Another 8-Bit bus, but with a different protocol

      具體的 OLED 使用怎樣的連線,我們需要查閱設備手冊。比如,SSD1306 就是 I2C。

    3. 確認連線引腳:

      知道了物理連線模式之後,我們一般都是把 OLED 連接到 Arduino Board 的輸出引腳,也就是軟件模擬通訊協議。當然,如果有現成的物理連線介面那就更好了。
      如:Arduino 的 A4 即為 I2C 的 SDA、A5 即為 I2C 的 SCL

    4. u8g2 初始化:

      經歷以上三步之後,我們就可以開始初始化出具體的 OLED 驅動了。比如,IIC SSD1306 128X64 的 OLED,就可以用以下初始化建構子(Constrator):

      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 還有其他的建構子,如:

      OLED : SSD1306 / 128×64
      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])
      page buffer size : 1024 bytes
      U8G2_SSD1306_128X64_NONAME_1_4W_HW_SPI(rotation, cs, dc [, reset])
      page buffer size : 128 bytes

      看到這裡,我們需要重點講述一下建構子(Constrator)的規則。建構子的名字由以下幾方面組合而成,它們之間使用 "_" 連接起來。

      NoDescriptionExample
      1PrefixU8G2
      2Display ControllerSSD1306
      3Display Name128X64_NONAME
      4Buffer Size
      1:保持一頁的緩衝區,用於 firstPage/nextPage 的 PageMode
      2:保持兩頁的緩衝區,用於 firstPage/nextPage 的 PageMode
      F:獲取整個屏幕的緩衝區,RAM 消耗大,一般用在 RAM 空間
          比較大的 arduino 板子
      5Communication
      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,其意義是指定整個螢幕是否要在旋轉的狀態下顯示內容,其詳細定義是:

      Rotation / MorrorDescriptiomn
      U8G2_R0No rotation, landscape
      U8G2_R190 degree clockwise rotation
      U8G2_R2180 degree clockwise rotation
      U8G2_R3 270 degree clockwise rotation
      U8G2_MIRRORNo 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.drawStr0,24,"Hello World!");
          } while ( u8g2.nextPage() );
      }
    5. u8g2 繪製模式:

      u8g2 支援三種繪製模式:

      1. Full screen buffer mode(全屏緩存模式)

        特點:繪製速度快、所有的繪製方法都可以使用、需要大量的 RAM 空間。

        建構子:必須帶有 F,比如:

        U8G2_ST7920_128X64_F_SW_SPI(rotation, clock, data, cs [, reset])

        用法:

        1. 清除緩衝區 u8g2.clearBuffer()
        2. 呼叫繪製方法
        3. 發送緩衝區的內容到顯示器 u8g2.sendBuffer()

        範例程式:

        void setup(void) {
            u8g2.begin();
        }
                              
        void loop(void) {
            u8g2.clearBuffer();
            u8g2.setFont(u8g2_font_ncenB14_tr);
            u8g2.drawStr(0,20,"Hello World!");
            u8g2.sendBuffer();
        }

      2. Page mode(分頁模式:This is the U8glib picture loop)

        特點:繪製速度慢、所有的繪製方法都可以使用、需要少量的 RAM 空間。

        建構子:必須帶有 1 或 2,比如:

        U8G2_ST7920_128X64_1_SW_SPI(rotation, clock, data, cs [, reset])

        用法:

        1. 呼叫 u8g2.firstPage()
        2. 開始一個 do while 循環
        3. 在循環內部呼叫繪製方法
        4. 不斷判斷 u8g2.nextPage()

        範例程式:

        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() );
        }

      3. U8x8 character only mode(僅僅支援普通字符)

        特點:繪製速度快、並不是對所有的顯示器都有效、圖形繪製不可用、不需要 RAM 空間。

        建構子:使用 U8X8 建構子,比如:

        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!");
        }