次はSTM32ボードを積極的に使ていきたい(23) グラフィック液晶(4)
TFT表示制御とタッチスクリーン制御用SPIバスの共有利用
前回の続きです。前回はTFT液晶表示とタッチスクリーンでそれぞれにSPIバスを
割当ていましたが、SPIバスを共有利用する方式に変更しました。
機能としては前回と全く同じです。
結線図
結線表
ブレットボード上の実装
スケッチ
/*************************************************** This is our touchscreen painting example for the Adafruit ILI9341 Shield ----> http://www.adafruit.com/products/1651 Check out the links above for our tutorials and wiring diagrams These displays use SPI to communicate, 4 or 5 pins are required to interface (RST is optional) Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. MIT license, all text above must be included in any redistribution ****************************************************/ // 2018/06/25,たま吉さん, XPT2046コントローラー対応 // 2018/06/27,たま吉さん, SPI1のみ利用に修正 #include <SPI.h> #include <Adafruit_GFX_AS.h> // Core graphics library #include <Adafruit_ILI9341_STM.h> #include <XPT2046_touch.h> // This is calibration data for the raw touch data to the screen coordinates #define TS_MINX 600 #define TS_MINY 440 #define TS_MAXX 3460 #define TS_MAXY 3460 // TFT制御用ピン #define TFT_CS PA0 #define TFT_RST PA1 #define TFT_DC PA2 // タッチパネルCSピン #define CS_PIN PA3 // TFT制御用 Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(TFT_CS, TFT_DC, TFT_RST); SPISettings TFT_SPISet(SAFE_FREQ, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT); // タッチスクリーン制御用 SPIClass SPI_TS(1); XPT2046_touch ts(CS_PIN, SPI_TS); // Chip Select pin, SPI port // Size of the color selection boxes and the paintbrush size #define BOXSIZE 40 #define PENRADIUS 3 int oldcolor, currentcolor; void setup(void) { Serial.begin(115200); Serial.println(F("Touch Paint!")); tft.begin(SPI); tft.fillScreen(ILI9341_BLACK); ts.begin(); Serial.println("Touchscreen started"); // make the color selection boxes SPI.beginTransaction(TFT_SPISet); tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED); tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW); tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN); tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN); tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE); tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA); // select the current color 'red' tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); currentcolor = ILI9341_RED; SPI.endTransaction(); } void loop() { // Retrieve a point TS_Point p = ts.getPoint(); if ( (p.z <=800) || (p.z > 3000)) return; int16_t tmp = p.x; p.x = p.y; p.y = tmp; Serial.print("Z = "); Serial.print(p.z); Serial.print(" X = "); Serial.print(p.x); Serial.print(" Y = "); Serial.print(p.y); SPI.beginTransaction(TFT_SPISet); // Scale from ~0 ~ TS_MAXX to tft.width using the calibration #'s p.x = tft.width() - map(p.x, TS_MINX, TS_MAXX, 0, tft.width()); p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height()); Serial.print("("); Serial.print(p.x); Serial.print(", "); Serial.print(p.y); Serial.println(")"); if (p.y < BOXSIZE) { oldcolor = currentcolor; if (p.x < BOXSIZE) { currentcolor = ILI9341_RED; tft.drawRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 2) { currentcolor = ILI9341_YELLOW; tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 3) { currentcolor = ILI9341_GREEN; tft.drawRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 4) { currentcolor = ILI9341_CYAN; tft.drawRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 5) { currentcolor = ILI9341_BLUE; tft.drawRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } else if (p.x < BOXSIZE * 6) { currentcolor = ILI9341_MAGENTA; tft.drawRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, ILI9341_WHITE); } if (oldcolor != currentcolor) { if (oldcolor == ILI9341_RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED); if (oldcolor == ILI9341_YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, ILI9341_YELLOW); if (oldcolor == ILI9341_GREEN) tft.fillRect(BOXSIZE * 2, 0, BOXSIZE, BOXSIZE, ILI9341_GREEN); if (oldcolor == ILI9341_CYAN) tft.fillRect(BOXSIZE * 3, 0, BOXSIZE, BOXSIZE, ILI9341_CYAN); if (oldcolor == ILI9341_BLUE) tft.fillRect(BOXSIZE * 4, 0, BOXSIZE, BOXSIZE, ILI9341_BLUE); if (oldcolor == ILI9341_MAGENTA) tft.fillRect(BOXSIZE * 5, 0, BOXSIZE, BOXSIZE, ILI9341_MAGENTA); } } if (((p.y - PENRADIUS) > BOXSIZE) && ((p.y + PENRADIUS) < tft.height())) { tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor); } SPI.endTransaction(); }
タッチ・スクリーンライブラリ XPT2046_touch は、API利用の都度、SPIの通信条件の
再設定を行ってくれており、他のデバイス利用との共有が出来るのですが、
TFT制御用のライブラリ Adafruit_ILI9341_STM は行ってくれません。
他のデバイスでSPIを利用した後は、TFT制御のためのSPIの設定は正しくない状態に
なります。
そこでAdafruit_ILI9341_STM のAPI利用の前に、SPIの通信条件の設定を
行うよう、修正しました。
具体的には、SPISettings型のSPI通信条件を定義しておき、
SPISettings TFT_SPISet(SAFE_FREQ, MSBFIRST, SPI_MODE0, DATA_SIZE_16BIT);
この定義を使って、TFT制御の直前に
SPI.beginTransaction(TFT_SPISet);
を実行して、通信条件を設定しています。
TFT制御終了後は
SPI.endTransaction();
を実行します(ただし、この命令、内部的には何も行っていません。お飾りです)
次回はこの方式にて、SDカードスロットの併用も試してみたいと思います。
最近のコメント