ゆるく楽しむプログラミング

320x240 TFT液晶 ILI9341

2.8" TFTインチ液晶ディスプレイ タッチパネル
の液晶部分 240x320ドットの ILI9341です。

このTFT液晶は電源電圧は3.3~5V対応ですが、信号レベルは3.3Vなので
ArduinoUNOなどの5V系のマイコンで使用する場合にはレベルシフタが必要です。
私は 8Bit双方向ロジックレベルコンバータ を使用しました。
ロジックレベルを3.3Vに変更できるArduinoUNO互換機(KEYSTUDIO PLUS)や、M5Stamp、RaspberryPi PICOでは直接接続できます。

ArduinoUNOとの接続

信号名がシルク印刷されていますので分かり易いと思います。
ハードウエアSPIを使用するために、ArduinoUNO側では13,12,11番ピンは固定ですが、それ以外は任意のピンに割り当てできます。
LCDモジュール ArduinoUNO 
VCC  3.3V 
GND  GND 
CS  D10 
RESET  D9 
DC  D8 
SDI(MOSI)  D11 
CSK  D13 
LED 3.3V 
SDO(MISO)  D12 



ILI9341のコマンド

動作 COMAND PARAMETA
Software Reset
 ソフトウエア・リセット
0x01 パラメタ - なし
Memory Access Control
 メモリと画面の対応(表示方向の設定)
0x36 パラメタ - 1Byte
 横(0xE8) or 縦(0x48)
COLMOD: Pixel Format Set
 メモリと表示色の対応(色指定方法の設定)
0x3A パラメタ - 1Byte
 16bit色(0x55) or 18bit色(0x66)
Sleep Out
 スリープモードからの復帰
0x11 パラメタ - なし
【重要】コマンド送信後、電源が安定するまで(5m秒以上)待つ必要がある。
Enter Sleep Mode
 スリープモードに設定
0x10
Display ON
 表示ON
0x29 パラメタ - なし
Display OFF
 表示OFF
0x28
Display Inversion OFF
表示色反転 OFF
0x20 パラメタ - なし
Display Inversion ON
表示色反転 ON
0x21 パラメタ - なし
Normal Display Mode On
全画面表示
0x13 パラメタ - なし
Partial Mode ON
部分表示
0x12 パラメタ - なし
範囲はPartial Area command(0x30)で指定
Partial Area
部分表示範囲指定
0x30 パラメタ - 2Bayte + 2Bayte
Column Address Set
ドットデータ書き込みカラム位置
0x2A パラメタ - 2Bayte + 2Bayte
Page Address Set
ドットデータ書き込みページ位置
0x2B パラメタ - 2Bayte + 2Bayte
Memory Write
ドットデータ書き込み
0x2C パラメタ - N Bayte
Memory Read
ドットデータ読み出し
0x2E パラメタ - N Bayte
Vertical Scrolling Start Address
スクロール開始アドレス
0x37 パラメタ - 2Bayte
初期化に必要なコマンド 描画に必要なコマンド

コマンドは1バイトでパラメタはデータ扱いになります
DCをLOWにしてコマンドを送信、DCをHIGHにしてパラメタを送信の手順で使用します

描画方向の設定

描画方向は、Memory Access Control(0x36)コマンドのパラメタで設定します
パラメタ設定は▼の通り
  D7 D6 D5 D4 D3 D2 D1 D0
コマンド  0 0 1 1 0 1 1 0
パラメタ  MY
(Y軸方向)
MX
(X軸方向)
MV
(XY軸入れ替え)
ML
(Y軸更新方向)
RGB
(色割り当て
 RGB or BGR)
MH
(X軸更新方向)
- -



Dotの色指定

1Dot(ピクセル)の色を指定する方法(フォーマット)の指定は COLMOD: Pixel Format Set で行います。
Memory Writeで書き込む値は 16Bitモードと18Bitモードで▼のようになります


描画手順

描画範囲を指定し、指定範囲を埋めるBitmapデータを送信する
描画範囲 COLの指定  0X2A  SC,EC
描画範囲 ROWの指定   0x2B  SP,EP
描画データ送信   0x2C  Bitmapデータ
※SC,EC,SP,EPは各16Bit



最小構成のスケッチ


ILI9341-DEMO2.zip ※参考動画で使用しているDEMOのスケッチ

