[STM32U3] 【STM32U385RG 测评】移植TouchGFX

[复制链接]
 楼主| lulugl 发表于 2025-7-13 12:51 | 显示全部楼层 |阅读模式
本帖最后由 lulugl 于 2025-7-13 12:51 编辑

#申请原创#
【前言】
非常感谢21ic与ST,给予我这次参与【STM32U385RG 测评】评测的机会。本次我参与的计划是移植TouchGFX并且制做一个基于TouchGFX的门禁控制系统。下面我将分享如何创建这个综合的管理系统。
【开发环境】
1、STM32CubeMX,这个是工程的软件核心,用其配置工程所有的外设、时钟、操作系统、TouchGFX的基础代码。
2、STM32CubeCLT,这个是进行编译的核心,提供了交叉编译工具。
3、CLion,提供代码编辑工具。
4、TouchGFX Designer,做为最优秀的GUI设计工具,做到所见即所得。
【硬件】
1、NUCLEO_U3385RG-Q开发板。
2、ST7789LCD(带GT911触摸屏)
【工程创建】
1、打开STM32CubeMX创建基于STM32U385RG的基础工程。
15862687304f5c2640.png
2、配置主时钟为96MHz
31775687305470c46b.png
3、配置sys的时基为TIM15
43750687305e04af13.png
为了移植FreeRTOS后,出现HAL_Delay卡死,修改TIM15的中断级别为1:
690636873064959be2.png
4、配置USART1为日志输出,根据原理图,IO使用PA9、PA10,波特率为115200。
370968730705bbe5d.png
740896873072aca932.png
5、配置操作系统为FreeRTOS,内存管理为heap_4
2112668730774f240f.png
修改Heap Size、Stack Size为0x2000
56173687307c6db216.png
使能CMISIS RTOS2:
214326873082d46b00.png
6、打开ICHACE
7、为了使用TouchGFX,打开CRC
到此基础的工程已经移植好了。
【移植TouchGFX】
移植touchgGFX需要驱动带触摸的LCD屏,TFT为st7789、触摸为GT911
1、使用SPI1来驱动LCD屏,同时还需要指定CS、DC、RST三个IO,定义IO如下:
  1. /*
  2. LCD_PWR:PB10
  3. LCD_RST:PC6
  4. LCD_WR: PC7
  5. LCD_CS: PC9
  6. LCD_SCK  PA1
  7. LCD_SDA  PA7
  8. */
在stm32cubeMX配置如下:
5889168730b2a6df7f.png
特别注意一点是SCK必须配置为上拉,并且速度需要设置为very high。
3875368730bde2f36e.png
传输数据宽度为8bit,时钟极性为空闲是高电平,第二个时钟沿采样。
为了提高传输效率,给SPI1的TX配置GPDMA
7906568730cf3a4844.png
为CH0配置为SPI1_TX,传输为从内存到外设,地址为自动增长,为了更高效的传输,传宽宽为Half Word即为16bit宽度。
打开spi以及GPDMA中断
6709468730d943bcf5.png
2、配置PC6、PC7、PC9为普通输出。用于LCD的CS、RST、DC。
2293568730e8dbf056.png
3、配置GT911,GT911使用I2C2,同时还需要配置RST与INT
  1. /*
  2. //引脚图:
  3. SDA--PB13
  4. SCL--PB14
  5. INT--PC8
  6. RST--PB5
  7. */
4401168730f6216d04.png

