[STM32U3] 【STM32U385RG 测评】移植TouchGFX
本文详细介绍了基于STM32U385RG开发板的TouchGFX移植过程,重点构建了一个门禁控制系统。作者使用STM32CubeMX配置外设(SPI、I2C、TIM等)和FreeRTOS操作系统,通过TouchGFX Designer设计GUI界面。关键步骤包括:LCD驱动(ST7789)和触摸屏(GT911)的移植、SPI DMA传输优化、内存分配调整(将heap移至RAM2区解决内存不足问题)
非常感谢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的基础工程。

2、配置主时钟为96MHz

3、配置sys的时基为TIM15

为了移植FreeRTOS后,出现HAL_Delay卡死,修改TIM15的中断级别为1:

4、配置USART1为日志输出,根据原理图,IO使用PA9、PA10,波特率为115200。


5、配置操作系统为FreeRTOS,内存管理为heap_4

修改Heap Size、Stack Size为0x2000

使能CMISIS RTOS2:

6、打开ICHACE
7、为了使用TouchGFX,打开CRC
到此基础的工程已经移植好了。
【移植TouchGFX】
移植touchgGFX需要驱动带触摸的LCD屏,TFT为st7789、触摸为GT911
1、使用SPI1来驱动LCD屏,同时还需要指定CS、DC、RST三个IO,定义IO如下:
/*LCD_PWR:PB10LCD_RST:PC6LCD_WR: PC7LCD_CS: PC9LCD_SCK PA1LCD_SDA PA7*/
在stm32cubeMX配置如下:

特别注意一点是SCK必须配置为上拉,并且速度需要设置为very high。

传输数据宽度为8bit,时钟极性为空闲是高电平,第二个时钟沿采样。
为了提高传输效率,给SPI1的TX配置GPDMA

为CH0配置为SPI1_TX,传输为从内存到外设,地址为自动增长,为了更高效的传输,传宽宽为Half Word即为16bit宽度。
打开spi以及GPDMA中断

2、配置PC6、PC7、PC9为普通输出。用于LCD的CS、RST、DC。

3、配置GT911,GT911使用I2C2,同时还需要配置RST与INT
/*//引脚图:SDA--PB13SCL--PB14INT--PC8RST--PB5*/


触摸屏配置到这里结束了。
【背光控制】
为了可以实现背光控制,启用TIM2_CH3为PWM输出,配置为2K的输出:

同时还需要添加一个定时器6,为touchgGFX提供一个20ms心跳。

到此外设配置结束
【TouchGFX】
打开cube-touchGFX


配置为自定义外设,宽长为240*320
实时操作系统为FreeRTOS V2
添加一个任务如下:

最后在工程中生成CMake的工程:

【创建touchGFX基础界面】
使用TouchGFX Designer在创建的工程中添加一个空白GUI添加界面如下:

生成代码后,使用Clion打开工程项目文件夹
【配置编译工具】
打开工程后,配置编工具链如下:

然后选择此工具链:

点击确定,打开工程。CMake会自动配置工程。
编译后成功生成工程:

看到RAM占用达到95%,因此需要把heap放到第二个内存区域,修改链接文件如下:
._user_heap_stack :{. = ALIGN(8);PROVIDE ( end = . );PROVIDE ( _end = . );. = . + _Min_Heap_Size;. = . + _Min_Stack_Size;. = ALIGN(8);} >RAM2
重新编译后点用内存如下:
[89/89] Linking CXX executable 21ic_touchGFX.elfMemory region Used Size Region Size %age UsedRAM: 170420 B 192 KB 86.68%RAM2: 16 KB 64 KB 25.00%FLASH: 305288 B 1 MB 29.11%
【移植lcd驱动】
将st7789与GT911的驱动添加到工程中。

将工程选项添加进CMakeLists.txt中

