● 実験テーマ150

「Picoで使用したILI9341_TFT液晶を、PIC24Fで動かす実験」
 (3.2"SPI液晶を、使い慣れている、PIC24Fで動かす実験をしてみました)

■ 2023.6.14
  ・既にこのテーマをやられている先人「趣味の実用電子工作」さんサイトにアップされてた、
   zipファイル:GLCD_SD_24F.Xをダウンロード後、解凍。
   プロジェクトファイル:GLCD_SD_24F.Xを開くと、
   dist- default- prodaction下に、HEXファイル:GLCD_SD_24F.X.prodactionがあるので、
   まずは、それをそのままPICに書込んでハードチェックがてら動作を確認してみた。

   グラフィックLCD用ライブラリーは、インターネット上で出回っているもの(GFX_Library.c)
   を改造して使用されているようで、見慣れた描画デモが展開された。
   SDカードへの書込み・読込みテストを含め、ハード(PIC24Fトレーニング基板使用)は問題無いようである。
   以下に描画デモの一部を示しました。

  ・私自身でも少し元のソースをいじって、ILI9341初期化のところだけでも理解しようと思い
   全画面を各色で塗潰すテスト、testFillScreen()のみのテストプロジェクトを作成してみることにした。
   オリジナルの開発環境は、
   MPLAB X IDE(v5.50)

    XC16(v1.70) に対し、
   私の環境は、ちょっと(だいぶかな・・)古く
   MPLAB X IDE v3.05
   XC16(v1.25)

   アップデートはPCの負荷が重くなるので極力やりたくないので、このままの環境で
   ILI9341初期化のところもオリジナル
   (手法としては、パラメータ・テーブルの置いてあるアドレス(ポインタ)を指定しインクリメントしながら
   パラメータの終わりまで、spi書込みを繰返すようなことをしている。)
   のまま記述してみた。


■ 2023.6.28
  ・昨日までに、SDは除いて、初期化のところまでsimpleなソースを考えてた。
  → 一応でっち上げた。

  ※ <結果>           ↓--- この対象となる変数も多岐にわたる。
    「unable to resolve identifier x」エラー多発。コンパイル以前のリンク段階でのエラーで先に進めず。
    (識別子 x を解決できません)

    この手のエラー多発:ILI9341.cにて
    どうもポインターの使い方に問題があるようだが・・・????
    それにしても、ILI9341初期化パラメータ・テーブルの数の多い事・・・


■ 2023.6.29
  「mag-tec電子工作」さんの、M5StackのILI9341ディスプレーを動かすソース例では、
   せいぜい5〜8個のパラメータを、テーブルでなく、直にwiteCommand()と、witeData()にて
   書込んでいる。
   これに変えてみる。

   void tft_begin(void)関数を書換える。
   直接コマンド・データともに与えるので、ILI9341.cの頭にあるパラメータ・マクロテーブルは不要になる。

/***********************************************************
* SPI 経由で ILI9341 に接続し、初期化手順コマンドを送信
************************************************************/
void tft_begin(void) {
delay_ms(100);

/// 100mS幅のリセットパルスを出力
TFT_RST = 1;
delay_ms(5);
TFT_RST = 0;
delay_ms(100); 
TFT_RST = 1;

delay_ms(200); 

TFT_CS = 0; // start write
TFT_DC = 1; // DCピンをHiにする 

witeCommand(0x38); //Idle mode OFF
witeCommand(0x3A); //COLMOD: Pixel Format Set
witeData(0b01010101); //RGB 16 bits / pixel, MCU 16 bits / pixel
witeCommand(0x36); //MADCTL: Memory Access Control
witeData(0b00001000); //D3: BGR(RGB-BGR Order control bit )="1"
witeCommand(0x11); //Sleep OUT
delay_ms(10);
witeData(0x29); //Display ON

TFT_CS = 1; // end write

_width = ILI9341_TFTWIDTH; // #define ILI9341_TFTWIDTH 240 ///< ILI9341 max TFT width
_height = ILI9341_TFTHEIGHT; // #define ILI9341_TFTHEIGHT 320 ///< ILI9341 max TFT height
rotation = 0;
}

  ・この修正でコンパイル通る。エラー無し。(今回未使用のsdカードポートの3信号に「unable to resolve identifier x」警告マークが
  いているが、コンパイルは綺麗に通っている。たぶん宣言だけで実行文がないので出ているマークと思われる。)

  ・hex書込んで動作確認したが、画面が真っ白のままng


■ 2023.6.30
<デバッグ開始>
 @ RESETパルスを確認した。
   100mS幅のLoパルスが正常に出力されてる。ok



 A ILI9341初期化関数:void tft_begin(void)を見直してみる。
   現在適応しているのは「mag-tec電子工作」さんの、M5StackのILI9341ディスプレーを動かすソース例。

   「ゆるプロ」さんのを参考にして、これと比較してみるとかなり異なる部分がある。

<「ゆるプロ」さんの初期化例>
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解放
}

