70歳の挑戦... 8bitパラレルTFTディスプレイモジュール、STMCubeIDE、STM32F411　表示できました

　![F411_8Para.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/893ae318-5a5a-261a-a1c0-5b2ef388b19b.jpeg)
　STM32F411CEU6ボード（BlackPill）からのSPI接続TFTモジュールへの表示はArduinoIDE環境下では出来ました。STM32CubeIDE環境では敷居が高く、なかなかできませんでした。何度目かの挑戦です。さらに今回は8ビットパラレル接続でやってみようと。そのため機材も整えました。ジャンパー線を繋ぎ易くはんだ付け配線したユニバーサル基板と700円程で購入した「ST-LINK V2」（これで書込み作業が格段に楽に）です。
 
![8bitParallel.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/50f224ba-f841-9ca4-d36b-8927bd0c9d51.jpeg)

 ![stlink.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/2eca9e9c-baba-1f47-3e4d-8cdcc85fe308.jpeg)

 そうこうするなか、次のサイトをみつけました。
 
 https://controllerstech.com/interface-tft-display-with-stm32/
 
ボードもディスプレイも違いますが、なんとなく出来そうな予感がしたので、ZIPファイルをダウンロードさせて頂きやってみたら... 表示出来ました:heart_exclamation:経過と変更点を以下に示します。
　まず、マイコンが異なります。上記サイトでは「F103c8」を使用しているようですが、私が使いたいのは「F411CE」です。STM32CubeIDE を立上げ、「STM32F411CEU6」を選択。Clock Configurationで最高速の100MGHzに設定。
 
![IDE_100MGHz.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/90372907-85f4-f0eb-13aa-cba959a6f86d.jpeg)

Pinout & Configuration は次のようにしました。

![PinOut.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/3ffa7117-4545-cffa-3bcd-d61a96d26f41.jpeg)