66492687310044e2a5.png
触摸屏配置到这里结束了。
【背光控制】
为了可以实现背光控制,启用TIM2_CH3为PWM输出,配置为2K的输出:
53177687310f567692.png 同时还需要添加一个定时器6,为touchgGFX提供一个20ms心跳。
1145868732c732b4c9.png
到此外设配置结束
【TouchGFX】
打开cube-touchGFX
44296687311301de9b.png
2495468731160d539c.png
配置为自定义外设,宽长为240*320
实时操作系统为FreeRTOS V2
添加一个任务如下:
28267687312436c9ac.png
最后在工程中生成CMake的工程:
45036873128b1e580.png
【创建touchGFX基础界面】
使用TouchGFX Designer在创建的工程中添加一个空白GUI添加界面如下:
8019768731398d711e.png
生成代码后,使用Clion打开工程项目文件夹
【配置编译工具】
打开工程后,配置编工具链如下:
69102687314177e8b0.png
然后选择此工具链:
77533687314650fb4c.png
点击确定,打开工程。CMake会自动配置工程。
编译后成功生成工程: 9006568731762033e0.png
看到RAM占用达到95%,因此需要把heap放到第二个内存区域,修改链接文件如下:
  1.   ._user_heap_stack :
  2.   {
  3.     . = ALIGN(8);
  4.     PROVIDE ( end = . );
  5.     PROVIDE ( _end = . );
  6.     . = . + _Min_Heap_Size;
  7.     . = . + _Min_Stack_Size;
  8.     . = ALIGN(8);
  9.   } >RAM2
重新编译后点用内存如下:
  1. [89/89] Linking CXX executable 21ic_touchGFX.elf
  2. Memory region         Used Size  Region Size  %age Used
  3.              RAM:      170420 B       192 KB     86.68%
  4.             RAM2:         16 KB        64 KB     25.00%
  5.            FLASH:      305288 B         1 MB     29.11%
【移植lcd驱动】
将st7789与GT911的驱动添加到工程中。
809876873284da3bf1.png
将工程选项添加进CMakeLists.txt中
80528687328f272413.png
在lcd中配置spi写入字节的函数:
  1. /**************************************************************
  2. 函数名称 : sp1_write_byte
  3. 函数功能 : SPI1 写一个字节
  4. 输入参数 : w_data:要写入的字节,size:写入字节大小
  5. 返回值           : 0 --> 写入成功,其他 --> 写入失败
  6. 备注                 : 无
  7. **************************************************************/
  8. uint8_t sp1_write_byte(uint8_t *r_data, uint16_t size)
  9. {
  10.         return HAL_SPI_Transmit(&hspi1, r_data, size, 1000);
  11. }
【区配置touchgfx显示】
1、打开TouchGFXHAL.cpp中在顶部添加代码如下:
  1. #ifdef __cplusplus
  2.     extern "C"{
  3. #include "lcd.h"
  4. #include "stdio.h"
  5. #include "spi.h"
  6. #include "app_freertos.h"
  7.     }
  8. #endif
  9. extern SPI_HandleTypeDef hspi1;
  10. extern __IO uint32_t wTransferState;

  11. #include <touchgfx/hal/OSWrappers.hpp>
2、修改屏幕刷新函数如下:
  1. void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect)
  2. {
  3.     TouchGFXGeneratedHAL::flushFrameBuffer(rect);
  4.     volatile uint16_t* buffer = getClientFrameBuffer()+(rect.y*LCD_WIDTH)+rect.x;
  5.     lcd_set_address(rect.x, rect.y, rect.x+rect.width-1, rect.y+rect.height-1);
  6.     lcd_write_ram();
  7.     hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
  8.     HAL_SPI_Init(&hspi1);
  9.     LCD_CS(0);
  10.     LCD_WR(1);
  11.     for(uint32_t i=0; i<rect.height; i++)
  12.     {
  13.         HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)buffer, rect.width);
  14.         while(wTransferState != TRANSFER_COMPLETE)
  15.         {
  16.             //osDelay(1); // 使用RTOS延迟代替空循环
  17.         }
  18.         wTransferState = TRANSFER_WAIT;
  19.         buffer += LCD_WIDTH;
  20.     }
  21.     hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  22.     HAL_SPI_Init(&hspi1);
  23. }
