2025-10-27 7:28 AM - edited 2025-11-07 12:26 AM
Hello all
Do we knoiw for the example like ( https://support.touchgfx.com/docs/development/scenarios/running-graphics-from-external-ram ) but for the STM32H750B-DK board where the bigger LCD is used?
Any comments are more than welcome!
Best.
2025-12-11 2:30 AM
Hello @total_and_STM32.
Could you please elaborate on what your question is?
If you are looking for examples on how to integrate a larger display with the STM32H750B-DK, I would recommend you to first of all have a look at the TouchGFX Board Setup (TBS) available in TouchGFX Designer for the STM32H750B-DK. Assuming the larger display also uses a parallel RGB interface, it should be fairly straightforward to configure it by modifying the LTDC settings in STM32CubeMX.
Best regards,
Johan
2025-12-11 3:12 AM
Thanks for your reply,
It looks very promising, thank you again!
For fun, have a look at what I am going through https://community.st.com/t5/stm32-mcus-touchgfx-and-gui/touch-gfx-and-custom-lcd/td-p/861733 since this information was not known to me :) need to review the actual TouchGFX Board setup as described here https://support.touchgfx.com/docs/development/scenarios/scenarios-create-at
This information should pop up the first thing when someone opens the Touch GFX documentation :)
Anyway, thanks!!! Fingers crossed, this will help me set up
Best.
2025-12-11 4:03 AM
I do not think you can use that documentation link in your current state. The procedure described there is for later, when your board setup is running and you want to e.g. distribute it or base multiple GUI projects on the same hardware setup.
What I am referring to are the TBSs that are available in TouchGFX Designer under the "Create" tab.
These are complete TouchGFX board setups for some of the graphics-relevant evaluation boards. They are open source and can be used as a reference when developing board setups for custom hardware.
Best regards,
Johan
2025-12-11 4:40 AM - edited 2025-12-11 4:51 AM
OK! Thanks!
So, when "the project" is created in the TouchGFX designer for the STM32H750b-dk, how can it then be opened in the CUBE IDE, or CUBE MX, where the LTDC is set up for the custom LCD?
Is this the idea, or is the resolution, etc. of the display defined within the TouchGFX Designer?
So far, I cannot define the dimension nor the color depth while the display orientation can be determined, see below.
Best.
2025-12-12 2:47 AM - edited 2025-12-12 5:22 AM
Managed to open the relevant file from the Touch GFX project folder, opened the *.ioc, set the setting in the MX, as well opened the Designer to check about the settings... it looks like that is it, however, the preview on the display is not normal, either with the cache CPU ICache and DChache enabled / disabled,
Anyway, I am wondering why I cannot sort out the general preview via TouchGFX and LTDC settings. For example, a basic setup to test the working of the LCD was achieved with the following code and little program in the uVision, before hand ExtBootloader was used..., so, the connections, namely GPIOs , LTDC is working properly. It seems this driver is used: "stm32h750b_discovery_lcd.c", for example it can be found here:
Attaching the code, maybe we can use some information to help us out with regard to the Touch GFX?
#include "main.h"
#include "stm32h7xx_hal.h"
#include <stdio.h> // to use the "printf"
#include "stdbool.h"
//#include "core_cm3.h"
#include "stm32h7xx_hal_gpio.h"
#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/* Private define ------------------------------------------------------------*/
#define CIRCLE_RADIUS 40
#define LINE_LENGHT 30
//LCD_FRAME_BUFFER ÔÚmain.h
/* Private macro -------------------------------------------------------------*/
#define CIRCLE_XPOS(i) ((i * 1024) / 7)
#define CIRCLE_YPOS(i) (600 - CIRCLE_RADIUS - 200)
#define CIRCLE_1_XPOS(i) ((i * 1024) / 7)
#define CIRCLE_1_YPOS(i) (600 - CIRCLE_RADIUS - 400)
#define LCD_BRIGHT GPIO_PK0
/* Private variables ---------------------------------------------------------*/
//LCD-touch?
TS_Init_t hTS;
TS_State_t TS_State;
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void MPU_Config(void);
static void Error_Handler(void);
static void OnError_Handler(uint32_t condition);
static void CPU_CACHE_Enable(void);
//extern UART_HandleTypeDef huart2; // Or huart3, depending on board schematic
void Touchscreen_DrawBackground_Circles(uint8_t state);
void Touch__demo(void);
/* Private functions ---------------------------------------------------------*/
uint8_t TxData[20]; //is this the "response", min length is 20bits ?
uint8_t RxData[20]; // to store the received data from slave!
int numDataBytes = 0; // variable to store how many bytes was received
uint8_t ID = 0; // the actuall ID sent by the master
int isDataValid = 0;
uint8_t Data[8];
int main(void)
{
/* Configure the MPU attributes as Write Through for SDRAM*/
MPU_Config();
/* Enable the CPU Cache */
CPU_CACHE_Enable();
/* STM32H7xx HAL library initialization:
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
HAL_Init();
//HAL_LIN_Init(); // how to actually use this?
/* Configure the system clock to 400 MHz */
SystemClock_Config();
/* Configure LED1 and LED2 */
BSP_LED_Init(LED1);
BSP_LED_Init(LED2);
/* Configure the User push-button in GPIO Mode */
BSP_PB_Init(BUTTON_USER, BUTTON_MODE_GPIO);
/* Proceed to LTDC and LCD screen initialization */
BSP_LCD_Init(0, LCD_ORIENTATION_LANDSCAPE);
UTIL_LCD_SetFuncDriver(&LCD_Driver);
UTIL_LCD_SetLayer(0); //we are working and displaying on leyer 0
/* Print example description */
UTIL_LCD_Clear(UTIL_LCD_COLOR_WHITE);
UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_BLACK);
UTIL_LCD_SetBackColor(UTIL_LCD_COLOR_WHITE);
UTIL_LCD_SetFont(&Font16); //Font16 /size!
UTIL_LCD_DisplayStringAt(150, 150, (uint8_t *)" TOUCH LCD ", CENTER_MODE);
UTIL_LCD_DisplayStringAt(CIRCLE_1_XPOS(0)+100, 220, (uint8_t *) "SEND DATA", 0);
UTIL_LCD_DisplayStringAt(CIRCLE_1_XPOS(0)+250, 220, (uint8_t *) "STOP SEND DATA", 0);
UTIL_LCD_DisplayStringAt(CIRCLE_XPOS(1)-55, 420, (uint8_t *)"OFF", 0);
UTIL_LCD_DisplayStringAt(CIRCLE_XPOS(2)-55, 420, (uint8_t *)"ON", 0);
UTIL_LCD_DisplayStringAt(CIRCLE_XPOS(3)-55, 420, (uint8_t *)"OFF", 0);
UTIL_LCD_DisplayStringAt(CIRCLE_XPOS(4)-55, 420, (uint8_t *)"ON", 0);
UTIL_LCD_DisplayStringAt(CIRCLE_XPOS(5)-55, 420, (uint8_t *)"OFF", 0);
UTIL_LCD_DisplayStringAt(CIRCLE_XPOS(6)-55, 420, (uint8_t *)"ON", 0);
HAL_Delay(100); // why are we waiting here?
//main app loop
while (1)
{
//printf("hello \n \r ");
Touch__LIN_demo(); //original, all functions
}
}
void USART1_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE(); // ¿ªÆô GPIOB ʱÖÓ
// PB6 -> USART1_TX, PB7 -> USART1_RX
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; //is this ok?
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //is this fpr the LCD or the LIN or the whole bank of GPIOs ?
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
// DEBUG
void UART2_Init(void)
{
__HAL_RCC_USART2_CLK_ENABLE(); // ¿ªÆô USART1 ʱÖÓ is this neccessary?
huart2.Instance = USART2;
huart2.Init.BaudRate = 9600; // max 192000
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
//dodajam
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT|UART_ADVFEATURE_DMADISABLEONERROR_INIT|UART_ADVFEATURE_AUTOBAUDRATE_INIT;
huart2.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;
huart2.AdvancedInit.DMADisableonRxError = UART_ADVFEATURE_DMA_DISABLEONRXERROR;
huart2.AdvancedInit.AutoBaudRateEnable = UART_ADVFEATURE_AUTOBAUDRATE_ENABLE;
huart2.AdvancedInit.AutoBaudRateMode = UART_ADVFEATURE_AUTOBAUDRATE_ON0X55FRAME;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
//dodajam
if (HAL_LIN_Init(&huart2, UART_LINBREAKDETECTLENGTH_10B) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
{
Error_Handler();
}
}
//LCD touch and circles...
void Touchscreen_DrawBackground_Circles(uint8_t state)
{
uint16_t x, y;
switch (state)
{
case 0:
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(1), CIRCLE_1_YPOS(1), CIRCLE_RADIUS, UTIL_LCD_COLOR_ORANGE);
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(2), CIRCLE_1_YPOS(2), CIRCLE_RADIUS, UTIL_LCD_COLOR_YELLOW);
UTIL_LCD_FillCircle(CIRCLE_XPOS(1), CIRCLE_YPOS(1), CIRCLE_RADIUS, UTIL_LCD_COLOR_BLUE);
UTIL_LCD_FillCircle(CIRCLE_XPOS(2), CIRCLE_YPOS(2), CIRCLE_RADIUS, UTIL_LCD_COLOR_RED);
UTIL_LCD_FillCircle(CIRCLE_XPOS(3), CIRCLE_YPOS(3), CIRCLE_RADIUS, UTIL_LCD_COLOR_YELLOW);
UTIL_LCD_FillCircle(CIRCLE_XPOS(4), CIRCLE_YPOS(3), CIRCLE_RADIUS, UTIL_LCD_COLOR_GREEN);
UTIL_LCD_FillCircle(CIRCLE_XPOS(5), CIRCLE_YPOS(5), CIRCLE_RADIUS, UTIL_LCD_COLOR_MAGENTA);
UTIL_LCD_FillCircle(CIRCLE_XPOS(6), CIRCLE_YPOS(6), CIRCLE_RADIUS, UTIL_LCD_COLOR_BLACK);
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(1), CIRCLE_1_YPOS(1), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(2), CIRCLE_1_YPOS(2), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
UTIL_LCD_FillCircle(CIRCLE_XPOS(1), CIRCLE_YPOS(1), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
UTIL_LCD_FillCircle(CIRCLE_XPOS(2), CIRCLE_YPOS(2), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
UTIL_LCD_FillCircle(CIRCLE_XPOS(3), CIRCLE_YPOS(3), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
UTIL_LCD_FillCircle(CIRCLE_XPOS(4), CIRCLE_YPOS(3), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
UTIL_LCD_FillCircle(CIRCLE_XPOS(5), CIRCLE_YPOS(5), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
UTIL_LCD_FillCircle(CIRCLE_XPOS(6), CIRCLE_YPOS(6), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
break;
//
case 1:
//EBL OFF
UTIL_LCD_FillCircle(CIRCLE_XPOS(1), CIRCLE_YPOS(1), CIRCLE_RADIUS, UTIL_LCD_COLOR_BLUE);
UTIL_LCD_FillCircle(CIRCLE_XPOS(1), CIRCLE_YPOS(1), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
//SEND DATA
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(1), CIRCLE_1_YPOS(1), CIRCLE_RADIUS, UTIL_LCD_COLOR_ORANGE);
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(1), CIRCLE_1_YPOS(1), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
//STOP SEND DATA
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(1), CIRCLE_1_YPOS(1), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_YELLOW);
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(1), CIRCLE_1_YPOS(1), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
break;
case 2:
UTIL_LCD_FillCircle(CIRCLE_XPOS(2), CIRCLE_YPOS(2), CIRCLE_RADIUS, UTIL_LCD_COLOR_RED);
UTIL_LCD_FillCircle(CIRCLE_XPOS(2), CIRCLE_YPOS(2), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(2), CIRCLE_1_YPOS(2), CIRCLE_RADIUS, UTIL_LCD_COLOR_ORANGE);
UTIL_LCD_FillCircle(CIRCLE_1_XPOS(2), CIRCLE_1_YPOS(2), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
break;
case 4:
UTIL_LCD_FillCircle(CIRCLE_XPOS(3), CIRCLE_YPOS(3), CIRCLE_RADIUS, UTIL_LCD_COLOR_YELLOW);
UTIL_LCD_FillCircle(CIRCLE_XPOS(3), CIRCLE_YPOS(3), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
break;
case 8:
UTIL_LCD_FillCircle(CIRCLE_XPOS(4), CIRCLE_YPOS(4), CIRCLE_RADIUS, UTIL_LCD_COLOR_GREEN);
UTIL_LCD_FillCircle(CIRCLE_XPOS(4), CIRCLE_YPOS(4), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
break;
case 16:
UTIL_LCD_FillCircle(CIRCLE_XPOS(5), CIRCLE_YPOS(5), CIRCLE_RADIUS, UTIL_LCD_COLOR_MAGENTA);
UTIL_LCD_FillCircle(CIRCLE_XPOS(5), CIRCLE_YPOS(5), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
break;
case 32:
UTIL_LCD_FillCircle(CIRCLE_XPOS(6), CIRCLE_YPOS(6), CIRCLE_RADIUS, UTIL_LCD_COLOR_BLACK);
UTIL_LCD_FillCircle(CIRCLE_XPOS(6), CIRCLE_YPOS(6), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
break;
// case 64:
// UTIL_LCD_FillCircle(CIRCLE_1_XPOS(1), CIRCLE_1_YPOS(1), CIRCLE_RADIUS, UTIL_LCD_COLOR_ORANGE);
// UTIL_LCD_FillCircle(CIRCLE_1_XPOS(1), CIRCLE_1_YPOS(1), CIRCLE_RADIUS - 2, UTIL_LCD_COLOR_WHITE);
// break;
}
}
// and so ON...