非常感谢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如下:

复制

 
  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配置如下:
 


特别注意一点是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

复制

 
  1. /*
  2. //引脚图:
  3. SDA--PB13
  4. SCL--PB14
  5. INT--PC8
  6. RST--PB5
  7. */



 


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

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


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


 


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


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


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


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


然后选择此工具链:
 


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


看到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的驱动添加到工程中。
 


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


在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. }

到此全部代码移植完毕。
【结果】
编译下载到开发板后效果如下:
 


【总结】
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所有,任何人未经允许禁止转载。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