This is continuing from part 1 of tutorial.
We prepared everything in previous tutorial now let’s initialize the display and write our simple “Hello world!”
We need to put following inside USER CODE 2 in main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* USER CODE BEGIN 2 */ /* LCD Initialization */ BSP_LCD_Init(); BSP_LCD_LayerDefaultInit(0, LCD_FB_START_ADDRESS); /* Enable the LCD */ BSP_LCD_DisplayOn(); /* Select the LCD Background Layer */ BSP_LCD_SelectLayer(0); /* Clear the Background Layer */ BSP_LCD_Clear(LCD_COLOR_BLACK); /* Some sign */ BSP_LCD_SetTextColor(LCD_COLOR_RED); BSP_LCD_SetFont(&Font12); BSP_LCD_DisplayStringAt(0, 0, (uint8_t*) "Hello world!", CENTER_MODE); /* USER CODE END 2 */ |
Now we need to compile this and program our board.
For the first time we need to right click on project name in Project Explorer and select Run As -> 1 Ac6 STM32 C/C++ Application
It will program and run our application and on display you should see nice Hello world!
Now we know that everything works and we should move on to STEmWin 🙂
First we need to make a few directories inside our project:
1 2 3 |
$Project_Name/GUI $Project_Name/GUI/inc $Project_Name/GUI/lib |
Copy all .h files from ‘$Library_path\STM32Cube_FW_F7_VX.X.X\Middlewares\ST\STemWin\inc\’ to GUI/inc folder inside project.
Copy file ‘$Library_path\STM32Cube_FW_F7_VX.X.X\Middlewares\ST\STemWin\Lib\STemWin532_CM7_GCC.a’ to folder GUI\lib iside our project. This is a precompiled library for EmWin from Segger.
Next we need to add this library to our project. We do this in project properties under C/C++ General -> Libraries -> Add… and write ‘:STemWin532_CM7_GCC.a’ It is important to just write this not input link to this file!
Note: While I was writing this tutorial the number of this file changed from 528 to 532. There might be some settings as 528 and some like 532 in this tutorial. Just use latest for everything and it will be ok.
We also need to tell the compiler path to this library, we do this under Project Properties -> C/C++ General -> Library Paths -> Add…
Enter ‘GUI/Lib‘
We also need to copy file GUIConf.c from ‘$Library_path\STM32Cube_FW_F7_VX.X.X\Middlewares\ST\STemWin\Config\’ to folder ‘src‘ inside root of our project. In this file we provide EmWin with memory for functioning.
We need to change line 65 to:
1 2 3 4 5 6 7 8 9 10 |
/********************************************************************* * * Defines * ********************************************************************** */ // // Define the available number of bytes available for the GUI // #define GUI_NUMBYTES (1024*150) |
We also need to copy file GUIConf.h from $Library_path\STM32Cube_FW_F7_VX.X.X\Middlewares\ST\STemWin\Config\ to folder \Inc’ in root of our project.
Next we need to copy file $Library_path\STM32Cube_FW_F7_VX.X.X\Middlewares\ST\STemWin\OS\GUI_X.c to folder ‘\Src’ in root of our project.
We need to add a few more include directories in our include list:
1 2 3 |
GUI GUI\inc GUI\lib |
Inside ‘inc’ folder in root of our project is ‘main.h’ file. We need to add this lines of code inside it:
1 2 3 4 5 |
/* USER CODE BEGIN Includes */ #include "stm32746g_discovery_lcd.h" //BSP #include "GUI.h" //STEmWin #include "WM.h" //STEmWin /* USER CODE END Includes */ |
This include of stm32746g_discovery_lcd.h makes a lot of errors which I have some workaround to solve, but I am not sure what causes them, but I will explain how to get rid of them.
In my case first error is something like: “…stm32746g_discovery_sdram.h:128:1: error: unknown type name ‘uint8_t’ “. It seems that linker doesn’t have the correct sequence of include files so it does not understand uint8_t type of number yet. We correct this by including stdint.h in stm32746g_discovery_sdram.h.
1 2 3 4 5 6 7 8 9 10 11 |
/* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32746G_DISCOVERY_SDRAM_H #define __STM32746G_DISCOVERY_SDRAM_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32f7xx_hal.h" #include <stdint.h> <-- add this line |
After this is done, all the rest of errors are like “stm32746g_discovery.h:316:41: error: unknown type name ‘UART_HandleTypeDef’ ” each of them is missing some kind of type name.
To correct this there are a few steps needed for each of them and a few times after we solve one error there are more errors than before, but ultimately every error is solved.
Let’s take a look at first one: “stm32746g_discovery_sdram.h:135:27: error: unknown type name ‘FMC_SDRAM_CommandTypeDef’ “:
First we double click on the error to see where it is.
Next we right click on the missing type, in this case FMC_SDRAM_CommandTypeDef and select Open Declaration. This opens the file in which this type is defined. In our case it is stm32f7xx_ll_fmc.h.
This means that we need to include stm32f7xx_ll_fmc.h inside stm32746g_discovery_sdram.h:
1 2 3 4 5 6 7 8 9 10 11 |
#ifndef __STM32746G_DISCOVERY_SDRAM_H #define __STM32746G_DISCOVERY_SDRAM_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32f7xx_hal.h" #include <stdint.h> #include "stm32f7xx_ll_fmc.h" <-- we added this one |
If we try to compile now, we see that error is gone, but there are a lot still remaining. Let’s remove another one so that you will understand what to do:
Next one is “stm32746g_discovery_sdram.h:141:27: error: unknown type name ‘SDRAM_HandleTypeDef’ “
We double click on it and see it is still in the same file as before, but if we right click on it and select Open Declaration we noe see that this one is defined inside stm32f7xx_hl_sdram.h. So we include another file inside stm32746g_discovery_sdram.h:
1 2 3 4 5 6 7 8 9 10 11 12 |
#ifndef __STM32746G_DISCOVERY_SDRAM_H #define __STM32746G_DISCOVERY_SDRAM_H #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "stm32f7xx_hal.h" #include <stdint.h> #include "stm32f7xx_ll_fmc.h" #include "stm32f7xx_hal_sdram.h" <-- we added this one now |
We continue this way until all of the type errors are gone… If someone knows better solution to this I would be very happy if they would let me know how to properly solve this!!!
After solving all of the errors we continue with the tutorial.
We need some kind of time base. We need to increment OS_TimeMS each milisecond and for this we will use SysTick Timer.
We start in ‘$Project_name\Src\stm32f7xx_it.c’ which takes care of interrupts and exceptions. In here is a function:
1 2 3 4 5 |
void SysTick_Handler(void) { ... HAL_SYSTICK_IRQHandler(); } |
which is executed each millisecond. This one calls another function:
1 2 3 4 |
void HAL_SYSTICK_IRQHandler(void) { HAL_SYSTICK_Callback(); } |
This one also calls another “__weak” function:
1 2 3 4 5 6 |
__weak void HAL_SYSTICK_Callback(void) { /* NOTE : This function Should not be modified, when the callback is needed, the HAL_SYSTICK_Callback could be implemented in the user file */ } |
__weak means that if compiler needs function with this name it uses __weak function unless there is strong (non __weak) function defined.
We will be making strong function inside main:
1 2 3 4 5 6 7 8 |
/* USER CODE BEGIN PFP */ /* Private function prototypes -----------------------------------------------*/ extern volatile GUI_TIMER_TIME OS_TimeMS; void HAL_SYSTICK_Callback(void) { OS_TimeMS++; } /* USER CODE END PFP */ |
And this function will increment OS_TimeMS each millisecond.
Now we need driver for display. We can make our own or we can just copy it from example, which we will do.
We need to copy ‘LCDConf.c‘ from ‘$Library_path\STM32Cube_FW_F7_VX.X.X\Projects\STM32746G-Discovery\Applications\STemWin\STemWin_HelloWorld\Src\’ to /src folder under root of our project.
and we need to copy ‘LCDConf.h‘ from ‘$Library_path\STM32Cube_FW_F7_VX.X.X\Projects\STM32746G-Discovery\Applications\STemWin\STemWin_HelloWorld\Inc\’ to /inc folder under root of our project.
To get rid of a few errors we need to comment a few lines of code inside ‘Src/stm32f7xx_hal_msp.c‘:
1 2 3 4 |
void HAL_DMA2D_MspInit(DMA2D_HandleTypeDef* hdma2d) //lines 132-147 void HAL_DMA2D_MspDeInit(DMA2D_HandleTypeDef* hdma2d) //lines 149-164 void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc) //lines 261-350 void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef* hltdc) //lines 352-414 these line numbers change from version to version!!! |
You might get an error like main.c:105: undefined reference to `OS_TimeMS’ this means that You forgot to copy GUI_X.c.
All we need to do now is to test if it works. We need to change code between /* USER CODE BEGIN 2 */ and /* USER CODE END 2 */:
1 2 3 4 5 6 7 8 9 10 |
/* USER CODE BEGIN 2 */ BSP_SDRAM_Init(); /* Initializes the SDRAM device */ __HAL_RCC_CRC_CLK_ENABLE() ; GUI_Init(); GUI_Clear(); GUI_SetFont(&GUI_Font20_1); GUI_SetColor(GUI_RED); GUI_DispString("Hello world!"); /* USER CODE END 2 */ |
I changed GUI_SetColor to dark gray so that I could get better picture with my camera. And here is the result you should get on display: *Don’t use GUI_SetColor with version 1.8.0, there looks like there is some bug somewhere and it doesn’t work! Solved the problem! We need to add single line at the end of GUI_Conf.h, #define GUI_USE_ARGB (0) :
1 2 3 4 5 6 7 8 9 10 11 |
/********************************************************************* * * Configuration of available packages */ #define GUI_SUPPORT_MOUSE (1) /* Support a mouse */ #define GUI_WINSUPPORT (1) /* Use window manager */ #define GUI_SUPPORT_MEMDEV (1) /* Memory device package available */ #define GUI_SUPPORT_DEVICES (1) /* Enable use of device pointers */ #define GUI_USE_ARGB (0) /* The color format to use is ARGB */ #endif /* Avoid multiple inclusion */ |
This concludes this tutorial! And here is the link for part 3.
Hey, first let me thank you for this great tutorial. I was never able to work around all this include issues, till now. I understand now what the error message would like to tell me ;-).
I followed all your instructions and they worked just fine, until i tried to use GUI_Init();. After inserting this into the code, it “explode”. I get the errormessage
“TouchTest.elf section “.bss” will not fit in region “RAM”
region “RAM” overflowed by 1775856 bytes
I am using STemWin540_CM7_GCC.a.
Do you know how to work around this?
I’m quite new at STemWin and don’t really use it much. I searched internet and this might be your solution. If not, please let me know.
Thank you for your comment!
Thanks for your answer, that would might have been a solution. But i managed to work around this problem otherwise. I just got rid of all that GUI stuff, cause i just needed the touch-functionalty. The graphical stuff i do by myself. But i have some trouble with the ltdc-layers. I draw something on layer1 while layer 2 is displayed.
Then i switch layers (layer1 is displayes, and layer2 is drawn on), and while switching layers, there happen a “flicker”, and since i switch several times a second, i get a heavily flickery display. I guess i am using the layers kind of wrong….
I wish I had the knowledge to help you. If you only need touch from STemWin, you might just use touch alone and not use STEmWin at all.
Had the same problem, because I forgot to change “#define GUI_NUMBYTES (1024*150)”, now it builds and “Hello world” in od the LCD.
Maybe it helps.
No problem. If I find a solution, i will post it here. Or is there a better place?
Yes you can post it here. I will add it to the article above. Thank You!
Finally i had a little time this weekend, to work arround the flickering issue. It seems that simply changing the transparency of a layer from 255 to 0 and the other layer from 0 to 255 works fine. So the solution is to not enable and dissable the layers, simply make them disapear in the transparancy.
greetings
I am happy you did it! Thank you for letting us know!
Regards!