ILI9341-DEMO-SIMPLE.zip
※ <>を全角<>に置き換えています。コピペの際は注意してください。
  ▼に表示しているのは、プログラムの一部です。全体はZIPファイルを解凍して参照してください。
// ILI9341 SPI Graphics TEST
#include <SPI.h>
#include "image2.h"
#include "font8x16.h"

#define TFT_CLK 13
#define TFT_MISO 12
#define TFT_MOSI 11
#define TFT_DC 8
#define TFT_RST 9
#define TFT_CS 10
// BackLightはHIGH固定にするのでソフトがらは制御しない
#define TFT_BL 7

// SPISettings settings = SPISettings(8000000, MSBFIRST, SPI_MODE0);  // 8MHzで合ってるよね?変だと思ったら修正してください。

// ▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼
void setup() {
  SPI.begin();  //SPIを初期化、SCK、MOSI、SSの各ピンの動作は出力、SCK、MOSIはLOW、SSはHIGH
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
//  SPI.beginTransaction(settings); // M5StampやRaspberryPi PICOで使う時はコッチの設定でないとコンパイルが通らない

  // --- ST3375 INITIAL
  pinMode(TFT_CS, OUTPUT);
  pinMode(TFT_DC, OUTPUT);
  pinMode(TFT_RST, OUTPUT);

  // --- HARDWARE Reset
  digitalWrite(TFT_RST, LOW);
  delay(20);
  digitalWrite(TFT_RST, HIGH);
  delay(20);    // このdelayは必要

  // --- ILI9341 動作設定
  digitalWrite(TFT_CS, LOW);  // TFTセレクト

  digitalWrite(TFT_DC, LOW);  // Command mode
  SPI.transfer(0x01);         //<< SOFTWARE RESET
  delay(150);                 // ※このdelayはなくても大丈夫かも

  SPI.transfer(0x13) ;        //<< Normal Display Mode ON

  SPI.transfer(0x36) ;        //<< Memory Access Control
  digitalWrite(TFT_DC, HIGH); // Data mode
  SPI.transfer(0x48) ;        //   MX = ON , GBR = ON (縦画面,左から右に表示)

  digitalWrite(TFT_DC, LOW);  // Command mode
  SPI.transfer(0x3a) ;        //<< COLMOD: Pixel Format Set
  digitalWrite(TFT_DC, HIGH); // Data mode
  SPI.transfer(0x55) ;        //<< 16Bits / 1Pixcel

  digitalWrite(TFT_DC, LOW);  // Command mode
  SPI.transfer(0x11) ;        //<< Sleep Out

  delay(60);                  // 【重要】このdelayは絶対に必要:電源が不安定な場合は長めに(120ms位に)する

  SPI.transfer(0x29) ;        //<< Display ON

  digitalWrite(TFT_CS, HIGH); // TFT解放
}

// ▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼▲▼
void loop() {
  for (int i=0;i<5;i++) {
    uint16_t color = 0x0000 ;
    switch(i) {
      case 0: color = 0x0000 ; break ;
      case 1: color = 0xF800 ; break ;
      case 2: color = 0x07E0 ; break ;
      case 3: color = 0x001F ; break ;
      case 4: color = 0xFFFF ; break ;
    }
    // --- 画面塗りつぶし
    digitalWrite(TFT_CS, LOW);  //TFTセレクト

    digitalWrite(TFT_DC, LOW);  // Command mode
    SPI.transfer(0x2a);         //<< Column Address Set
    digitalWrite(TFT_DC, HIGH); // Data mode
    SPI.transfer16(0);          // 開始カラム 0
    SPI.transfer16(239);        // 終了カラム 239

    digitalWrite(TFT_DC, LOW);  // Command mode
    SPI.transfer(0x2b);         //<< Page Address Set
    digitalWrite(TFT_DC, HIGH); // Data mode
    SPI.transfer16(0);          // 開始ページ 0
    SPI.transfer16(319);        // 終了ページ 319

    digitalWrite(TFT_DC, LOW);  // Command mode
    SPI.transfer(0x2c);         //<< Memory Write
    digitalWrite(TFT_DC, HIGH); // Data mode
    for (int y = 0 ; y < 320 ; y++) {
      for (int x = 0 ; x < 240 ; x++) {
        uint16_t data = color ;
        SPI.transfer16(color);
      }
    }
    digitalWrite(TFT_CS, HIGH); //TFT解放
    delay(500) ;
  }
}

解説動画