<自分の場合・修正後>
/***********************************************************
* SPI 経由で ILI9341 に接続し、初期化手順コマンドを送信
************************************************************/
void tft_begin(void) {
delay_ms(100);

/// 100mS幅のリセットパルスを出力
TFT_RST = 1;
delay_ms(5);
TFT_RST = 0;
delay_ms(100); 
TFT_RST = 1;

delay_ms(200); 

TFT_CS = 0; // start write
TFT_DC = 1; // DCピンをHiにする

witeCommand(0x01); // SOFTWARE RESET 追加:230630
delay_ms(150); // このdelayはなくても大丈夫かも

witeCommand(0x13); // Normal Display Mode On(全画面表示)追加:230630

// witeCommand(0x38); //Idle mode OFF:削除 230630

witeCommand(0x3A); //COLMOD: Pixel Format Set
witeData(0b01010101); //RGB 16 bits / pixel, MCU 16 bits / pixel
witeCommand(0x36); //MADCTL: Memory Access Control
witeData(0b00001000); //D3: BGR(RGB-BGR Order control bit )="1"
witeCommand(0x11); //Sleep OUT

delay_ms(100); // 【重要】このdelayは絶対に必要:電源が不安定な場合は長めに(120ms位に)する
// 10 -> 100に変更:230630 

witeData(0x29); //Display ON

TFT_CS = 1; // end write

_width = ILI9341_TFTWIDTH; // #define ILI9341_TFTWIDTH 240 ///< ILI9341 max TFT width
_height = ILI9341_TFTHEIGHT; // #define ILI9341_TFTHEIGHT 320 ///< ILI9341 max TFT height
rotation = 0;
}

※ これでやってみたが結果は同じng
→ 初期化のパラメータの与え方は、これで良いはずと思う・・・
  基本的に、SPI通信が出来ているかタイミングを確認してみたい。
  それには、通信速度=16MHzを、100kHz以下に落とさないと、自作ロジアナでは見れない。

<その修正箇所 (デバッグの為の一時的な変更)>
 @ PIC24F_GLCD_MSP3217_TEST_1.c
Fcy= 16MHz→ 4MHzにダウン
// CONFIG2
// #pragma config FNOSC = FRCPLL // 内部オシレータでPLL動作させる
#pragma config FNOSC = FRC // 内部オシレータでPLL動作無し

 A PIC24F_GLCD_MSP3217_TEST_1.c
SPI2のプライマリプリスケールの分周 1:1 → 1:64に増やす
// SPI2_Init(SPI2_MODE0, SPI2_PPRE_DIV1, 0); //プライマリプリスケールの分周 1:1 (16MHz x 1/1 = 16MHz)
SPI2_Init(SPI2_MODE0, SPI2_PPRE_DIV64, 0); //プライマリプリスケールの分周 1:64 (4MHz x 1/64 = 62.5kHz)

 B ILI9341.h
/// クロック周波数定義 ---------------------
// #define CLOCK 16
#define CLOCK 4

