/****************************************************** * プロジェクトファイル名:ILI9328_test2_Rev2.ino * ハードSPI版 * 初期化はaitendo参考コード準拠 * コントローラ:ESP32S3 Dev Module * 内蔵MPU:ESP32-WROOM-1:動作クロック周波数=240MHz(max) * * 2026/1/28 N.Ishii *******************************************************/ #include #include "soc/spi_reg.h" // レジスタ操作に必要 #include "soc/soc.h" /// LCDピン定義(ESP32S3側のGPIO番号) #define MOSI 11 #define SCK 12 #define CS 10 #define RST 18 // #define DC 7 // 未使用(接続しない) /// SPI2(FSPI)の名前を「SPI2」に統一して定義 SPIClass SPI2(FSPI); // SPIClass *SPI2 = new SPIClass(FSPI); // 設定をグローバルに定義(全関数で使用可能) // ソフトSPIの1.62uS(約600kHz)に合わせて設定 //SPISettings settings(600000, MSBFIRST, SPI_MODE3); SPISettings settings(10000000, MSBFIRST, SPI_MODE3); /******************************************* * 16bit Color Difinition *******************************************/ #define WHITE 0xFFFF #define BLACK 0x0000 #define RED 0xF800 #define GREEN 0x07E0 #define BLUE 0x001F #define CYAN 0x07FF #define YELLOW 0xFFE0 #define ROW 320 #define COL 240 void WriteData(unsigned int data) { SPI2.beginTransaction(settings); digitalWrite(CS, LOW); SPI2.transfer(0x72); // データ識別(スタートバイト:これからデータを送ります) SPI2.transfer(data >> 8); // 上位バイトを送信 SPI2.transfer(data & 0xFF); // 下位バイトを送信 digitalWrite(CS, HIGH); SPI2.endTransaction(); } void WriteCommand(unsigned int cmd) { SPI2.beginTransaction(settings); digitalWrite(CS, LOW); SPI2.transfer(0x70); // コマンド識別(スタートバイト:これからコマンドを送ります) SPI2.transfer(cmd >> 8); // 上位バイトを送信 SPI2.transfer(cmd & 0xFF); // 下位バイトを送信 digitalWrite(CS, HIGH); SPI2.endTransaction(); } void LCD_Init() { // ハードリセット digitalWrite(RST, LOW); delay(20); digitalWrite(RST, HIGH); delay(120); WriteCommand(0x00E5); WriteData(0x78F0); // set SRAM internal timing WriteCommand(0x0001); WriteData(0x0000); // s et SS and SM bit WriteCommand(0x0002); WriteData(0x0400); // s et 1 line inversion WriteCommand(0x0003); WriteData(0x1090); // s et GRAM write direction and BGR=1. WriteCommand(0x0004); WriteData(0x0000); // Resize register WriteCommand(0x0008); WriteData(0x0202); // s et the back porch and front porch WriteCommand(0x0009); WriteData(0x0000); // s et non-display area refresh cycle ISC[3:0] WriteCommand(0x000A); WriteData(0x0000); // RGB interface setting WriteCommand(0x000D); WriteData(0x0000); // Frame marker Position WriteCommand(0x000F); WriteData(0x0000); // RGB interface polarity // Power On sequence WriteCommand(0x0010); WriteData(0x0000); // SAP, BT[3:0], AP, DSTB, SLP, STB WriteCommand(0x0011); WriteData(0x0007); // DC1[2:0], DC0[2:0], VC[2:0] WriteCommand(0x0012); WriteData(0x0000); // VREG1OUT voltage WriteCommand(0x0013); WriteData(0x0000); // VDV[4:0] for VCOM amplitude WriteCommand(0x0007); WriteData(0x0001); // Dis-charge capacitor power voltage delay(200); WriteCommand(0x0010); WriteData(0x1690); // SAP, BT[3:0], AP, DSTB, SLP, STB WriteCommand(0x0011); WriteData(0x0227); // Set DC1[2:0], DC0[2:0], VC[2:0] delay(50); WriteCommand(0x0012); WriteData(0x008C); // External reference voltage= Vci; delay(50); WriteCommand(0x0013); WriteData(0x1500); // VDV[4:0] for VCOM amplitude 0X1000 WriteCommand(0x0029); WriteData(0x0004); // VCM[5:0] for VCOMH 0X0009 WriteCommand(0x002B); WriteData(0x000D); //Set Frame Rate delay(50); WriteCommand(0x0020); WriteData(0x0000); // GRAM horizontal Address WriteCommand(0x0021); WriteData(0x0000); // GRAM Vertical Address // Gamma WriteCommand(0x0030); WriteData(0x0000); WriteCommand(0x0031); WriteData(0x0607); WriteCommand(0x0032); WriteData(0x0305); WriteCommand(0x0035); WriteData(0x0000); WriteCommand(0x0036); WriteData(0x1604); WriteCommand(0x0037); WriteData(0x0204); WriteCommand(0x0038); WriteData(0x0001); WriteCommand(0x0039); WriteData(0x0707); WriteCommand(0x003C); WriteData(0x0000); WriteCommand(0x003D); WriteData(0x000F); // GRAM area WriteCommand(0x0050); WriteData(0x0000); // Horizontal GRAM Start Address WriteCommand(0x0051); WriteData(0x00EF); // Horizontal GRAM End Address WriteCommand(0x0052); WriteData(0x0000); // Vertical GRAM Start Address WriteCommand(0x0053); WriteData(0x013F); // Vertical GRAM End Address WriteCommand(0x0060); WriteData(0xA700); // Gate Scan Line WriteCommand(0x0061); WriteData(0x0001); // NDL,VLE, REV WriteCommand(0x006A); WriteData(0x0000); // set scrolling line // Partial Display WriteCommand(0x0080); WriteData(0x0000); WriteCommand(0x0081); WriteData(0x0000); WriteCommand(0x0082); WriteData(0x0000); WriteCommand(0x0083); WriteData(0x0000); WriteCommand(0x0084); WriteData(0x0000); WriteCommand(0x0085); WriteData(0x0000); // Panel Control WriteCommand(0x0090); WriteData(0x0010); WriteCommand(0x0092); WriteData(0x0600); WriteCommand(0x0007); WriteData(0x0133); // 262K color and display ON } void LCD_Fill(unsigned int color) { WriteCommand(0x0020); WriteData(0x0000); // Horizontal Start Address WriteCommand(0x0021); WriteData(0x0000); // Vertical Start Address WriteCommand(0x0022); // GRAM write /// 全画面塗りつぶし用(高速化のため一気に送る) SPI2.beginTransaction(settings); digitalWrite(CS, LOW); /// 開始指示 SPI2.transfer(0x72); // データ識別:Start Byte /// 320x240ピクセル分をループ for (int i = 0; i < COL * ROW; i++) { SPI2.transfer16(color); // 16bitを一気に送る } digitalWrite(CS, HIGH); SPI2.endTransaction(); } //======================================================================= void setup() { Serial.begin(115200); Serial.println("setup start"); // 一度確実に終了させてから開始(初期化の安定化) SPI2.end(); /// CS,RSTは手動制御なので設定が必要 /// SCK, MOSIはbeginに任せる(pinModeは不要) /// これで SPI.transfer() を呼び出した際に、ESP32のハードウェアが自動的に /// SCKピンからロック信号を出力してくれる SPI2.begin(SCK, -1, MOSI, CS); pinMode(CS, OUTPUT); pinMode(RST, OUTPUT); digitalWrite(CS, HIGH); digitalWrite(RST, HIGH); /// ビットずれ対策:レジスタ直接操作 /// SPI2(FSPI)の送信タイミングを半サイクル遅らせて安定させます /// (1 << 2) は DOUT_MODE ビットを指す //WRITE_PERI_REG(SPI_DIN_MODE_REG(2), (1 << 2)); WRITE_PERI_REG(SPI_DIN_MODE_REG(2), 0); // 入力遅延をリセット LCD_Init(); Serial.println("setup end"); } void loop() { Serial.println("RED start"); LCD_Fill(RED); Serial.println("RED end"); delay(1000); Serial.println("GREEN start"); LCD_Fill(GREEN); Serial.println("GREEN end"); delay(1000); Serial.println("BLUE start"); LCD_Fill(BLUE); Serial.println("BLUE end"); delay(1000); Serial.println("WHITE start"); LCD_Fill(WHITE); Serial.println("WHITE end"); delay(1000); }