71歳の挑戦... TFT LCD Shield に STM32のF103・F401・F411 よりUTFT_Demoを表示、比較した。

　「STM32」の３種のMCUボードに全く同じスケッチ（接続に使用するPinも同じです）

:::note
・Arduino IDE 2.3.4
・8ビットパラレル接続のTFTLCDモジュール
・TFT_eSPI ライブラリの Example UTFT_Demo_480x320.ino
:::    
を動作させ、どのくらいの差が出るか比較してみました。ただし、次のようなToolsオプションを適用しました。

![ToolsOption.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/afdb118b-ff72-4dfd-8bc6-53ed8f513ac9.jpeg)
「with LTO」を付けたため赤字の警告メッセージが出ますが動作し、少し速くなってます。「Board」「Board part number」はもちろんそれぞれのボードに応じて変えてあります。その結果以下の通りです。

|チップの刻印|動作周波数|1ループに要する時間||
|--|------------------------|-------------|-------------|
|STM32F103C8T6|72MHz|1415msecs |72x1415=101,880|
|STM32F401CCU6|84MHz|1112msecs|84x1112=93,408 最速？|
|STM32F411CEU6|100MHz|984msecs|100x984=98,400|

ちなみに「F103C8T6」の「8」からフラッシュメモリサイズは「64KB」と思いきや、

    Sketch uses 84036 bytes (64%) of program storage space. Maximum is 131072 bytes.
    Global variables use 4732 bytes (23%) of dynamic memory, leaving 15748 bytes for local variables. Maximum is 20480 bytes.
となり「84KB」のスケッチを受け入れており、実サイズは「13107 bytes x 1024 = 128KB」のようです。
【参考】https://qiita.com/shuji4649/items/bb5a30f0cea2839f9439

![8bitPar_STM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/ca6d14c1-4d3e-4e12-8d31-f9b9107fac35.jpeg)

（写真内の金色の部品、以前購入した「ST-LINK V2」の御蔭で、作業がはかどりありがたいです。）
　TFTモジュールと各MCUボードの接続は全く同じで、次のようにしました。

|TFT LCD ディスプレイ|各MCUボードのGPIOピン|
|--|--|
|TFT_RST(LCD_RST)|PB3|
|TFT_CS |PB4|
|TFT_DC |PB5|
|TFT_WR |PB6|
|TFT_RD |PB7|
|TFT_D0 |PA0|
|TFT_D1 |PA1|
|TFT_D2 |PA2|
|TFT_D3 |PA3|
|TFT_D4 |PA4|
|TFT_D5 |PA5|
|TFT_D6 |PA6|
|TFT_D7 |PA7|
|5V|5V|
|GND|GND|

「User_Setup.h]とスケッチ本体の「UTFT_Demo_480x320.ino」を示します。

```html:User_Setup.h
#define USER_SETUP_INFO "User_Setup"

#define STM32

#define STM_PORTA_DATA_BUS
//#define STM_PORTB_DATA_BUS
// Tell the library to use parallel mode (otherwise SPI is assumed)
#define TFT_PARALLEL_8_BIT

#define ILI9488_DRIVER     // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high)

#define TFT_CNTRL_PORT GPIOB
#define TFT_DATA_PORT	GPIOA
#define TFT_DATA_SHIFT 0 // take the lower bits/pins 0..7

// The ESP32 and TFT the pins used for testing are:
#define TFT_RST  PB3//PB0  // Reset pin, toggles on startup
#define TFT_CS   PB4//PB1  // Chip select control pin (library pulls permanently low
#define TFT_DC   PB5//PB3  // Data Command control pin - must use a pin in the range 0-31
#define TFT_WR   PB6//PB4  // Write strobe control pin - must use a pin in the range 0-31
#define TFT_RD   PB7//PB5  // Read strobe control pin

#define TFT_D0   PA0  // Must use pins in the range 0-31 for the data bus
#define TFT_D1   PA1  // so a single register write sets/clears all bits.
#define TFT_D2   PA2  // Pins can be randomly assigned, this does not affect
#define TFT_D3   PA3  // TFT screen update performance.
#define TFT_D4   PA4
#define TFT_D5   PA5
#define TFT_D6   PA6
#define TFT_D7   PA7

#define LOAD_GLCD   // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2  // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4  // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6  // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7  // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
#define LOAD_FONT8  // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
#define LOAD_GFXFF  // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts

// ##################################################################################
//
// Section 4. Other options
//
// ##################################################################################

// For the STM32 processor define the SPI port channel used (default 1 if undefined)
//#define TFT_SPI_PORT 2 // Set to 1 for SPI port 1, or 2 for SPI port 2

// Define the SPI clock frequency, this affects the graphics rendering speed. Too
// fast and the TFT driver will not keep up and display corruption appears.
// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails
// With a ST7735 display more than 27MHz may not work (spurious pixels and lines)
// With an ILI9163 display 27 MHz works OK.

// #define SPI_FREQUENCY   1000000
// #define SPI_FREQUENCY   5000000
// #define SPI_FREQUENCY  10000000
// #define SPI_FREQUENCY  20000000
//#define SPI_FREQUENCY  27000000
// #define SPI_FREQUENCY  40000000
#define SPI_FREQUENCY  55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz)
// #define SPI_FREQUENCY  80000000

// Optional reduced SPI frequency for reading TFT
#define SPI_READ_FREQUENCY  20000000

// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here:
#define SPI_TOUCH_FREQUENCY  2500000
```