・あと上記には関係ないけど、デバッグled(RA3,4)ポートの初期化が、Loになっていて点灯しているので
 ここだけHiにしておく。
 そしてプログラムの最後(while(1))の前で、RA3(赤)LEDを点灯させることにする。

----------------------------------------------------------------------------------------------------------------

<修正後の動作確認結果>
 @ 以下のチャンネル設定で自作ロジアナにてSPIタイミングを確認したところ、CS/の立下りから
   witeCommand(0x11); //Sleep OUTまで問題無いことが確認出来た。
 ※-> いや良くタイミングをみたら、何故かCS/が立ち下がってから上がりまでの時間が極短い??-
 ---> 230701に気付く!! 
     しかしこの時は、この事が、画面が真っ白なまま・・の原因だとは、何故か思わなかった。
   


 A それと今更ながら設定ソースに誤りのある事が発覚。
    writeData(0x29); //Display ON -> writeCommand(0x29); //Display ON が正しい

 ※ ここまでの修正をしたが未だ症状変わらず。真っ白表示のまま??
   何か設定が足りないのか???


■ 2023.7.1
  ・setAddrWindow()のところのcs/からのタイミングが上手く取れた。
   この部分のspiタイミングは問題無いと言って良いと考える。


■ 2023.7.4
  ・setAddrWindow(x, y, w, h);で、writeCommand(ILI9341_RAMWR); // Write to RAMまでは確認出来ているので、
   全画面(320 x 240= 76800画素)を赤:0xF800で埋め尽くす関数のところのタイミングを観測してみる。
 
   自作ロジアナはトリガ用の信号が無いと厳しい。
   led_on(RA3)信号をトリガにしてみる。
   そこがlowになったら、そのルーチンが実行される。

void fillRect(int x, int y, int w, int h, unsigned int color) {
 unsigned long px;

 /// 16bitカラーコードを上位8bit/ 下位8bitに変換(RGB565変換)
 unsigned char hi,lo;
 hi = (unsigned char)((color >> 8) & 0x00FF);
 lo = (unsigned char)(color & 0x00FF);

 if( (x < _width) && (y < _height) && w && h) { // 塗り潰し範囲が範囲内か?(ゼロ以外の幅と高さになっているか?)
  if((x + w - 1) >= _width) w = _width - x;
  if((y + h - 1) >= _height) h = _height - y;

  TFT_CS = 0; // start write
  setAddrWindow(x, y, w, h);

  px = (unsigned long)(w * h); // 塗り潰し範囲内の画素総数

  PORTAbits.RA3=0; // RED LED ON(デバッグ・ロジアナトリガ用)230704

  /// 塗り潰し範囲内の画素総数だけSPI書込みし指定色で塗潰す
  while (px--) {
   writeData(hi);
   writeData(lo);
  }
  TFT_CS = 1; // end write
 }


-----------------------------------------------------------------------------------------------------------

<main>

//--------------------------
// グラフィック表示例の処理
//--------------------------
testFillScreen();

PORTAbits.RA3=1; // RED LED OFF
while(1);
}

/***********************************************************
* グラフィック表示例用の関数群
* 初回バージョンは、全面を各色指定で塗り潰す関数のみテスト
************************************************************/
void testFillScreen() {
// fillRect(0, 0, _width, _height, ILI9341_BLACK);
fillRect(0, 0, _width, _height, ILI9341_RED);
// fillRect(0, 0, _width, _height, ILI9341_GREEN);
// fillRect(0, 0, _width, _height, ILI9341_BLUE);
// fillRect(0, 0, _width, _height, ILI9341_BLACK);
}

※ 320 x 240= 76800画素分書込むので、
  自作ロジアナのバッファには全部収まり切れない。
  5121byte分が上限
  途中の取得データで評価可能

<評価結果>
・赤のRGB565コード:0xF800
 これを、上位8bit:0xF8と、下位8bit:0x00に分けて正常に、2byte転送されていた。


