0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rapberry PI Pico用 ILI9341 TFT液晶 SDKライブラリ

Posted at

概要

このライブラリは、Raspberry PI PICO 上で、ILI9341 TFT液晶をコントロールするためのライブラリです。日本語表示等に対応しています。

手っ取り早くソースを見たい、という人は githubページへどうぞ。


このライブラリについて

Adafruitは、Arduinoで簡単に使用できるが、標準SDK用のものがありません。日本語にも対応していないため作成されました。
今回は、なるべくコンパクトになるように作ったRapberry PI Pico用 ST7735 TFT液晶 SDKライブラリとは異なり、Adafruitのソースコードや関数になるべく準拠するように作成しました。おそらく、Adafruit_GFXを使用していたプログラムのほとんどがソースコードを変えることなく動作すると思います。

クラス名や関数名がAdafruit_GFXと同じになっていることから、Adafruitとの競合を避けるため、このプログラムは名前空間を変えてあります。

主な変更点

  • 漢字の表示
  • 文字表示の高速化(漢字のみ)
  • TFTへの表示に際しprintfなどの追加
  • 透過色のサポート

動作例

次の動画は、このライブラリのサンプルプログラム(本体に同梱)です。

  • 図形表示のデモ。直線や円などを表示し、最後に実行時間を表示します。Adafruit_GFXから変更がほとんどありません
  • ビットマップ表示のデモ。いろいろな表示方法や、それぞれの時間を表示させています。オリジナルに存在しない、透過色指定などの機能を追加しました
  • アルファベット表示のデモ。様々なフォントで文字を表示します。Adafruit_GFXから変更がほとんどありません。
  • 日本語表示のデモ。日本語のテキストを表示します。このプログラムではフォントの指定方法がST7735と異なり、Adafruit_GFXに近くしてあります。理論上は異なるフォントを複数持てるはずですがメモリの制限から現実的とは言えません。
  • キャンバスを使用してフリッカーレスで文字を表示させます。

ソースコード

ソースコードは

githubのST7735-TFTDriverページ

で公開しています。

フォルダ構成と用途

プロジェクトのフォルダ構成と主な用途は次のようになっています。

/ 動作を確認するためのプログラムや、VSCodeのプロジェクト関連ファイル
 |
 +ー lib-9341 ライブラリ本体のソースコード
      |
      +ー Adafruit_GFX_Library Adafruitの提供するライブラリ
      |  +Fonts      英字フォントファイル
      |
      +ー Adafruit_ILI9341   Adafruit提供のILI9341特有のファイル
      |
      +ー Kanji         漢字処理のライブラリ
      |  +Fonts        漢字ファイル
      |
      +ー core          最低限必要なArduinoIDEファイル
      +ー spi           Raspberry PI PICOのSPI処理を行うファイル
      +ー XPT2046_TouchScreen  XPT2046タッチパネル用ファイル

ライブラリの本体は、lib-9341以下に含まれています。このライブラリを使用するプログラムは、lib-9341フォルダ以下を自分のプロジェクトに複製し、使用してください。

フォント情報ファイル

fontサブフォルダは、テキスト表示の際に使用されるフォントのビットマップ情報です。

英文フォント用ファイル

拡張子 .hは、adafruitのgfxライブラリで使用されているものがそのまま使用できます。必要な(使用する)ファイルだけをincludeして使用します。

日本語フォント用ファイル

拡張子 .incは、日本語フォント用のファイルです。複数のファイルがあります。必要なフォントをインクルードして使用します。理論上、複数のファイルをインクルードし、使い分けることが可能なはずですが、漢字フォントのデータサイズは英文字と比較にならないサイズなので、現実的に使用できるかは疑問です。使用する文字だけのサブセットを作成・使用することで可能かもしれません。

ファイル名は、 <もとになったTTFフォント名>_<横ドット数>_<文字セット>.inc の形になっています。現時点で、次のファイルが使用できます。

フォント名

TTFフォント名 フォント名 文字の大きさ ヘッダファイルの名前
JF-Dot-Shinonome12 東雲12ドットフォント 12x12 JF-Dot-Shinonome12_12x12_<文字セット>.inc
JF-Dot-Shinonome14 東雲14ドットフォント 14x14 JF-Dot-Shinonome12_14x14_<文字セット>.inc
JF-Dot-Shinonome16 東雲16ドットフォント 16x16 JF-Dot-Shinonome12_16x16_<文字セット>.inc