```cpp:UTFT_Demo_480x320.ino
/*
 Example animated analogue meters using a TFT LCD screen

 Originanally written for a 320 x 240 display, so only occupies half
 of a 480 x 320 display.

 Needs Font 2 (also Font 4 if using large centered scale label)

  #########################################################################
  ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
  #########################################################################
 */

// Attention to 5V !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// 128kb board.BluePill or BlackPill

#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>
#include "User_Setup.h" // User_Setup_Select.h からドライバー設定を外しておく

#define WAIT 0 // Delay between tests, set to 0 to demo speed, 2000 to see what it does!
#define WAITs 0 // Delay between tests, set to 0 to demo speed, 2000 to see what it does!
#define CENTRE 240

TFT_eSPI tft = TFT_eSPI();       // Invoke custom library
#define TFT_GREY 0x7BEF

uint32_t runTime = 0;

void setup()
{
  randomSeed(analogRead(0));
  Serial.begin(115200);
  Serial.println("* TFT_eSPI Test*");
// Setup the LCD
  tft.init();
  tft.setRotation(1);
}

void loop()
{
  int buf[478];
  int x, x2;
  int y, y2;
  int r;

  runTime = millis();
// Clear the screen and draw the frame
  tft.fillScreen(TFT_BLACK);

  tft.fillRect(0, 0, 480, 13, TFT_RED);

  tft.fillRect(0, 305, 480, 320, TFT_GREY);
  tft.setTextColor(TFT_BLACK,TFT_RED);

  tft.drawCentreString("* TFT_eSPI *", CENTRE, 3, 1);
  tft.setTextColor(TFT_YELLOW,TFT_GREY);
  tft.drawCentreString("Adapted by Bodmer", CENTRE, 309,1);

  tft.drawRect(0, 14, 479, 305-14, TFT_BLUE);

  delay(WAIT);
// Draw crosshairs
  tft.drawLine(239, 15, 239, 304, TFT_BLUE);
  tft.drawLine(1, 159, 478, 159, TFT_BLUE);
  for (int i=9; i<470; i+=10){
    tft.drawLine(i, 157, i, 161, TFT_BLUE);
    delay(WAITs);
  }
  for (int i=19; i<220; i+=10){
    tft.drawLine(237, i, 241, i, TFT_BLUE);
    delay(WAITs);
  }
// Draw sin-, cos- and tan-lines  
  tft.setTextColor(TFT_CYAN);
  tft.drawString("Sin", 5, 15,2);
  for (int i=1; i<478; i++){
    tft.drawPixel(i,159+(sin(((i*1.13)*3.14)/180)*95),TFT_CYAN);
    delay(WAITs);
  }
  
  tft.setTextColor(TFT_RED);
  tft.drawString("Cos", 5, 30,2);
  for (int i=1; i<478; i++){
    tft.drawPixel(i,159+(cos(((i*1.13)*3.14)/180)*95),TFT_RED);
    delay(WAITs);
  }

  tft.setTextColor(TFT_YELLOW);
  tft.drawString("Tan", 5, 45,2);
  for (int i=1; i<478; i++){
    tft.drawPixel(i,159+(tan(((i*1.13)*3.14)/180)),TFT_YELLOW);
    delay(WAITs);
  }

  delay(WAIT);

  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);
  tft.drawLine(239, 15, 239, 304,TFT_BLUE);
  tft.drawLine(1, 159, 478, 159,TFT_BLUE);

// Draw a moving sinewave
int col = 0;
  x=1;
  for (int i=1; i<(477*15); i++) {
    x++;
    if (x==478) x=1;
    if (i>478){
      if ((x==239)||(buf[x-1]==159)) col = TFT_BLUE;
      else      tft.drawPixel(x,buf[x-1],TFT_BLACK);
    }
    y=159+(sin(((i*0.7)*3.14)/180)*(90-(i / 100)));
    tft.drawPixel(x,y, TFT_BLUE);
    buf[x-1]=y;
    delay(WAITs);
  }

  delay(WAIT);
  
  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);

// Draw some filled rectangles
  for (int i=1; i<6; i++) {
    switch (i){
      case 1:
        col = TFT_MAGENTA;
        break;
      case 2:
        col = TFT_RED;
        break;
      case 3:
        col = TFT_GREEN;
        break;
      case 4:
        col = TFT_BLUE;
        break;
      case 5:
        col = TFT_YELLOW;
        break;
    }
    tft.fillRect(150+(i*20), 70+(i*20), 60, 60,col);
    delay(WAITs);
  }

  delay(WAIT);
  
  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);

// Draw some filled, rounded rectangles
  for (int i=1; i<6; i++) {
    switch (i) {
      case 1:
        col = TFT_MAGENTA;
        break;
      case 2:
        col = TFT_RED;
        break;
      case 3:
        col = TFT_GREEN;
        break;
      case 4:
        col = TFT_BLUE;
        break;
      case 5:
        col = TFT_YELLOW;
        break;
    }
    tft.fillRoundRect(270-(i*20), 70+(i*20), 60, 60, 3, col);
    delay(WAITs);
  }
  
  delay(WAIT);
  
  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);

// Draw some filled circles
  for (int i=1; i<6; i++) {
    switch (i) {
      case 1:
        col = TFT_MAGENTA;
        break;
      case 2:
        col = TFT_RED;
        break;
      case 3:
        col = TFT_GREEN;
        break;
      case 4:
        col = TFT_BLUE;
        break;
      case 5:
        col = TFT_YELLOW;
        break;
    }
    tft.fillCircle(180+(i*20),100+(i*20), 30,col);
    delay(WAITs);
  }
  
  delay(WAIT);
  
  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);

// Draw some lines in a pattern

  for (int i=15; i<304; i+=5) {
    tft.drawLine(1, i, (i*1.6)-10, 303, TFT_RED);
    delay(WAITs);
  }

  for (int i=304; i>15; i-=5) {
    tft.drawLine(477, i, (i*1.6)-11, 15, TFT_RED);
    delay(WAITs);
  }

  for (int i=304; i>15; i-=5) {
    tft.drawLine(1, i, 491-(i*1.6), 15, TFT_CYAN);
    delay(WAITs);
  }

  for (int i=15; i<304; i+=5) {
    tft.drawLine(477, i, 490-(i*1.6), 303, TFT_CYAN);
    delay(WAITs);
  }
  
  delay(WAIT);
  
  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);

// Draw some random circles
  for (int i=0; i<100; i++) {
    x=32+random(416);
    y=45+random(226);
    r=random(30);
    tft.drawCircle(x, y, r,random(0xFFFF));
  }

  delay(WAIT);
  
  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);

// Draw some random rectangles
  for (int i=0; i<100; i++) {
    x=2+random(476);
    y=16+random(289);
    x2=2+random(476);
    y2=16+random(289);
    if (x2<x) r=x;x=x2;x2=r;
    if (y2<y) r=y;y=y2;y2=r;
    tft.drawRect(x, y, x2-x, y2-y,random(0xFFFF));
    delay(WAITs);
  }

  delay(WAIT);
  
  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);

// Draw some random rounded rectangles
  for (int i=0; i<100; i++) {
    x=2+random(476);
    y=16+random(289);
    x2=2+random(476);
    y2=16+random(289);
    if (x2<x) r=x;x=x2;x2=r;
    if (y2<y) r=y;y=y2;y2=r;
    tft.drawRoundRect(x, y, x2-x, y2-y, 3,random(0xFFFF));
    delay(WAITs);
  }

  delay(WAIT);
  
  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);

  for (int i=0; i<100; i++) {
    x=2+random(476);
    y=16+random(289);
    x2=2+random(476);
    y2=16+random(289);
    col=random(0xFFFF);
    tft.drawLine(x, y, x2, y2,col);
    delay(WAITs);
  }

  delay(WAIT);
  
  tft.fillRect(1,15,478-1,304-15,TFT_BLACK);

  for (int i=0; i<10000; i++) {
    tft.drawPixel(2+random(476), 16+random(289),random(0xFFFF));
  }

  delay(WAIT);

  tft.fillRect(0, 0, 480, 320, TFT_BLUE);

  tft.fillRoundRect(160, 70, 319-160, 169-70, 3,TFT_RED);
  
  tft.setTextColor(TFT_WHITE,TFT_RED);
  tft.drawCentreString("That's it!", CENTRE, 93,2);
  tft.drawCentreString("Restarting in a", CENTRE, 119, 2);
  tft.drawCentreString("few seconds...", CENTRE, 132, 2);

  tft.setTextColor(TFT_GREEN,TFT_BLUE);
  tft.drawCentreString("Runtime: (msecs)", CENTRE, 280, 2);
  tft.setTextDatum(TC_DATUM);
  runTime = millis()-runTime;
  tft.drawNumber(runTime, CENTRE, 300,2);
  tft.setTextDatum(TL_DATUM);
  delay (10000);
}
```
　最後まで見ていただきありがとうございました。