フォト
2025年4月
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30      
無料ブログはココログ

« 次はSTM32ボードを積極的に使ていきたい(22) グラフィック液晶(3) | トップページ | 次はSTM32ボードを積極的に使ていきたい(24) グラフィック液晶(5) »

2018年6月27日 (水)

次はSTM32ボードを積極的に使ていきたい(23) グラフィック液晶(4)

TFT表示制御とタッチスクリーン制御用SPIバスの共有利用

前回の続きです。前回はTFT液晶表示とタッチスクリーンでそれぞれにSPIバスを
割当ていましたが、SPIバスを共有利用する方式に変更しました。

機能としては前回と全く同じです。

結線図
01
結線表

02

ブレットボード上の実装

03


スケッチ

/***************************************************
  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カードスロットの併用も試してみたいと思います。

« 次はSTM32ボードを積極的に使ていきたい(22) グラフィック液晶(3) | トップページ | 次はSTM32ボードを積極的に使ていきたい(24) グラフィック液晶(5) »

arduino」カテゴリの記事

表示器制御関連」カテゴリの記事

ARM」カテゴリの記事

STM32」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

« 次はSTM32ボードを積極的に使ていきたい(22) グラフィック液晶(3) | トップページ | 次はSTM32ボードを積極的に使ていきたい(24) グラフィック液晶(5) »