文字セット

文字セット 設定値 含まれる文字 文字数 サイズ(12x12)
All 0 JISすべて 約6,800文字 約165Kbytes
Level1 1 第二水準を除いた文字 約3,500文字 約83Kbytes
SCHOOL 2 小学校6年生までで習う漢字 約800文字 約19Kbytes

このヘッダファイルは、 PythonFontConverter でTTFファイルから変換しました。PythonFontConverterも、パブリックドメインとして公開しています。

使用方法

実装にあわせた変更

とくにビルド前に変更や調整が必要な項目はありません。実行時に環境にあわせて指定してください。

ハードウェアにあわせて変更するもの

とくにビルド前に変更や調整が必要な項目はありません。実行時に環境にあわせて指定してください。

使用するまでの準備

ハードウェア

結線例

今回、みんな大好き秋月電子のILI9341搭載2.8インチSPI制御タッチパネル付TFT液晶MSP2807を使って開発しました。この接続でTFT液晶の制御とタッチパネルが使用できるようになります。

そのほか、いろいろな製品がありますが、多くのデバイスは同じピン配列を持っているようです。

ST7732と同様に、このコントローラも、コントローラーからマイコン側に信号を送る、MISOは持っていません。3番ピンのCS信号で、デバイスを使用するかどうかの選択と、5番ピンのD/Cでデータとコマンドの区別を行います。

Raspberry PI TFT液晶
3.3V(36pin) VCC(1Pin)・LED(8Pin)
GND(38Pin) GND(2Pin)
GP22(29Pin) CS(3Pin)
GP21(27Pin) RESET(4Pin)
GP20(26Pin) D/C(5Pin)
GP19(25Pin)-MOSI/SDO/TX SDI(MOSI)・T_DIN (6Pin&12Pin)
GP18(24Pin)-SCK SCK・T-CLK (7Pin&10Pin)
GP17(22Pin)-CSn T-CS(11Pin)
GP16(21Pin)-MISO/SDO/RX T-DO(13Pin)

タッチパネルの接続もあるため、結線は少し複雑ですが、次のように接続してください。

RaspTFT.png

タッチパネルが無いデバイスや、使用しない場合には TOUCH にある部分は接続しなくても構いません。

今回のライブラリのサンプルプログラムは、次のデモに進む際にタッチパネルの操作を行いますが、タッチパネルが無い場合でも、一定の時間が来ると自動的に先に進みます。

ソフトウェア

必要なソフトウェアは、Raspberry PI pico の標準SDKだけです。

RaspBerry pi の公式ページ、Get started with Raspberry Pi Pico-series and VS Codeなどを参照し、VSCodeにSDKを導入します。日本語でもこれ や、これなどで情報を見つけることができます。

プロジェクトを新規作成し、 githubページから、lib-9341フォルダをダウンロードして、自分のプロジェクトに組み込んで使用してください。

プロジェクトには、spi、dmaが必要になります。ビルド時にエラーになった場合、適宜CMakeList.txtの target_link_librariesに追加してください。

ライブラリを使用する

Hello, Worldに相当するプログラムの作成手順はつぎのとおりです。

プロジェクトの作成とライブラリのコピー

Raspberry PI SDKから、C++のプロジェクトを作成します。

この時、次の点に注意してください。

  • APIバージョンは2.0.0以上が必要です。
  • SPI、DMAのサポートが必要です。
1.png

その他の設定は、使用しているボードや環境にあわせて適宜設定を行ってください。

次に、 githubページから、右上にあるReleaseのリンクをクリック、最新のソースコードをダウンロードします。

1.png

ダウンロードしたzipファイル(もしくはtar.gzip)ファイルを展開し、lib-9341フォルダを、作成したプロジェクトのフォルダにコピーします。

下の例は Test9341\Simpleというフォルダにプロジェクトを作成した 場合のフォルダ構成です。コピーしたlib-9341フォルダの下に、フォルダ構成と用途の章に記した複数のフォルダが確認できます。

3.png

CMakeFiles.txtの作成

