やりたいこと
- XIAO RP2040でST7789 LCDに日本語文字列を表示させる
- 開発環境はPlatformIOのArduinoフレームワーク (C++)
- Adafruit GFXライブラリとefontを使用する
→ LovyanGFX を使用する場合は こちら
使用するLCDモジュール
- Waveshare 1.69inch LCD Display Module
- スイッチサイエンスで購入
- 240×280ピクセル / 1.69インチ 角丸ディスプレイ
- ドライバIC: ST7789V2 / SPI接続
- コネクタ: MX1.25 8ピン (ケーブル1本付属)
- ケーブルを自作する場合は とかを使用
使用するライブラリ
- Adafruit GFX Library
- Adafruit ST7735 and ST7789 Library
- efont Unicode Font Data
platformio.ini は下記の通り。
(Adafruit ST7735 and ST7789 Library は Adafruit GFX Library に依存)
[env:seeed_xiao_rp2040] platform = https://github.com/Seeed-Studio/platform-seeedboards.git board = seeed-xiao-rp2040 framework = arduino lib_deps = adafruit/Adafruit ST7735 and ST7789 Library@^1.11.0 tanakamasayuki/efont Unicode Font Data@^1.0.9
テストプログラム
#include <Adafruit_GFX.h> #include <Adafruit_ST7789.h> #include <SPI.h> #include <efontEnableJa.h> //#include <efontEnableJaMini.h> #include <efont.h> //#define TFT_MOSI D10 //#define TFT_SCLK D8 #define TFT_CS D7 #define TFT_DC D6 #define TFT_RST D5 #define TFT_BL D4 Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); #define DEV_Set_BL(_Pin, _Value) analogWrite(_Pin, _Value) #define SCREEN_WIDTH 280 // 画面幅 String text1, text2; // 表示する文字列 // バックライト輝度制御 // value : 0 ~ 100 void setBacklight(int value) { if(value > 100) value=100; analogWrite(TFT_BL, (int)((float)value * 2.55f)); } // 日本語文字列を表示する // posX, posY : 開始座標 // txtsize : 文字サイズ (1: 1倍=16ドット, 2: 2倍=32ドット, ...) // color : 色 // str : 文字列 void printEfont(int16_t posX, int16_t posY, int16_t size, uint16_t color, const char *str) { uint8_t font[32]; const char *p = str; // 文字列の終端まで while (*p != 0x00) { // 改行処理 if (*p == '\n') { posX = 0; posY += 24 * size; // 改行は24ドット × 文字サイズ p++; continue; } // strUTF16に1文字取得して、pを1文字進める uint16_t strUTF16; p = efontUFT8toUTF16(&strUTF16, const_cast<char*>(p)); // strUTF16のフォントデータをfontに取得 getefontData(font, strUTF16); // 文字横幅 (全角文字は16ドット, 半角文字は8ドット) × 文字サイズ int width = 16 * size; if( strUTF16 < 0x0100 ){ width = 8 * size; // 半角 } // 折返し処理 if (posX >= SCREEN_WIDTH | (posX+width) > SCREEN_WIDTH) { posX = 0; posY += 24 * size; // 改行は24ドット × 文字サイズ } // フォントを点描 for (uint8_t row = 0; row < 16; row++) { word fontdata = font[row * 2] * 256 + font[row * 2 + 1]; for (uint8_t col = 0; col < 16; col++) { if ((0x8000 >> col) & fontdata) { int drawX = posX + col * size;; int drawY = posY + row * size;; if( size == 1 ){ tft.drawPixel(drawX, drawY, color); } else { tft.fillRect(drawX, drawY, size, size, color); } } } } // 描画位置を1文字ぶん進める posX += width; } } void setup(void) { Serial.begin(115200); Serial.println(F("Hello! ST7789 LCD Test")); setBacklight(100); // バックライト100%(全点灯) tft.init(240, 280); // 240x280ドット tft.setRotation(1); // 画面回転(横向き) // 表示データ text1 = "吾輩は猫である。名前はまだ無い。\nどこで生れたかとんと見当がつかぬ。"; text1 += "何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。"; text2 = text1; text2 += "吾輩はここで始めて人間というものを見た。"; text2 += "しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。"; text2 += "この書生というのは時々我々を捕えて煮て食うという話である。"; text2 += "しかしその当時は何という考もなかったから別段恐しいとも思わなかった。"; text2 += "ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。"; text2 += "掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。"; } void loop() { // USBシリアルでスペース ' ' を送ると文字サイズが変わる static bool update = true; static bool baikaku = false; while(Serial.available() > 0){ char c = Serial.read(); if(c == ' '){ update = true; baikaku = !baikaku; } } if(update){ update = false; if(baikaku == false){ // 1倍サイズ, 緑色 tft.fillScreen(ST77XX_BLACK); const char* str = text2.c_str(); printEfont(0, 0, 1, ST77XX_GREEN, str); }else{ // 2倍サイズ, 水色 tft.fillScreen(ST77XX_BLACK); const char* str = text1.c_str(); printEfont(0, 0, 2, ST77XX_CYAN, str); } } }