■ 2023.8.17
  ・ここ5Wほど、SPIのタイミング設定等、色々試したが、どうしても「画面真っ白」のまま変わらず。
   初期化のspiタイミングも良さそうだし。
   初期化の内容も良さそうなのに????

   大元プロジェクト「GLCD_SD_24F.X」(趣味の電子工作さん)のhexでは動いているのに・・・・
   そのままのソースでコンパイルすると、私の使っている古いMPLAB IDE X v.3.05では、ポインタ変数の所
   で大量のエラーが出てコンパイル不能になる。

   どうも迷走状態にはまり込んでしまったようで、このプロジェクトは暫く保留にすことにした。
   気が向いたら再開予定にする。


■ 2023.10.4
  ・ずいぶんと間が空いてしまったが、ちょっとやる気が出たので再開することに。
   まずは、これまで、MPLAB X IDEでデバッグを進めてきたが、やにWIN10_PCへの負荷が重く、
   特に、MPLAB X IDE起動時、完全に立上るまでに、時間が掛かり過ぎて非効率。
   (前々から、MPLAB_X_IDEの立上り時間が異常に長いのが気になっている。
    「Back ground scanning....」とは何をやってんだか? )

   そこで、負荷が軽くて常用している、MPLAB IDE v8.60に適合するようソースを変更して
   この先、進めることにした。

   コンパイルokだが、白画面のまま変わらず。


■ 2023.10.5
  ・spiのclkとdataのタイミングが気になっている。再度転送速度を、62.5kHzに落として確認
   -> タイミングは問題ない模様
     ちゃんと、clkの立上りで、dataを読込んでいる。


■ 2023.10.6
  ・TFT初期化の冒頭で、CSをアクティブLoにするが、一瞬Loになってから直ぐにHiに戻ってしまう事を再確認した。



  -> CSをアクティブLo後、DCをHiにしているが、DCレベルの初期化はmain頭で既に済んでいるので
    ダブル処理になる。ここを削除したら、TFT初期化ルーチンを実行の間、CSはアクティブLo
    をキープするようになり初めて塗潰し動作を確認出来た。



    ただし未だおかしい。横方向は良いのだが、縦方向が上部の一部しか塗潰さない・・


    しかし何故、この処理をしたら良くなったかはよく判らない。(ダブル処理だが問題無いはず) 
    CSとDCの微妙なタイミングの問題が改善されたのかな・・・  
     まあ長い間ここで悩んでいたのが解決したので良しとする。
     (TFT初期化の間、CSがノンアクティブHiの為、設定が全て無効になっていたので当然な話である)

  -> fillRect関数内で以下修正した
    (1) 340- -> 320 (塗潰し範囲オーバー判断の箇所)
    (2) px=(unsigned long)(w * h);が思い通リ動いていないようで
      直に、320x240=76800なので、px= 76800としたら、全画面塗潰しはokになる。


■ 2023.10.7
  ・px = (long)w * h;としたら、変数対応の塗潰しokになる。


■ 2023.10.8
  ・中央付近に小さな塗潰し四角形を描画を追加


■ 2023.10.13
  ・新たなプロジェクトを作成し、塗潰し四角形描画の他、各種の描画デモを追加した。
   詳細は、末尾にアップしたソース類を参照してください。


<最終回路図>
 ・こちらから、どうぞ→ 「PIC24F_3.2"SPI_GLCD実験回路図」

<最終ソース及び、ヘッダーファイル>

(1) mainソース
  @ PIC24F_GLCD_ILI9341_TEST_SIMPLE.c(四角形を各色で塗潰すのみのテスト)
   A PIC24F_GLCD_ILI9341_TEST.c (各種描画デモ)

(2) 各種ライブラリ・ヘッダファイル
  ・ILI9341.c
  ・ILI9341.h
  ・skSPIlib.c
  ・skSPIlib.h
  ・ASCII12dot(12*12_フォントデータ: 後閑氏が作成された、アスキー文字データ ・ 後から私自身で数点キャラクタを追加してます)
  ・ImageData.h


← 実験テーマ1に戻る   TOP PAGEに戻る   実験テーマ151へ →