CMakeList.txtを変更して、作成されたプロジェクトがライブラリをビルド対象に含めるように設定します。設定は、大きく分けて次のようになります。1~3までは、標準SDKで開発をしている人にはほとんど不要な説明かと思いますが、Arduino IDEを主に使っている人にはある意味一番難しい部分かもしれないため、解説してあります。

  1. add_executablesに、コンパイル対象の.cpp ファイルを加える
  2. target_link_librariesに、lib-9341が内部で使用するライブラリを追加する
  3. target_include_directoriesに、lib-9341が使用するフォルダを追加する
  4. ライブラリ内部で使用しているボード種類が判別できるよう、マクロ値を設定する
  5. ビルドできるかをテストしておく

1.add_executablesに、コンパイル対象の.cpp ファイルを加える

自動作成されるCMakeFiles.txtは次のようになっています。

  add_executable(simple simple.cpp )

この部分に、ライブラリで使用する .cppを追加します。

add_executable(simple simple.cpp 
# 使用するプログラムを追加する
    lib-9341/defines.cpp
        :
       (略)
        :
    lib-9341/XPT2046_Touchscreen/XPT2046_Touchscreen.cpp
    lib-9341/pins.cpp
)
全ボード共通の設定例 中身の文章
add_executable(simple simple.cpp 
# 使用するプログラムを追加する
    lib-9341/defines.cpp
    lib-9341/Adafruit_GFX_Library/Adafruit_GFX.cpp
    lib-9341/Adafruit_GFX_Library/Adafruit_SPITFT.cpp
    lib-9341/Adafruit_ILI9341/Adafruit_ILI9341.cpp
    lib-9341/spi/spi.cpp
    lib-9341/Kanji/KanjiHelper.cpp
    lib-9341/core/PIOProgram.cpp
    lib-9341/core/cyw43_wrappers.cpp
    lib-9341/core/delay.cpp
    lib-9341/core/_freertos.cpp
    lib-9341/core/CoreMutex.cpp
    lib-9341/core/Print.cpp
    lib-9341/core/RP2040Support.cpp
    lib-9341/core/stdlib_noniso.cpp
    lib-9341/core/WString.cpp
    lib-9341/core/wiring_private.cpp
    lib-9341/core/wiring_digital.cpp
    lib-9341/core/wiring_analog.cpp
    lib-9341/XPT2046_Touchscreen/XPT2046_Touchscreen.cpp
    lib-9341/pins.cpp
)

2.target_link_librariesに、lib-9341が内部で使用するライブラリを追加する

target_link_librariesはリンクするライブラリの指定ですが、今回の場合、SDKが提供する必須のライブラリを指定することになります。

プロジェクトを新規で作成すると、target_link_librariesは2つ作成されます。

前半は、標準で必ず使用するライブラリやユーザーが後から追加したライブラリ、後半は、プロジェクトウィザードで指定したライブラリのようです。

# Add the standard library to the build
target_link_libraries(simple
        pico_stdlib)
      :
     (略)
      :
# Add any user requested libraries
target_link_libraries(simple 
        hardware_spi
        hardware_dma
        )        

どちらに追加しても構いませんが、一応、前述のルールに従うようにライブラリを追加していきます。
PICO/PICO2で、必要としているライブラリに一部違いがありますが、PICOW用を使用しておけば、どちらでも問題ありません。(若干、使用するフラッシュメモリの量が増えます)

# Add the standard library to the build
target_link_libraries(simple
        pico_stdlib
#使用するライブラリを追加する        
        pico_rand
        pico_unique_id
        hardware_exception)
      :
     (略)
      :
# Add any user requested libraries
target_link_libraries(simple 
        hardware_spi
        hardware_dma
#PICOWの場合にのみ必要        
        pico_cyw43_arch_none
        )
PICO/PICO2の設定例
# Add the standard library to the build
target_link_libraries(simple
        pico_stdlib
#使用するライブラリを追加する        
        pico_rand
        pico_unique_id
        hardware_exception)
      :
     (略)
      :
# Add any user requested libraries
target_link_libraries(simple 
        hardware_spi
        hardware_dma
        )
PICOW/PICO2Wの設定例
# Add the standard library to the build
target_link_libraries(simple
        pico_stdlib
#使用するライブラリを追加する        
        pico_rand
        pico_unique_id
        hardware_exception)
      :
     (略)
      :
# Add any user requested libraries
target_link_libraries(simple 
        hardware_spi
        hardware_dma
#PICOWの場合にのみ必要        
        pico_cyw43_arch_none
        )

3. target_include_directoriesに、lib-9341が使用するフォルダを追加する

