1.总览

1.1 学习 TouchGFX 的原因

一开始我们学习过接在开发板之上的 LCD 屏幕,使用起来比较方便,用于调试非常合适,不过想做一些比较美观的困难(没有更深入学习图形库,因为电赛时间比较紧,学习的必要性比较低)

之后我们接触到了串口屏,串口屏开发简单,控件全面,学习成本比较低,非常适合当时我们时间比较紧的情况下学习。

但是串口屏的界面比较局限,被限制得很死,很难做出动画效果。所以在时间充裕的情况下我想尝试尝试 TouchGFX

初衷:想要借助 TouchGFX 做出更好的界面效果,要让开发更加舒畅!

1.2 涉及到的内容的参考

1.3 开发环境

STM32CubeIDE : 1.7.0

STM32Cube_FW_H7 : 1.9.0

X-CUBE-TOUCHGFX : 4.17.0

TouchGFX Designer : 4.18.0

2. BSP 的驱动

买了一块非常轻量的 H7 板子,封装十分不错

01开发板

型号:STM32H732IIT6

2.1 RCC

首先先配置外部时钟.

02RCC配置

2.2 Cache & MPU

H7 相比 F4,最核心的差别就是增加了 I&D Cache,掌握好能极大加速读写速度.

03Cache&MPU

2.3 LED

作为嵌入式开发可少不了点灯.

04LED

2.4 DEBUG

设置 DEBUG 为 串行 模式.

05DEBUG

2.5 USART

设置一个用于调试用的串口.

06USART

2.6 QSPI

外部 FLASH,芯片型号为 W25Q64,有 8M byte 的空间,驱动后可挂载到总线上,直接通过地址访问,用于之后储存较大的图片或者文字使用.(在引脚配置的界面,配置配置好 QSPI 对应的引脚后一点一点要右键 PIN(锁定)一下引脚,后面配置也是一样,不然可能会出现引脚莫名转移到其他位置的情况!)

07QSPI1
07QSPI2

2.7 SDRAM

外部 SDRAM,芯片类型为 W9825G6-6I,有 32M byte 的空间,用于之后作为显存使用。当然也可以用来“空间换时间”.

08SDRAM1
08SDRAM2

2.8 LDTC

通过 LDTC 配置 RGB接口.

这里还是推荐使用 RGB555,帧数更高,而且相较 RGB888 颜色差别也不太大.

09LDTC1
09LDTC2
09LDTC3

RGB接口支持 RGB888,由此出多的建议也配置上,防止以后误用.
09LDTC4

**重要:**配置 LDTC 的全局中断,因为 TouchGFX 的刷新依赖于 LDTC 的中断,所以这里必须要开启.
09LDTC5

最后还有一个背光控制的引脚需配置.
09LDTC6

2.9 DMA2D

09LDTC-DMA2D

2.10 触摸芯片的驱动

触摸芯片通过 IIC 来与 MCU 通信,这里使用 GPIO 模拟 IIC 的方法来实现通讯。
10TOUCH

2.11 时钟树

11时钟树

2.12 项目配置

12项目配置

2.13 相关驱动代码

2.13.1 QSPI

MX_QUADSPI_Init() 执行后要进入内存映射模式

1
2
3
4
/* USER CODE BEGIN QUADSPI_Init 2 */
QSPI_W25Qxx_Init(); //重启一下
QSPI_W25Qxx_MemoryMappedMode(); //进入透传模式
/* USER CODE END QUADSPI_Init 2 */

2.13.2 SDRAM

MX_FMC_Init() 执行后有相关配置

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  /* USER CODE BEGIN FMC_Init 2 */
SDRAM_Initialization_Sequence(&hsdram1,&command);//配置SDRAM
/* USER CODE END FMC_Init 2 */

/* USER CODE BEGIN 0 */
FMC_SDRAM_CommandTypeDef command; // 控制指令
/******************************************************************************************************
* 函 数 名: SDRAM_Initialization_Sequence
* 入口参数: hsdram - SDRAM_HandleTypeDef定义的变量,即表示定义的sdram
* Command - 控制指令
* 返 回 值: 无
* 函数功能: SDRAM 参数配置
* 说 明: 配置SDRAM相关时序和控制方式
*******************************************************************************************************/

void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
{
__IO uint32_t tmpmrd = 0;

/* Configure a clock configuration enable command */
Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; // 开启SDRAM时钟
Command->CommandTarget = FMC_COMMAND_TARGET_BANK; // 选择要控制的区域
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;

HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT); // 发送控制指令
HAL_Delay(1); // 延时等待

/* Configure a PALL (precharge all) command */
Command->CommandMode = FMC_SDRAM_CMD_PALL; // 预充电命令
Command->CommandTarget = FMC_COMMAND_TARGET_BANK; // 选择要控制的区域
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;

HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT); // 发送控制指令

/* Configure a Auto-Refresh command */
Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; // 使用自动刷新
Command->CommandTarget = FMC_COMMAND_TARGET_BANK; // 选择要控制的区域
Command->AutoRefreshNumber = 8; // 自动刷新次数
Command->ModeRegisterDefinition = 0;

HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT); // 发送控制指令

/* Program the external memory mode register */
tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;

Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE; // 加载模式寄存器命令
Command->CommandTarget = FMC_COMMAND_TARGET_BANK; // 选择要控制的区域
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = tmpmrd;

HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT); // 发送控制指令

HAL_SDRAM_ProgramRefreshRate(hsdram, 918); // 配置刷新率
}
/* USER CODE END 0 */

2.13.3 LDTC

MX_LTDC_Init() 执行后打开消抖和背光

1
2
3
4
/* USER CODE BEGIN LTDC_Init 2 */
HAL_LTDC_EnableDither(&hltdc); //开启消抖
HAL_GPIO_WritePin(LTDC_BL_GPIO_Port, LTDC_BL_Pin, GPIO_PIN_SET); //开启背光
/* USER CODE END LTDC_Init 2 */

3 TouchGFX

3.1 FreeRTOS

选择 FreeRTOS CMSIS_V2,并开启 FPU(先开着吧,也不知道会不会用上)

13FreeRTOS1

因为 TouchGFX 处理的函数将要执行在 defaultTask 任务上,而且需要较多堆栈空间,因此需要调整堆栈空间。

首先给 FreeRTOS 分配 256K byte 空间,再设置defaultTask 堆栈为 4096

13FreeRTOS2

13FreeRTOS3

Cube不推荐直接用滴答定时器作为系统时钟,所以这里我用基础定时器TIM7作为系统时钟

13FreeRTOS4

3.2 CRC

开启 CRC
14CRC

3.3 TouchGFX

首先要安装 Cube 的 TouchGFX 工具包(用于代码生成)
15TouchGFX1

15TouchGFX2

再配置 TouchGFX

15TouchGFX3

配置完成后就可以生成代码了!

3.4 忽略 TouchGFX 的 video 组件

Cube使用的是 4.17 的版本,而TouchGFX 使用的是 4.18的版本,编译的时候会出现以下报错。

16TouchGFX-Designer1

可配置项目忽略此文件

16TouchGFX-Designer2

3.5 生成 TouchGFX 代码

打开 TouchGFX 文件夹下的 ApplicationTemplate.touchgfx.part, 创建一个 Demo 例程。

16TouchGFX-Designer3

然后点击 </> 生成代码

3.6 添加 TouchGFX 处理任务

在 Src/freertos.c 文件下添加头文件

1
2
3
/* USER CODE BEGIN Includes */
#include "app_touchgfx.h"
/* USER CODE END Includes */

并在 StartDefaultTask 函数添加对应内容

1
2
3
4
5
6
7
8
9
10
11
12
void StartDefaultTask(void *argument)
{
/* init code for USB_DEVICE */
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
MX_TouchGFX_Process();
osDelay(1);
}
/* USER CODE END StartDefaultTask */
}

3.7 添加 触摸扫描 到TouchGFX

打开 TouchGFX/target/STM32TouchController.cpp 文件,添加触摸芯片初始化和扫描.

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/* USER CODE BEGIN STM32TouchController */

#include <STM32TouchController.hpp>

extern "C"{
#include "touch_800x480.h"
}

void STM32TouchController::init()
{
/* 触摸屏初始化 */
Touch_Init();
}

bool STM32TouchController::sampleTouch(int32_t& x, int32_t& y)
{
#define frequency 5 //扫描频率
static uint8_t i=0; //
static uint16_t lx,ly,lflag; //用于记录之前的坐标和记录


if(i/frequency) {
/* 开启一次对触摸屏的扫描 */
Touch_Scan();

/* 按下则赋予坐标 */
if(touchInfo.flag == 1) {
x = lx = touchInfo.x[0];
y = ly = touchInfo.y[0];
lflag = 1;
return true;
}
else {
lflag = 0;
return false;
}
}

else {
if(lflag == 1) {
x = lx;
y = ly;
return true;
}
else {
return false;
}
}
}

/* USER CODE END STM32TouchController */

添加完成后再上机烧录,实测没有问题,非常丝滑!

16TouchGFX-Designer4

4.总结

这次由商家给的例程移植到用 CubeIDE 开发,花了不少功夫,走了不少弯路(驱动不出来是真滴难受),但是我也接触到了 RTOS 已经 图形库 的内容,视野开扩了不少。

下一步需要学习的方向:

  • FreeRTOS 内核
  • TouchGFX 常用组件的使用

5.源码下载

source