在lcd中配置spi写入字节的函数:
/**************************************************************函数名称 : sp1_write_byte函数功能 : SPI1 写一个字节输入参数 : w_data:要写入的字节,size:写入字节大小返回值 : 0 --> 写入成功,其他 --> 写入失败备注 : 无**************************************************************/uint8_t sp1_write_byte(uint8_t *r_data, uint16_t size){return HAL_SPI_Transmit(&hspi1, r_data, size, 1000);}
【区配置touchgfx显示】
1、打开TouchGFXHAL.cpp中在顶部添加代码如下:
#ifdef __cplusplusextern "C"{#include "lcd.h"#include "stdio.h"#include "spi.h"#include "app_freertos.h"}#endifextern SPI_HandleTypeDef hspi1;extern __IO uint32_t wTransferState;#include <touchgfx/hal/OSWrappers.hpp>
2、修改屏幕刷新函数如下:
void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect){TouchGFXGeneratedHAL::flushFrameBuffer(rect);volatile uint16_t* buffer = getClientFrameBuffer()+(rect.y*LCD_WIDTH)+rect.x;lcd_set_address(rect.x, rect.y, rect.x+rect.width-1, rect.y+rect.height-1);lcd_write_ram();hspi1.Init.DataSize = SPI_DATASIZE_16BIT;HAL_SPI_Init(&hspi1);LCD_CS(0);LCD_WR(1);for(uint32_t i=0; i<rect.height; i++){HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)buffer, rect.width);while(wTransferState != TRANSFER_COMPLETE){//osDelay(1); // 使用RTOS延迟代替空循环}wTransferState = TRANSFER_WAIT;buffer += LCD_WIDTH;}hspi1.Init.DataSize = SPI_DATASIZE_8BIT;HAL_SPI_Init(&hspi1);}
添加同步函数如下:
extern "C"void touchgfxSignalVSync(void){HAL::getInstance()->vSync();OSWrappers::signalVSync();HAL::getInstance()->swapFrameBuffers();}
在spi.c中添加spi-GPDMA回调函数,代码如下:
/* USER CODE BEGIN 1 */__IO uint32_t wTransferState = TRANSFER_WAIT;void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi){/* Turn LED2 on: Transfer in transmission/reception process is complete */wTransferState = TRANSFER_COMPLETE;}void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi){wTransferState = TRANSFER_ERROR;}/* USER CODE END 1 */
在main.c中的定时器回函数中添加代码如下:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){/* USER CODE BEGIN Callback 0 *//* USER CODE END Callback 0 */if (htim->Instance == TIM15){HAL_IncTick();}/* USER CODE BEGIN Callback 1 */if (htim->Instance == TIM6){touchgfxSignalVSync();}/* USER CODE END Callback 1 */}
同时添加lcd的初始化代码,并开启定时器:
/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(&htim6);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);lcd_init();/* USER CODE END 2 */
【添加gt911与toucgfx的适配】
在STM32TouchController.cpp中添加对头文件的引用:
#ifdef __cplusplusextern "C"{#include "gt911.h"}#endifextern Touch_Struct User_Touch;
添加gt911初始化与触摸获取代码如下:
void STM32TouchController::init(){GTP_Init();}bool STM32TouchController::sampleTouch(int32_t& x, int32_t& y){if ((GTP_INT_GPIO_PORT->IDR & GTP_RST_GPIO_PIN) != 0x00U){return false;}GTXXXX_Scanf();if (User_Touch.Touch_State == 0x80){x = User_Touch.Touch_XY[0].X_Point;y = User_Touch.Touch_XY[0].Y_Point;User_Touch.Touch_State = 0;User_Touch.Touch_Number = 0;return true;}return false;}
到此全部代码移植完毕。
【结果】
编译下载到开发板后效果如下:

【总结】
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下载后,不能自动重启,在下载后,需要手工复位开发板。





























。
---------------------
作者:lulugl
链接:https://bbs.21ic.com/icview-3470090-1-1.html?_dsign=70debd4e
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)