ライブラリ自身が使用するファイルのincludeフォルダを追加します。
ライブラリのディレクトリと、SDKのディレクトリが必要です。

デフォルトの状態では、ソースコードのあるディレクトリだけが含まれています。

target_include_directories(simple PRIVATE
        ${CMAKE_CURRENT_LIST_DIR}
)

ここに、ライブラリのフォルダと、ハードウェア例外のインクルードフォルダ、ネットワーク関連のフォルダを追加します。

PICO/PICO2の場合はネットワーク関連のincludeフォルダは必要ありませんが、指定してあったとしても(=PICO_W用であっても)特に弊害はありません。

target_include_directories(simple PRIVATE
#インクルードディレクトリも追加する       
        ${CMAKE_CURRENT_LIST_DIR}
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Adafruit_GFX_Library
       :
         (略)
       :
        ${CMAKE_CURRENT_LIST_DIR}/XPT2046_Touchscreen   
#PICOW以外の場合、これ以降は不要         
        ${PICO_SDK_PATH}/src/rp2_common/hardware_exception/include
       :
         (略)
       :
        ${PICO_SDK_PATH}/src/rp2_common/pico_lwip/include
        ${PICO_SDK_PATH}/lib/cyw43-driver/src/

)
PICO/PICO2の設定例
target_include_directories(simple PRIVATE
#インクルードディレクトリも追加する       
        ${CMAKE_CURRENT_LIST_DIR}
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Adafruit_GFX_Library
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Adafruit_GFX_Library/Fonts
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Adafruit_BusIO
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Adafruit_ILI9341
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/core
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/spi
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/variants
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Kanji
        ${CMAKE_CURRENT_LIST_DIR}/XPT2046_Touchscreen   
)
PICOW/PICO2Wの設定例
target_include_directories(simple PRIVATE
#インクルードディレクトリも追加する       
        ${CMAKE_CURRENT_LIST_DIR}
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Adafruit_GFX_Library
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Adafruit_GFX_Library/Fonts
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Adafruit_BusIO
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Adafruit_ILI9341
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/core
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/spi
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/variants
        ${CMAKE_CURRENT_LIST_DIR}/lib-9341/Kanji
        ${CMAKE_CURRENT_LIST_DIR}/XPT2046_Touchscreen   
#PICOW以外の場合、これ以降は不要         
        ${PICO_SDK_PATH}/src/rp2_common/hardware_exception/include
        ${PICO_SDK_PATH}/src/rp2_common/pico_lwip/include
        ${PICO_SDK_PATH}/src/rp2_common/pico_cyw43_driver/include
        ${PICO_SDK_PATH}/src/rp2_common/pico_cyw43_driver/include/pico
        ${PICO_SDK_PATH}/src/rp2_common/pico_cyw43_arch/include
        ${PICO_SDK_PATH}/src/rp2_common/pico_cyw43_arch/include/pico
        ${PICO_SDK_PATH}/src/rp2_common/pico_async_context/include
        ${PICO_SDK_PATH}/src/rp2_common/pico_async_context/include/pico
        ${PICO_SDK_PATH}/src/rp2_common/hardware_adc/include/
        ${PICO_SDK_PATH}/src/rp2_common/hardware_pwm/include/
        ${PICO_SDK_PATH}/lib/lwip/src/include
        ${PICO_SDK_PATH}/lib/lwip/src/include/iwip
        ${PICO_SDK_PATH}/lib/cyw43-driver/src/

)

4. ライブラリ内部で使用しているボード種類が判別できるよう、マクロ値を設定する

条件コンパイルのため、使用しているボードによってコンパイラに渡すシンボル値を決定する処理を追加します。

なぜこの処理が必要かに関する小難しい解説はこちら

Adafruit_GFX(おそらくそれに限らず)ではGPIOの出力で「特定のファイルがコンパイル対象に含まれるか、含まれないか」によって処理を分けるために弱参照を使っています。具体的には、pins.cppに含まれる関数は、同名の関数が wiring_digital.cppにも含まれており、これが弱参照で extern されています。
pins.cppがプログラムにリンクされると、こちらの参照の方が強くなるため、wiring_digital.cpp内の関数ではなく、pins.cppの関数の方が呼び出されることになります。一種の「関数オーバーロード」のようなことを実現しているわけです。