添加同步函数如下:
  1. extern "C"
  2. void touchgfxSignalVSync(void)
  3. {
  4.     HAL::getInstance()->vSync();
  5.     OSWrappers::signalVSync();
  6.     HAL::getInstance()->swapFrameBuffers();
  7. }
在spi.c中添加spi-GPDMA回调函数,代码如下:

  1. /* USER CODE BEGIN 1 */
  2. __IO uint32_t wTransferState = TRANSFER_WAIT;
  3. void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
  4. {
  5.   /* Turn LED2 on: Transfer in transmission/reception process is complete */

  6.   wTransferState = TRANSFER_COMPLETE;

  7. }

  8. void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
  9. {
  10.   wTransferState = TRANSFER_ERROR;
  11. }
  12. /* USER CODE END 1 */
在main.c中的定时器回函数中添加代码如下:
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  2. {
  3.   /* USER CODE BEGIN Callback 0 */

  4.   /* USER CODE END Callback 0 */
  5.   if (htim->Instance == TIM15)
  6.   {
  7.     HAL_IncTick();
  8.   }
  9.   /* USER CODE BEGIN Callback 1 */
  10.   if (htim->Instance == TIM6)
  11.   {
  12.     touchgfxSignalVSync();
  13.   }
  14.   /* USER CODE END Callback 1 */
  15. }
同时添加lcd的初始化代码,并开启定时器:
  1.   /* USER CODE BEGIN 2 */
  2.   HAL_TIM_Base_Start_IT(&htim6);
  3.   HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);
  4.   lcd_init();
  5.   /* USER CODE END 2 */
【添加gt911与toucgfx的适配】
在STM32TouchController.cpp中添加对头文件的引用:
  1. #ifdef __cplusplus
  2.     extern "C"{
  3. #include "gt911.h"
  4.     }
  5. #endif
  6. extern Touch_Struct User_Touch;
添加gt911初始化与触摸获取代码如下:
  1. void STM32TouchController::init()
  2. {
  3.     GTP_Init();
  4. }

  5. bool STM32TouchController::sampleTouch(int32_t& x, int32_t& y)
  6. {
  7.     if ((GTP_INT_GPIO_PORT->IDR & GTP_RST_GPIO_PIN) != 0x00U)
  8.     {
  9.         return false;
  10.     }
  11.     GTXXXX_Scanf();
  12.     if (User_Touch.Touch_State == 0x80)
  13.     {

  14.         x = User_Touch.Touch_XY[0].X_Point;
  15.         y = User_Touch.Touch_XY[0].Y_Point;
  16.         User_Touch.Touch_State = 0;
  17.         User_Touch.Touch_Number = 0;
  18.         return true;
  19.     }
  20.     return false;

  21. }
到此全部代码移植完毕。
【结果】
编译下载到开发板后效果如下:
67556873396789757.png
【总结】
1、stm32提供了非常友好的图形化界面配置,配置外设非常简单,特别是整合了freertos、touchgfx这么大的工程。
2、本次的工程使用到的GPIO、USART、I2C、SPI、TIM、GPDMA外设,整合为TouchGFX提供了硬件支持。特别是SPI可以通过GPDMA进行16bit的高带宽的数据传输为TouchGFX提供了强大的硬件支持。
3、注意事项,在移植过程中,需要注意以下几点:
一、为SYS提供心跳支持的TIM15需要手工调整中断级别,以免在freertos还没有正常工作时,由于得不到中断权限卡死在HAL_Delay中。
二、FreeRTOS的内存空间需要尽可能大,要不在创建TouchGFX任务时会出现失败。
三、由于U385的内存空间是分为两个区间的,需要手工调整一下链接文件对内存的分配。以免出现内存不足的现象。
四、由于CLion下载后,不能自动重启,在下载后,需要手工复位开发板。


小小蚂蚁举千斤 发表于 2025-7-28 23:23 | 显示全部楼层
移植TouchGFX了解一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

180

主题

830

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部