スッキリ配線にしたくて、事前にArduinoIDEで試したところ可能だったので、コントロールピン、データピンをこのように設定しました。user_setting.h 内の記述も次のように変更。
```c:user_setting.h
#ifndef USER_SETTING_H_
#define USER_SETTING_H_

#define RD_PORT GPIOA
#define RD_PIN  GPIO_PIN_4
#define WR_PORT GPIOA
#define WR_PIN  GPIO_PIN_3
#define CD_PORT GPIOA          // RS PORT
#define CD_PIN  GPIO_PIN_2     // RS PIN
#define CS_PORT GPIOA
#define CS_PIN  GPIO_PIN_1
#define RESET_PORT GPIOA
#define RESET_PIN  GPIO_PIN_0

#define D0_PORT GPIOB
#define D0_PIN GPIO_PIN_0
#define D1_PORT GPIOB
#define D1_PIN GPIO_PIN_1
#define D2_PORT GPIOB
#define D2_PIN GPIO_PIN_2
#define D3_PORT GPIOB
#define D3_PIN GPIO_PIN_3
#define D4_PORT GPIOB
#define D4_PIN GPIO_PIN_4
#define D5_PORT GPIOB
#define D5_PIN GPIO_PIN_5
#define D6_PORT GPIOB
#define D6_PIN GPIO_PIN_6
#define D7_PORT GPIOB
#define D7_PIN GPIO_PIN_7

#define  WIDTH    ((uint16_t)320)
#define  HEIGHT   ((uint16_t)480)
.
.
```
STM32CubeMX での設定により main.h が作成されますが、user_setting.h の name 付けが優先されるようです。TFTモジュールの幅と高さも今回私の使用する物に合わせて直しておきます。
　Tim1のdelay関数を作るように書かれてますが不要かもしれません（動かしてみるとかなり高速なので、適宜delayを入れても良いかも）。
　ピンの変更に伴い次に重要なのは「write_8 function」「read_8 function」の書換えです。user_setting.h のその部分を次のように変更しました。
 ```c:user_setting.h
  #define write_8(d) { \
   GPIOB->BSRR = 0b0000000011111111 << 16; \
   GPIOB->BSRR = (((d) & (1<<0)) << 0) \
               | (((d) & (1<<1)) << 0) \
			   | (((d) & (1<<2)) << 0) \
			   | (((d) & (1<<3)) << 0) \
			   | (((d) & (1<<4)) << 0) \
			   | (((d) & (1<<5)) << 0) \
			   | (((d) & (1<<6)) << 0) \
			   | (((d) & (1<<7)) << 0); \
	}

...

  #define read_8() (        (((GPIOB->IDR & (1<<0)) >> 0) \
                           | ((GPIOB->IDR & (1<<1)) >> 0) \
                           | ((GPIOB->IDR & (1<<2)) >> 0) \
                           | ((GPIOB->IDR & (1<<3)) >> 0) \
                           | ((GPIOB->IDR & (1<<4)) >> 0) \
                           | ((GPIOB->IDR & (1<<5)) >> 0) \
                           | ((GPIOB->IDR & (1<<6)) >> 0) \
                           | ((GPIOB->IDR & (1<<7)) << 0)))



/********************* For 180 MHz *****************************/
//#define WRITE_DELAY { WR_ACTIVE8; }
//#define READ_DELAY  { RD_ACTIVE16;}


/************************** For 72 MHZ ****************************/
//#define WRITE_DELAY { }
//#define READ_DELAY  { RD_ACTIVE;  }


/************************** For 100 MHZ ****************************/
#define WRITE_DELAY { WR_ACTIVE2; }
#define READ_DELAY  { RD_ACTIVE4; }


/************************** For 216 MHZ ****************************/
//#define WRITE_DELAY { WR_ACTIVE8; WR_ACTIVE8; } //216MHz
//#define IDLE_DELAY  { WR_IDLE4;WR_IDLE4; }
//#define READ_DELAY  { RD_ACTIVE16;RD_ACTIVE16;RD_ACTIVE16;}


/************************** For 48 MHZ ****************************/
//#define WRITE_DELAY { }
//#define READ_DELAY  { }


/*****************************  DEFINES FOR DIFFERENT TFTs   ****************************************************/

//#define SUPPORT_0139              //S6D0139 +280 bytes
//#define SUPPORT_0154              //S6D0154 +320 bytes
//#define SUPPORT_1289              //SSD1289,SSD1297 (ID=0x9797) +626 bytes, 0.03s
//#define SUPPORT_1580              //R61580 Untested
//#define SUPPORT_1963              //only works with 16BIT bus anyway
//#define SUPPORT_4532              //LGDP4532 +120 bytes.  thanks Leodino
//#define SUPPORT_4535              //LGDP4535 +180 bytes
//#define SUPPORT_68140             //RM68140 +52 bytes defaults to PIXFMT=0x55
//#define SUPPORT_7735
//#define SUPPORT_7781              //ST7781 +172 bytes
//#define SUPPORT_8230              //UC8230 +118 bytes
//#define SUPPORT_8347D             //HX8347-D, HX8347-G, HX8347-I, HX8367-A +520 bytes, 0.27s
//#define SUPPORT_8347A             //HX8347-A +500 bytes, 0.27s
//#define SUPPORT_8352A             //HX8352A +486 bytes, 0.27s
//#define SUPPORT_8352B             //HX8352B
//#define SUPPORT_8357D_GAMMA       //monster 34 byte
//#define SUPPORT_9163              //
//#define SUPPORT_9225              //ILI9225-B, ILI9225-G ID=0x9225, ID=0x9226, ID=0x6813 +380 bytes
//#define SUPPORT_9326_5420         //ILI9326, SPFD5420 +246 bytes
//#define SUPPORT_9342              //costs +114 bytes
//#define SUPPORT_9806              //UNTESTED
#define SUPPORT_9488_555          //costs +230 bytes, 0.03s / 0.19s
//#define SUPPORT_B509_7793         //R61509, ST7793 +244 bytes
//#define OFFSET_9327 32            //costs about 103 bytes, 0.08s

#endif /* USER_SETTING_H_ */
```
合わせて、100MGHz用のWRITE_DELAY、READ_DELAY、ディスプレイSUPPORT_9488_555 の指定も出来ました。
（STM32CubeMXによる）コード生成後のCore/Inc、Core/Srcフォルダーに指示通り次のファイルをコピーします。

:::note
user_setting.h
fonts.h
functions.h
tft.h
fonts.c
tft.c
:::

tft.c 内のincludeを "stm32f1xx_hal.h" から変更しておきます（最初気付かずエラーになりました）。
```tft.c
#include "stm32f4xx_hal.h"
```

　最後に main.c 内に次の記述を加えます。
    
```c:main.c
.
.

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
  MX_CRC_Init();
  /* USER CODE BEGIN 2 */
  
  HAL_TIM_Base_Start(&htim1);

  ID = readID();

  HAL_Delay(100);

  tft_init (ID);

  fillScreen(BLACK);
  testFillScreen();
  testLines(CYAN);
  testFastLines(RED, BLUE);
  testFilledCircles(10, MAGENTA);
  testCircles(10, WHITE);

  printnewtstr(100, RED, &mono12x7bold, 1, "HELLO WORLD");

  scrollup(100);
  /* USER CODE END 2 */

  /* Infinite loop */
  
  /* USER CODE BEGIN WHILE */

  while (1)
  {
  
  .
  .
```
これでビルドすれば、警告はいっぱい出るものの .bin ファイルが作られます。
　さらに、最初の写真のように、関数をいじって文字列を表示してみました。ここでも難しいことはわからないもののいろいろ勉強になりました。
　最後まで見ていただきありがとうございます。