これはArduino IDEでは便利なのかもしれませんが、標準SDKでは少々なじみが悪いように感じたため、シンボルを使った条件(普通の#ifdef)に変更してあります。

これにより、ボードを変更(例:pico⇒pico_wなど)するときに、一々 add_executable のエントリを変更する必要がなく、一般的な方法である set(PICO_BOARD pico_w CACHE STRING "Board type") の変更だけで済むようになります。

ここで設定されたシンボルは、ライブラリ内で次のように使用され、PICOとPICOWとで行われる処理を分けるようにしています。

extern "C" void pinMode(pin_size_t pin, PinMode mode) {
	#if PICO_BOARD_VALUE == 1 || PICO_BOARD_VALUE == 2  // PICO/PICO2
	__pinMode(pin, mode);
	#else
	cyw43_pinMode(pin, mode);
	#endif
}

詳細については、pins.cpp内のコメントを参照してください。


デフォルトの状態では、次のようになっています。

set(PICO_BOARD pico_w CACHE STRING "Board type")

ここで設定された変数に従い、コンパイル時にシンボルを設定させます。

set(PICO_BOARD pico_w CACHE STRING "Board type")

# プログラム内で処理を分けられるように、マクロ値としてコンパイラに渡す
if(PICO_BOARD STREQUAL "pico")
    set(PICO_BOARD_VALUE 1)
elseif(PICO_BOARD STREQUAL "pico_w")
    set(PICO_BOARD_VALUE 3)
elseif(PICO_BOARD STREQUAL "pico2")
    set(PICO_BOARD_VALUE 2)
elseif(PICO_BOARD STREQUAL "pico2_w")
    set(PICO_BOARD_VALUE 4)
else()
    set(PICO_BOARD_VALUE 0) # 未知のボード
endif()
add_compile_definitions(PICO_BOARD_VALUE=${PICO_BOARD_VALUE})

5. ビルドできるかをテストしておく

これでプロジェクトの準備は完了ですが、間違いがないか、一度テストしておきます。エディタ画面にフォーカスを合わせて、CTRL+Pを押します。左下の歯車をクリック > [コマンドパレット]でも構いません。コマンドの一覧が表示されたら、 CMake ビルドをクリックします。

1.png

キットの問い合わせがあった場合、[未指定]を選択し、CMakeに任せます。もしくは正しいビルドのためのキットを指定してください。

1.png

Visual Studio Codeの出力タブに、ビルドの状況が表示されます。終了コード0で終了し、エラーが出ていなければビルドは成功しています。

[main] フォルダーのビルド中: e:/work/Test9341/simple/build 
[main] プロジェクトを構成しています: simple 
[proc] コマンドを実行しています: C:\Users\hisay/.pico-sdk/cmake/v3.31.5/bin/cmake -
     :
[build] [64/64 100% :: 2.463] Linking CXX executable simple.elf
[driver] ビルド完了: 00:00:03.012
[build] ビルドが終了コード 0 で終了しました

ソースコードのコーディング

もっとも簡単なプログラムとして、画面に日本語テキストを表示してみます。

自動生成されたコードの確認と削除

自動生成されたメインプログラムには、SPIのポート指定(GP16~GP19)とCS(デバイスセレクト)の処理や、DMA関連の処理がサンプルとして自動的に作られています。これらは邪魔になるため削除していきます。

自動生成されたコードを見る 自動生成されたコードの参考例です。環境やプロジェクト作成時のオプションにより内容は異なります。
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/dma.h"

// SPI Defines
// We are going to use SPI 0, and allocate it to the following GPIO pins
// Pins can be changed, see the GPIO function select table in the datasheet for information on GPIO assignments
#define SPI_PORT spi0
#define PIN_MISO 16
#define PIN_CS   17
#define PIN_SCK  18
#define PIN_MOSI 19

// Data will be copied from src to dst
const char src[] = "Hello, world! (from DMA)";
char dst[count_of(src)];



int main()
{
    stdio_init_all();

    // SPI initialisation. This example will use SPI at 1MHz.
    spi_init(SPI_PORT, 1000*1000);
    gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
    gpio_set_function(PIN_CS,   GPIO_FUNC_SIO);
    gpio_set_function(PIN_SCK,  GPIO_FUNC_SPI);
    gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
    
    // Chip select is active-low, so we'll initialise it to a driven-high state
    gpio_set_dir(PIN_CS, GPIO_OUT);
    gpio_put(PIN_CS, 1);
    // For more examples of SPI use see https://github.com/raspberrypi/pico-examples/tree/master/spi

    // Get a free channel, panic() if there are none
    int chan = dma_claim_unused_channel(true);
    
    // 8 bit transfers. Both read and write address increment after each
    // transfer (each pointing to a location in src or dst respectively).
    // No DREQ is selected, so the DMA transfers as fast as it can.
    
    dma_channel_config c = dma_channel_get_default_config(chan);
    channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
    channel_config_set_read_increment(&c, true);
    channel_config_set_write_increment(&c, true);
    
    dma_channel_configure(
        chan,          // Channel to be configured
        &c,            // The configuration we just created
        dst,           // The initial write address
        src,           // The initial read address
        count_of(src), // Number of transfers; in this case each is 1 byte.
        true           // Start immediately.
    );
    
    // We could choose to go and do something else whilst the DMA is doing its
    // thing. In this case the processor has nothing else to do, so we just
    // wait for the DMA to finish.
    dma_channel_wait_for_finish_blocking(chan);
    
    // The DMA has now copied our text from the transmit buffer (src) to the
    // receive buffer (dst), so we can print it out from there.
    puts(dst);

    while (true) {
        printf("Hello, world!\n");
        sleep_ms(1000);
    }
}

削除したものが次のプログラムです。

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/dma.h"


int main()
{
    stdio_init_all();


    while (true) {
    }
}

画面表示プログラムの記述

ここではいくつかの改変をプログラムに加えていきます。

  1. 本ライブラリが使用する機能を定義してある、インクルードファイルを追加します。
     

  2. 本ライブラリの名前空間を使用するための宣言を行います。
    本ライブラリは、多くの関数やクラスで、Adafruit_GFXと同じ名前の関数で異なる実装を行っています。ユーザープログラムが、ある名前の関数を呼び出すとき、本ライブラリの関数か、Adafruit_GFXの関数かを区別するため、本ライブラリには ardPort という名前で名前空間を付けてあります。(arduinoからPortingした、程度の意味で適当につけたものです)ここで追加する2行は、明示的に名前空間を指定せずに呼び出しを行った時、Adafruit_GFXではなく、本ライブラリの関数を呼び出すように定義を行います。
     

  3. 使用するポートの定義を行います。
    本解説では、使用するまでの準備>ハードウェア>結線例 にあるような接続をしています。これを、ライブラリに対して通知するための処理を行います。#defineでの定義と、ライブラリ関数への登録が必要になります。
    登録が終わったら、tft.beginを呼びだして液晶の制御を開始します。
     

  4. 漢字関連のフォントを設定し、画面に表示します。フォントファイルを includeし、制御開始後の液晶コントローラオブジェクトに対して、setFontを使用してフォントを指定します。引数は2つあります。実際の文字コードを表すデータと、フォントの文字コードとビットマップデータを結びつける情報です。フォントファイル(拡張子inc)の中を確認すると、指定するデータの名前を確認できます。
    tft.useWindowMode(true); を追加してあります。この指定することで、ILI9451の持っているウインドウ機能を使用して、効率的に文字が表示できることがあります。とくに問題がなければ、おまじないとして追加してください。
     

  5. 画面に文字を表示させる処理を追加してきます。
    画面を黒で塗りつぶし、文字の前景色、背景色を決定、表示位置を指定して文字を表示します。1つは固定の文字列、もう一つはprintfでフォーマット指定可能な文字の表示です。

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/spi.h"
#include "hardware/dma.h"

// ライブラリのヘッダファイル        <<<<< 追加  (1) 
#include "lib-9341/Adafruit_ILI9341/Adafruit_ILI9341.h"
#include "KanjiHelper.h"

// 漢字フォント情報ファイル         <<<<< 追加  (4) 
#include "Kanji/Fonts/JF-Dot-Shinonome12_12x12_ALL.inc"

// 名前空間の使用を宣言            <<<<< 追加 (2)
using namespace ardPort;
using namespace ardPort::spi;


// 使用するポートの定義            <<<<< 追加 (3)
#define TFT_SCK 18  // 液晶表示の SCK
#define TFT_MOSI 19 // 液晶表示の MOSI
#define TFT_DC 20   // 液晶画面の DC
#define TFT_RST 21  // 液晶画面の RST
#define TFT_CS 22   // 液晶画面の CS

int main()
{
    stdio_init_all();
    
    // ILI9341ディスプレイのインスタンスを作成  <<<<< 追加 (3)
    Adafruit_ILI9341 tft = Adafruit_ILI9341(&SPI, TFT_DC, TFT_CS, TFT_RST); 
    SPI.setTX(TFT_MOSI); // SPI0のTX(MOSI)
    SPI.setSCK(TFT_SCK); // SPI0のSCK  
    tft.begin();         // TFTを初期化

    // 漢字フォントの設定             <<<<< 追加 (4) 
    tft.setFont(JFDotShinonome12_12x12_ALL, JFDotShinonome12_12x12_ALL_bitmap); 

    // 文字の表示を高速化させる          <<<<< 追加 (4) 
    tft.useWindowMode(true); 

    // 画面を黒で塗りつぶす            <<<<< 追加 (5) 
    tft.fillScreen(ILI9341_BLACK); 

    while (true) {
        tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK); // 文字色を白に設定
        tft.setCursor(10, 10);
        tft.printf("こんにちは、世界!");                     // 文字を表示
        uint64_t time_us = time_us_64();                    // 起動後の経過時間(ミリ秒)
        tft.setCursor(10, 40);
        tft.printf("経過時間: %llu ms", time_us / 1000); // 経過時間を表示
    }
}

