0.STM32F429使用STM32CUBMX5.6移植touchGFX4.13
1.使用MVP架构来实现GUI和硬件的双向交互
2.STM32F429移植TouchGFX到RT-Thread系统
实战:
3.STM32F767移植touchGFX—— 使用RT-Thread系统实现DIY数字仪表(正在进行)
4.STM32H747移植touchGFX—— 基于RT-Thread物联网系统实现AI图像识别(计划进行)
硬件: 野火挑战者STM32F429 V1开发版,5寸屏
软件: 最新版本的STM32CubeF4固件库,TouchGFXDesigner v4.13和 STM32CubeMX v5.6.1,开发环境MDK v5.29
1.准备一套STM32F429开发版,和下载工具
2.下载 TouchGFXDesigner v4.13
压缩包下载完后,解压如下:
Projects目录下有STM32H7B3I-DK的工程,可以用来参考。touchGFX Designer的PC端安装包在Utilities目录下,找到后并安装。
3.下载 STM32CubeMX v5.6.1
安装完STM32CubeMX v5.6.1版本后,还需要安装X_CUBE_TOUCHGFX软件包,安装路径如下:
4.下载 MDK v5.27以上版本
0d7235786fced5552aa3b1bd374b5697
代码持续更新中:github代码下载地址https://gitee.com/Aladdin-Wang/hellotouchGFX.git
觉得有用的话,欢迎打个小星星
关注公众号,加入技术交流群共同学习
打开…\board\CubeMX_Config\CubeMX_Config.ioc,由于bsp已经配置了很多外设,所以只需要修改部分配置就可以了
拷贝OSWrappers.cpp,重命名为OSWrappers_RTT.cpp文件
更改代码
/**
******************************************************************************
* File Name : OSWrappers.cpp
******************************************************************************
* @attention
*
* © Copyright (c) 2020 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
#include
#include
#include
#include
#include
#include
#include
static rt_sem_t frame_buffer_sem;
static rt_mq_t vsync_q = 0;
using namespace touchgfx;
// Just a dummy value to insert in the VSYNC queue.
static uint8_t dummy = 0x5a;
/*
* Initialize frame buffer semaphore and queue/mutex for VSYNC signal.
*/
void OSWrappers::initialize()
{
frame_buffer_sem = rt_sem_create("gfx_sem", 1, RT_IPC_FLAG_PRIO);
// Create a queue of length 1
vsync_q = rt_mq_create("gfx_mq", 1, 1, RT_IPC_FLAG_PRIO);
}
/*
* Take the frame buffer semaphore. Blocks until semaphore is available.
*/
void OSWrappers::takeFrameBufferSemaphore()
{
rt_sem_take(frame_buffer_sem, RT_WAITING_FOREVER);
}
/*
* Release the frame buffer semaphore.
*/
void OSWrappers::giveFrameBufferSemaphore()
{
rt_sem_release(frame_buffer_sem);
}
/*
* Attempt to obtain the frame buffer semaphore. If semaphore is not available, do
* nothing.
*
* Note must return immediately! This function does not care who has the taken the semaphore,
* it only serves to make sure that the semaphore is taken by someone.
*/
void OSWrappers::tryTakeFrameBufferSemaphore()
{
rt_sem_trytake(frame_buffer_sem);
}
/*
* Release the frame buffer semaphore in a way that is safe in interrupt context. Called
* from ISR.
*
* Release the frame buffer semaphore in a way that is safe in interrupt context.
* Called from ISR.
*/
void OSWrappers::giveFrameBufferSemaphoreFromISR()
{
// Since this is called from an interrupt, FreeRTOS requires special handling to trigger a
// re-scheduling. May be applicable for other OSes as well.
rt_sem_release(frame_buffer_sem);
}
/*
* Signal that a VSYNC has occurred. Should make the vsync queue/mutex available.
*
* Note This function is called from an ISR, and should (depending on OS) trigger a
* scheduling.
*/
void OSWrappers::signalVSync()
{
if (vsync_q)
{
rt_mq_send(vsync_q, &dummy, 1);
}
}
/*
* This function blocks until a VSYNC occurs.
*
* Note This function must first clear the mutex/queue and then wait for the next one to
* occur.
*/
void OSWrappers::waitForVSync()
{
// First make sure the queue is empty, by trying to remove an element with 0 timeout.
rt_mq_recv(vsync_q, &dummy, 1, 0);
// Then, wait for next VSYNC to occur.
rt_mq_recv(vsync_q, &dummy, 1, RT_WAITING_FOREVER);
}
/*
* A function that causes executing task to sleep for a number of milliseconds.
*
* A function that causes executing task to sleep for a number of milliseconds.
* This function is OPTIONAL. It is only used by the TouchGFX in the case of
* a specific frame refresh strategy (REFRESH_STRATEGY_OPTIM_SINGLE_BUFFER_TFT_CTRL).
* Due to backwards compatibility, in order for this function to be useable by the HAL
* the function must be explicitly registered:
* hal.registerTaskDelayFunction(&OSWrappers::taskDelay)
*
* see HAL::setFrameRefreshStrategy(FrameRefreshStrategy s)
* see HAL::registerTaskDelayFunction(void (*delayF)(uint16_t))
*/
void OSWrappers::taskDelay(uint16_t ms)
{
rt_thread_mdelay(ms);
}
static rt_base_t IdleTaskHook(void* p)
{
if ((int)p) //idle task sched out
{
touchgfx::HAL::getInstance()->setMCUActive(true);
}
else //idle task sched in
{
touchgfx::HAL::getInstance()->setMCUActive(false);
}
return RT_TRUE;
}
// FreeRTOS specific handlers
extern "C"
{
void vApplicationStackOverflowHook(rt_thread_t xTask,
signed char* pcTaskName)
{
while (1);
}
void vApplicationMallocFailedHook(rt_thread_t xTask,
signed char* pcTaskName)
{
while (1);
}
void vApplicationIdleHook(void)
{
// Set task tag in order to have the "IdleTaskHook" function called when the idle task is
// switched in/out. Used solely for measuring MCU load, and can be removed if MCU load
// readout is not needed.
//vTaskSetApplicationTaskTag(NULL, IdleTaskHook);
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
拷贝main.c的部分外设初始化代码到sample_touchgfx.c,示例代码如下:
#include
#include
#include
#include "app_touchgfx.h"
CRC_HandleTypeDef hcrc;
DMA2D_HandleTypeDef hdma2d;
LTDC_HandleTypeDef hltdc;
static void MX_CRC_Init(void);
static void MX_DMA2D_Init(void);
static void MX_LTDC_Init(void);
#define DISP_Pin GET_PIN(D, 4)
#define CTDL_BL_Pin GET_PIN(D, 7)
#define WIFI_Pin GET_PIN(G, 9)//野火开发板使用LCD需要关闭WIFI电源
/**
* @brief This function handles LTDC global interrupt.
*/
void LTDC_IRQHandler(void)
{
/* USER CODE BEGIN LTDC_IRQn 0 */
/* USER CODE END LTDC_IRQn 0 */
HAL_LTDC_IRQHandler(&hltdc);
/* USER CODE BEGIN LTDC_IRQn 1 */
/* USER CODE END LTDC_IRQn 1 */
}
/**
* @brief This function handles DMA2D global interrupt.
*/
void DMA2D_IRQHandler(void)
{
/* USER CODE BEGIN DMA2D_IRQn 0 */
/* USER CODE END DMA2D_IRQn 0 */
HAL_DMA2D_IRQHandler(&hdma2d);
/* USER CODE BEGIN DMA2D_IRQn 1 */
/* USER CODE END DMA2D_IRQn 1 */
}
/**
* @brief CRC Initialization Function
* @param None
* @retval None
*/
static void MX_CRC_Init(void)
{
/* USER CODE BEGIN CRC_Init 0 */
/* USER CODE END CRC_Init 0 */
/* USER CODE BEGIN CRC_Init 1 */
/* USER CODE END CRC_Init 1 */
hcrc.Instance = CRC;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CRC_Init 2 */
/* USER CODE END CRC_Init 2 */
}
/**
* @brief DMA2D Initialization Function
* @param None
* @retval None
*/
static void MX_DMA2D_Init(void)
{
/* USER CODE BEGIN DMA2D_Init 0 */
/* USER CODE END DMA2D_Init 0 */
/* USER CODE BEGIN DMA2D_Init 1 */
/* USER CODE END DMA2D_Init 1 */
hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_M2M;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
hdma2d.Init.OutputOffset = 0;
hdma2d.LayerCfg[1].InputOffset = 0;
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[1].InputAlpha = 0;
if (HAL_DMA2D_Init(&hdma2d) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN DMA2D_Init 2 */
/* USER CODE END DMA2D_Init 2 */
}
/**
* @brief LTDC Initialization Function
* @param None
* @retval None
*/
static void MX_LTDC_Init(void)
{
/* USER CODE BEGIN LTDC_Init 0 */
/* USER CODE END LTDC_Init 0 */
LTDC_LayerCfgTypeDef pLayerCfg = {0};
/* USER CODE BEGIN LTDC_Init 1 */
/* USER CODE END LTDC_Init 1 */
hltdc.Instance = LTDC;
hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;
hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;
hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;
hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
hltdc.Init.HorizontalSync = 0;
hltdc.Init.VerticalSync = 0;
hltdc.Init.AccumulatedHBP = 46;
hltdc.Init.AccumulatedVBP = 23;
hltdc.Init.AccumulatedActiveW = 846;
hltdc.Init.AccumulatedActiveH = 503;
hltdc.Init.TotalWidth = 866;
hltdc.Init.TotalHeigh = 525;
hltdc.Init.Backcolor.Blue = 0;
hltdc.Init.Backcolor.Green = 0;
hltdc.Init.Backcolor.Red = 0;
if (HAL_LTDC_Init(&hltdc) != HAL_OK)
{
Error_Handler();
}
pLayerCfg.WindowX0 = 0;
pLayerCfg.WindowX1 = 800;
pLayerCfg.WindowY0 = 0;
pLayerCfg.WindowY1 = 480;
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;
pLayerCfg.Alpha = 255;
pLayerCfg.Alpha0 = 0;
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
pLayerCfg.FBStartAdress = 0xd0000000;
pLayerCfg.ImageWidth = 800;
pLayerCfg.ImageHeight = 480;
pLayerCfg.Backcolor.Blue = 255;
pLayerCfg.Backcolor.Green = 255;
pLayerCfg.Backcolor.Red = 255;
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN LTDC_Init 2 */
rt_pin_mode(DISP_Pin, PIN_MODE_OUTPUT);
rt_pin_mode(CTDL_BL_Pin, PIN_MODE_OUTPUT);
rt_pin_mode(WIFI_Pin, PIN_MODE_OUTPUT);
rt_pin_write(DISP_Pin, 1);
rt_pin_write(CTDL_BL_Pin, 1);
rt_pin_write(WIFI_Pin, 0);
/* USER CODE END LTDC_Init 2 */
}
void touchgfx_thread_entry(void *parameter)
{
MX_CRC_Init();
MX_DMA2D_Init();
MX_LTDC_Init();
MX_TouchGFX_Init();
MX_TouchGFX_Process();
for(;;)
{
rt_thread_mdelay(100);
}
}
int TouchGFXTask(void)
{
rt_thread_t tid = NULL;
tid = rt_thread_create("TouchGFX",
touchgfx_thread_entry, RT_NULL,
4096, 15, 20);
if (tid != RT_NULL)
rt_thread_startup(tid);
else
return -1;
return RT_EOK;
}
INIT_APP_EXPORT(TouchGFXTask);
import os
import rtconfig
from building import *
cwd = GetCurrentDir()
# add general drivers
src = Split('''
Src/sample_touchgfx.c
Src/OSWrappers_RTT.cpp
Src/STM32DMA.cpp
Src/STM32TouchController.cpp
Src/TouchGFXGPIO.cpp
Src/TouchGFXConfiguration.cpp
Src/TouchGFXGeneratedHAL.cpp
Src/TouchGFXHAL.cpp
Src/app_touchgfx.c
''')
path = [cwd + '/Src']
path += [cwd + '/Middlewares/ST/touchgfx/framework/include']
if rtconfig.CROSS_TOOL == 'gcc':
src += [cwd + '/Middlewares/ST/touchgfx/lib/core/cortex_m4f/gcc/libtouchgfx.a']
elif rtconfig.CROSS_TOOL == 'keil':
src += [cwd + '/Middlewares/ST/touchgfx/lib/core/cortex_m4f/Keil/touchgfx_core.lib']
elif rtconfig.CROSS_TOOL == 'iar':
src += [cwd + '/Middlewares/ST/touchgfx/lib/core/cortex_m4f/IAR8.x/touchgfx_core.a']
group = DefineGroup('TouchGFX_app', src, depend = [''], CPPPATH = path)
# add TouchGFX generated
genSrc = Glob('./Src/generated/fonts/src/*.cpp')
genSrc += Glob('./Src/generated/gui_generated/src/*/*.cpp')
genSrc += Glob('./Src/generated/images/src/*.cpp')
genSrc += Glob('./Src/generated/texts/src/*.cpp')
genPath = [cwd + '/Src/generated/fonts/include']
genPath += [cwd + '/Src/generated/gui_generated/include']
genPath += [cwd + '/Src/generated/images/include']
genPath += [cwd + '/Src/generated/texts/include']
group = group + DefineGroup('TouchGFX_generated', genSrc, depend = [''], CPPPATH = genPath)
# add TouchGFX resource
resSrc = Glob('./Src/generated/images/src/*/*.cpp')
group = group + DefineGroup('TouchGFX_resource', resSrc, depend = [''])
# add TouchGFX gui
guiSrc = Glob('./Src/gui/src/*/*.cpp')
guiPath = [cwd + '/Src/gui/include']
group = group + DefineGroup('TouchGFX_gui', guiSrc, depend = [''], CPPPATH = guiPath)
Return('group')
添加如下代码:
if GetDepend(['BSP_USING_TouchGFX']):
src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c']
src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c']
src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c']
src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c']
src += ['STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c']
使用scons --target=mdk5 命令生成 MDK工程。此时还不能编译下载,因为图片资源太大,会超过内部flash的存储空间,还需要把图片下载到外部flash,上电初始化通过spi把图片资源加载到SDRAM。
配置fal_cfg.h,
tgfx分区用于touchgfx的资源存储,其他分区用于OTA、文件系统和系统参数配置。
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-05-17 armink the first version
*/
#ifndef _FAL_CFG_H_
#define _FAL_CFG_H_
#include
#include
#define FLASH_SIZE_GRANULARITY_16K (4 * 16 * 1024)
#define FLASH_SIZE_GRANULARITY_64K (64 * 1024)
#define FLASH_SIZE_GRANULARITY_128K (7 * 128 * 1024)
#define STM32_FLASH_START_ADRESS_16K STM32_FLASH_START_ADRESS
#define STM32_FLASH_START_ADRESS_64K (STM32_FLASH_START_ADRESS_16K + FLASH_SIZE_GRANULARITY_16K)
#define STM32_FLASH_START_ADRESS_128K (STM32_FLASH_START_ADRESS_64K + FLASH_SIZE_GRANULARITY_64K)
/* ===================== Flash device Configuration ========================= */
extern const struct fal_flash_dev stm32_onchip_flash_16k;
extern const struct fal_flash_dev stm32_onchip_flash_64k;
extern const struct fal_flash_dev stm32_onchip_flash_128k;
extern struct fal_flash_dev nor_flash0;
/* flash device table */
#define FAL_FLASH_DEV_TABLE \
{ \
&stm32_onchip_flash_16k, \
&stm32_onchip_flash_64k, \
&stm32_onchip_flash_128k, \
&nor_flash0, \
}
/* ====================== Partition Configuration ========================== */
#ifdef FAL_PART_HAS_TABLE_CFG
/* partition table */
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WROD, "bootloader", "onchip_flash_16k", 0 , FLASH_SIZE_GRANULARITY_16K , 0}, \
{FAL_PART_MAGIC_WROD, "ef", "onchip_flash_64k", 0 , FLASH_SIZE_GRANULARITY_64K , 0}, \
{FAL_PART_MAGIC_WROD, "app", "onchip_flash_128k", 0 , FLASH_SIZE_GRANULARITY_128K, 0}, \
{FAL_PART_MAGIC_WROD, "tgfx", "W25Q128", 0 , 4 * 1024 * 1024, 0}, \
{FAL_PART_MAGIC_WROD, "download", "W25Q128", 4 * 1024 * 1024 , 1024 * 1024, 0}, \
{FAL_PART_MAGIC_WROD, "factory", "W25Q128", (4 * 1024 + 1024) * 1024 , 1024 * 1024, 0}, \
{FAL_PART_MAGIC_WROD, "filesystem", "W25Q128", (4 * 1024 + 1024 + 1024) * 1024 , 2 * 1024 * 1024, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
#endif /* _FAL_CFG_H_ */
初始化fal
int fs_init(void)
{
/* partition initialized */
fal_init();
return 0;
}
INIT_COMPONENT_EXPORT(fs_init);
配置模拟I2C
在applications文件夹下新建gtxx_ccollect.c文件,添加一下内容
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-06-01 tyustli the first version
*/
#include
#include "gt9147.h"
#define DBG_TAG "gt9147"
#define DBG_LVL DBG_LOG
#include
#define THREAD_PRIORITY 5
#define THREAD_STACK_SIZE 1024
#define THREAD_TIMESLICE 5
#define GT9147_RST_PIN 59
#define GT9147_IRQ_PIN 61
static rt_thread_t gt9147_thread = RT_NULL;
static rt_sem_t gt9147_sem = RT_NULL;
static rt_device_t dev = RT_NULL;
static struct rt_touch_data *read_data;
static struct rt_touch_info info;
struct rt_touch_data *read_coordinate(void)
{
return &read_data[0];
}
static void gt9147_entry(void *parameter)
{
rt_device_control(dev, RT_TOUCH_CTRL_GET_INFO, &info);
read_data = (struct rt_touch_data *)rt_malloc(sizeof(struct rt_touch_data) * info.point_num);
while (1)
{
rt_sem_take(gt9147_sem, RT_WAITING_FOREVER);
if (rt_device_read(dev, 0, read_data, info.point_num) == info.point_num)
{
for (rt_uint8_t i = 0; i < info.point_num; i++)
{
if (read_data[i].event == RT_TOUCH_EVENT_DOWN || read_data[i].event == RT_TOUCH_EVENT_MOVE)
{
LOG_D("%d %d %d %d %d\n", read_data[i].track_id,
read_data[i].x_coordinate,
read_data[i].y_coordinate,
read_data[i].timestamp,
read_data[i].width);
}
}
}
rt_device_control(dev, RT_TOUCH_CTRL_ENABLE_INT, RT_NULL);
}
}
static rt_err_t rx_callback(rt_device_t dev, rt_size_t size)
{
rt_sem_release(gt9147_sem);
rt_device_control(dev, RT_TOUCH_CTRL_DISABLE_INT, RT_NULL);
return 0;
}
static int rt_hw_gt9147_port(void)
{
struct rt_touch_config config;
rt_uint8_t rst;
rst = GT9147_RST_PIN;
config.dev_name = "i2c1";
config.irq_pin.pin = GT9147_IRQ_PIN;
config.irq_pin.mode = PIN_MODE_INPUT_PULLDOWN;
config.user_data = &rst;
rt_hw_gt9147_init("gt", &config);
return 0;
}
/* Test function */
int gt9147_init(void)
{
void *id;
rt_hw_gt9147_port();
dev = rt_device_find("gt");
if (dev == RT_NULL)
{
rt_kprintf("can't find device gt\n");
return -1;
}
if (rt_device_open(dev, RT_DEVICE_FLAG_INT_RX) != RT_EOK)
{
rt_kprintf("open device failed!");
return -1;
}
id = rt_malloc(sizeof(rt_uint8_t) * 8);
rt_device_control(dev, RT_TOUCH_CTRL_GET_ID, id);
rt_uint8_t * read_id = (rt_uint8_t *)id;
rt_kprintf("id = %c %c %c %c \n", read_id[0], read_id[1], read_id[2], read_id[3]);
rt_device_control(dev, RT_TOUCH_CTRL_GET_INFO, id);
rt_kprintf("range_x = %d \n", (*(struct rt_touch_info*)id).range_x);
rt_kprintf("range_y = %d \n", (*(struct rt_touch_info*)id).range_y);
rt_kprintf("point_num = %d \n", (*(struct rt_touch_info*)id).point_num);
rt_free(id);
rt_device_set_rx_indicate(dev, rx_callback);
gt9147_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO);
if (gt9147_sem == RT_NULL)
{
rt_kprintf("create dynamic semaphore failed.\n");
return -1;
}
gt9147_thread = rt_thread_create("gt9147",
gt9147_entry,
RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY,
THREAD_TIMESLICE);
if (gt9147_thread != RT_NULL)
rt_thread_startup(gt9147_thread);
return 0;
}
INIT_APP_EXPORT(gt9147_init);
修改STM32TouchController.cpp
/**
******************************************************************************
* File Name : STM32TouchController.cpp
******************************************************************************
* @attention
*
* © Copyright (c) 2020 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE BEGIN STM32TouchController */
#include
#include "gt9147.h"
extern "C"
{
struct rt_touch_data *read_coordinate(void);
}
void STM32TouchController::init()
{
/**
* Initialize touch controller and driver
*
*/
}
bool STM32TouchController::sampleTouch(int32_t& x, int32_t& y)
{
/**
* By default sampleTouch returns false,
* return true if a touch has been detected, otherwise false.
*
* Coordinates are passed to the caller by reference by x and y.
*
* This function is called by the TouchGFX framework.
* By default sampleTouch is called every tick, this can be adjusted by HAL::setTouchSampleRate(int8_t);
*
*/
struct rt_touch_data *read_data;
read_data = read_coordinate();
if (read_data->event == RT_TOUCH_EVENT_DOWN || read_data->event == RT_TOUCH_EVENT_MOVE)
{
x = read_data->x_coordinate;
y = read_data->y_coordinate;
return true;
}
else
{
return false;
}
}
/* USER CODE END STM32TouchController */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/