実行

コーディングが終わったら、ビルドして実行します。ビルドの手順はビルドできるかをテストしておくを参照してください。

画面に「こんにちは、世界!」などの文字が出れば正常です。

6.png

フォントの変更

フォントの変更には、プログラム中2カ所を変更する必要があります。 includeする日本語フォントデータと、setFontの引数です。
フォントデータは、./lib-9341/Kanji/Fonts の中に拡張子 inc で含まれています。例えば、IPAの24x24ドットの漢字フォント、教育漢字のみのデータを使用する場合、

#include "Kanji\Fonts\ipaexg_24x24_SCHOOL.inc"

となります。

ipaexg_24x24_SCHOOL.incを、テキストエディタで開くと、static const KanjiData で定義された、漢字データ構造体と、static const uint8_t で定義されている字形データが存在します。

    :
  (略)
    :
static const KanjiData ipaexg_24x24_SCHOOL[] = {
	{0x00000000 , 0x0000 , 0x0000 , 12 ,24 , 0x00000000},	// "0x00"
	{0x00000001 , 0x0001 , 0x0001 , 12 ,24 , 0x00000030},	// "0x01"
    :
  (略)
    :
static const uint8_t ipaexg_24x24_SCHOOL_bitmap[] = {
// UNICODE:0x00000000 -  Offset:0x00000000   -- CHAR:"0x00" 
	0x00,	0x00,		// 0000000000000000 
	0x00,	0x00,		// 0000000000000000 
    :
  (略)
    :

この二つの変数名を、setFontに与えることでフォントを指定します。ipaexg_24x24_SCHOOL.incの場合であれば次のようになります。

tft.setFont(ipaexg_24x24_SCHOOL, ipaexg_24x24_SCHOOL_bitmap); 

ビルドを行い、実行するとフォントが変更されています。

7.png

サンプルプログラムのビルドと実行

より多くの機能を確認するため、デモプログラムが合わせて配布されています。次の手順で、使っている環境ででもンストレーションプログラムを実行できます。

※このデモンストレーションプログラムは、XPT2046コントローラを使用し、接続されているTFT液晶用です。タッチパネルのICが無い場合や、異なるコントローラを使用している場合、タッチ機能が働きません。
画面上の<<タッチで次へ>>などはそのまま無視していると20秒程度で自動的に次に進みます。

新規プロジェクトを作成

プロジェクトの作成とライブラリのコピーを参照し、新規プロジェクトを作成します。

作成が終わったら、githubページから、右上にあるReleaseのリンクをクリック、最新のソースコードをダウンロードします。

zipファイルを解凍し、すべてのファイルを今回作成した新規プロジェクトのフォルダにコピーします。

上書きの確認があった場合、そのまま上書きしてください。

メインプログラムの削除

プロジェクトのルートフォルダには、今回作成したプロジェクトのmain 関数を含むファイルがありますが、このファイルは削除してください。

ビルドと実行

これで準備は終わりです。ビルドして実行してください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?